1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 60c312b8eSJed Brown #include <petscsf.h> 7e228b242SToby Isaac #include <petscds.h> 8e412dcbdSMatthew G. Knepley #include <petscdraw.h> 9f19dbd58SToby Isaac #include <petscdmfield.h> 10012bc364SMatthew G. Knepley #include <petscdmplextransform.h> 11552f7358SJed Brown 12552f7358SJed Brown /* Logging support */ 1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad; 14172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate; 15552f7358SJed Brown 16*f39ec787SMatthew G. Knepley PetscBool Plexcite = PETSC_FALSE; 17*f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n" 18*f39ec787SMatthew G. Knepley "title = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n" 19*f39ec787SMatthew G. Knepley "author = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n" 20*f39ec787SMatthew G. Knepley "journal = {SIAM Journal on Scientific Computing},\n" 21*f39ec787SMatthew G. Knepley "volume = {38},\n" 22*f39ec787SMatthew G. Knepley "number = {5},\n" 23*f39ec787SMatthew G. Knepley "pages = {S143--S155},\n" 24*f39ec787SMatthew G. Knepley "eprint = {http://arxiv.org/abs/1506.07749},\n" 25*f39ec787SMatthew G. Knepley "doi = {10.1137/15M1026092},\n" 26*f39ec787SMatthew G. Knepley "year = {2016},\n" 27*f39ec787SMatthew G. Knepley "petsc_uses={DMPlex},\n}\n"; 28*f39ec787SMatthew G. Knepley 295a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 30552f7358SJed Brown 31e5337592SStefano Zampini /*@ 329318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 339318fe57SMatthew G. Knepley 349318fe57SMatthew G. Knepley Input Parameter: 35a1cb98faSBarry Smith . dm - The `DMPLEX` object 369318fe57SMatthew G. Knepley 379318fe57SMatthew G. Knepley Output Parameter: 389318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 399318fe57SMatthew G. Knepley 409318fe57SMatthew G. Knepley Level: intermediate 419318fe57SMatthew G. Knepley 42a1cb98faSBarry Smith Note: 43a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 44a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 45a1cb98faSBarry Smith 461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 479318fe57SMatthew G. Knepley @*/ 48d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 49d71ae5a4SJacob Faibussowitsch { 509318fe57SMatthew G. Knepley DMPolytopeType ct; 519318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 529318fe57SMatthew G. Knepley 539318fe57SMatthew G. Knepley PetscFunctionBegin; 549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 559371c9d4SSatish Balay if (cEnd <= cStart) { 569371c9d4SSatish Balay *simplex = PETSC_FALSE; 573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 589371c9d4SSatish Balay } 599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 609318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 629318fe57SMatthew G. Knepley } 639318fe57SMatthew G. Knepley 649318fe57SMatthew G. Knepley /*@ 65412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 66e5337592SStefano Zampini 67d8d19677SJose E. Roman Input Parameters: 68a1cb98faSBarry Smith + dm - The `DMPLEX` object 69412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 70e5337592SStefano Zampini 71e5337592SStefano Zampini Output Parameters: 72412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 73412e9a14SMatthew G. Knepley - cEnd - The upper bound on "normal"" cells 74e5337592SStefano Zampini 75412e9a14SMatthew G. Knepley Level: developer 76e5337592SStefano Zampini 77a1cb98faSBarry Smith Note: 78a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 79a1cb98faSBarry Smith 802827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()` 81e5337592SStefano Zampini @*/ 82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 83d71ae5a4SJacob Faibussowitsch { 84412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 85412e9a14SMatthew G. Knepley PetscInt cS, cE, c; 86e5337592SStefano Zampini 87e5337592SStefano Zampini PetscFunctionBegin; 889566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE)); 89412e9a14SMatthew G. Knepley for (c = cS; c < cE; ++c) { 90412e9a14SMatthew G. Knepley DMPolytopeType cct; 91412e9a14SMatthew G. Knepley 929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &cct)); 93412e9a14SMatthew G. Knepley if ((PetscInt)cct < 0) break; 94412e9a14SMatthew G. Knepley switch (cct) { 95ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 96ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 97ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 98ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 99ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 100d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 101d71ae5a4SJacob Faibussowitsch ct = cct; 102d71ae5a4SJacob Faibussowitsch break; 103d71ae5a4SJacob Faibussowitsch default: 104d71ae5a4SJacob Faibussowitsch break; 105e5337592SStefano Zampini } 106412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) break; 107e5337592SStefano Zampini } 108412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) { 109412e9a14SMatthew G. Knepley DMLabel ctLabel; 110412e9a14SMatthew G. Knepley 1119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 1129566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE)); 113695799ffSMatthew G. Knepley // Reset label for fast lookup 114695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 115e5337592SStefano Zampini } 116412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 117412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 1183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119e5337592SStefano Zampini } 120e5337592SStefano Zampini 121d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 122d71ae5a4SJacob Faibussowitsch { 123412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 124a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 1257e42fee7SMatthew G. Knepley 1267e42fee7SMatthew G. Knepley PetscFunctionBegin; 127e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 1289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1309566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 1319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1327e42fee7SMatthew G. Knepley if (field >= 0) { 1339566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 1349566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 1357e42fee7SMatthew G. Knepley } else { 1369566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 1379566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 1387e42fee7SMatthew G. Knepley } 139712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 140a99a26bcSAdrian Croucher if (globalvcdof[0]) { 1417e42fee7SMatthew G. Knepley *sStart = vStart; 1427e42fee7SMatthew G. Knepley *sEnd = vEnd; 143f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 1447e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 145a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 1467e42fee7SMatthew G. Knepley *sStart = cStart; 1477e42fee7SMatthew G. Knepley *sEnd = cEnd; 148f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 1497e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 150e630c359SToby Isaac } else { 151e630c359SToby Isaac if (field >= 0) { 152e630c359SToby Isaac const char *fieldname; 153e630c359SToby Isaac 1549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 15563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 156e630c359SToby Isaac } else { 15763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 158e630c359SToby Isaac } 159e630c359SToby Isaac } 1603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1617e42fee7SMatthew G. Knepley } 1627e42fee7SMatthew G. Knepley 1636913077dSMatthew G. Knepley /*@ 1646913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 1656913077dSMatthew G. Knepley 16620f4b53cSBarry Smith Collective 1676913077dSMatthew G. Knepley 1686913077dSMatthew G. Knepley Input Parameters: 169a1cb98faSBarry Smith + dm - The `DMPLEX` object 1706913077dSMatthew G. Knepley . n - The number of vectors 1716913077dSMatthew G. Knepley . u - The array of local vectors 172a1cb98faSBarry Smith - viewer - The `PetscViewer` 1736913077dSMatthew G. Knepley 1746913077dSMatthew G. Knepley Level: advanced 1756913077dSMatthew G. Knepley 1761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 1776913077dSMatthew G. Knepley @*/ 178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 179d71ae5a4SJacob Faibussowitsch { 1806913077dSMatthew G. Knepley PetscDS ds; 1816913077dSMatthew G. Knepley PetscDraw draw = NULL; 1826913077dSMatthew G. Knepley PetscDrawLG lg; 1836913077dSMatthew G. Knepley Vec coordinates; 1846913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 1856913077dSMatthew G. Knepley PetscReal *vals; 1866913077dSMatthew G. Knepley PetscInt *Nc; 1876913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 1886913077dSMatthew G. Knepley char **names; 1896913077dSMatthew G. Knepley 1906913077dSMatthew G. Knepley PetscFunctionBegin; 1919566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 1929566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 1939566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 1949566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 1956913077dSMatthew G. Knepley 1969566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 1973ba16761SJacob Faibussowitsch if (!draw) PetscFunctionReturn(PETSC_SUCCESS); 1989566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 1996913077dSMatthew G. Knepley 2009566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 2016913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 2026913077dSMatthew G. Knepley const char *vname; 2036913077dSMatthew G. Knepley 2049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 2056913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 2066913077dSMatthew G. Knepley PetscObject disc; 2076913077dSMatthew G. Knepley const char *fname; 2086913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 2096913077dSMatthew G. Knepley 2109566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 2116913077dSMatthew G. Knepley /* TODO Create names for components */ 2126913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 2139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 214c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname))); 215c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname))); 216c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname))); 2179566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 2186913077dSMatthew G. Knepley } 2196913077dSMatthew G. Knepley } 2206913077dSMatthew G. Knepley } 2219566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 2226913077dSMatthew G. Knepley /* Just add P_1 support for now */ 2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2249566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2259566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 2269566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 2276913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 2286913077dSMatthew G. Knepley PetscScalar *x, *svals; 2296913077dSMatthew G. Knepley 2309566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 2316913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 2329566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 2336913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 2346913077dSMatthew G. Knepley } 2359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 2366913077dSMatthew G. Knepley } 2379566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 2389566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 2399566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 2409566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 2416913077dSMatthew G. Knepley 2429566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 2439566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 2443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2456913077dSMatthew G. Knepley } 2466913077dSMatthew G. Knepley 247d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 248d71ae5a4SJacob Faibussowitsch { 2496913077dSMatthew G. Knepley DM dm; 2506913077dSMatthew G. Knepley 2516913077dSMatthew G. Knepley PetscFunctionBegin; 2529566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 2539566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 2543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2556913077dSMatthew G. Knepley } 2566913077dSMatthew G. Knepley 257d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 258d71ae5a4SJacob Faibussowitsch { 259e412dcbdSMatthew G. Knepley DM dm; 260d1df6f1dSMatthew G. Knepley PetscSection s; 261e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 262e412dcbdSMatthew G. Knepley DM cdm; 263e412dcbdSMatthew G. Knepley PetscSection coordSection; 264e412dcbdSMatthew G. Knepley Vec coordinates; 265c9c77995SMatthew G. Knepley const PetscScalar *array; 266c9c77995SMatthew G. Knepley PetscReal lbound[3], ubound[3]; 267339e3443SMatthew G. Knepley PetscReal vbound[2], time; 2686913077dSMatthew G. Knepley PetscBool flg; 269d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 270e412dcbdSMatthew G. Knepley const char *name; 271339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 272e412dcbdSMatthew G. Knepley 273e412dcbdSMatthew G. Knepley PetscFunctionBegin; 2749566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2759566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 2769566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 2779566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 2789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 2799566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 2809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 2819566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 2829566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2849566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 285e412dcbdSMatthew G. Knepley 2869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 2879566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 288e412dcbdSMatthew G. Knepley 2899566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 290c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lbound, ubound)); 2919566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 292e412dcbdSMatthew G. Knepley 293d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 294d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 295d1df6f1dSMatthew G. Knepley DM fdm = dm; 296d1df6f1dSMatthew G. Knepley Vec fv = v; 297d1df6f1dSMatthew G. Knepley IS fis; 298d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 299d1df6f1dSMatthew G. Knepley const char *fname; 300d1df6f1dSMatthew G. Knepley 3019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 3029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 303d1df6f1dSMatthew G. Knepley 3049566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 305ad540459SPierre Jolivet else prefix[0] = '\0'; 306d1df6f1dSMatthew G. Knepley if (Nf > 1) { 3079566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 3089566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 3099566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 3109566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 311d1df6f1dSMatthew G. Knepley } 312d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 313d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 314d1df6f1dSMatthew G. Knepley 3159566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 31663a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 31763a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 3189566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 319d1df6f1dSMatthew G. Knepley 320d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 3219566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 322339e3443SMatthew G. Knepley if (!flg) { 3239566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 3249566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 325d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 326339e3443SMatthew G. Knepley } 327c9c77995SMatthew G. Knepley 3289566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 3299566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 330c9c77995SMatthew G. Knepley PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1])); 3319566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 332e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 33399a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 334c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 335c9c77995SMatthew G. Knepley PetscBool isDG; 336e56f9228SJed Brown PetscInt numCoords, color[4] = {-1, -1, -1, -1}; 337e412dcbdSMatthew G. Knepley 3389566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 339339e3443SMatthew G. Knepley if (a) { 340d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 341339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 342339e3443SMatthew G. Knepley } else { 343339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 344339e3443SMatthew G. Knepley PetscInt numVals, va; 345339e3443SMatthew G. Knepley 3469566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 34763a3b9bcSJacob 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); 348d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 349d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 350d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 351d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 352339e3443SMatthew G. Knepley break; 353d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 354d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 355d1df6f1dSMatthew 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]); 356d1df6f1dSMatthew G. Knepley break; 357d71ae5a4SJacob Faibussowitsch default: 358d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 359339e3443SMatthew G. Knepley } 3609566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 361339e3443SMatthew G. Knepley } 362c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 363e412dcbdSMatthew G. Knepley switch (numCoords) { 364e412dcbdSMatthew G. Knepley case 6: 3659edc3542SMatthew Knepley case 12: /* Localized triangle */ 3669566063dSJacob 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])); 367e412dcbdSMatthew G. Knepley break; 368e412dcbdSMatthew G. Knepley case 8: 3699edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 3709566063dSJacob 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])); 3719566063dSJacob 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])); 372e412dcbdSMatthew G. Knepley break; 373d71ae5a4SJacob Faibussowitsch default: 374d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 375e412dcbdSMatthew G. Knepley } 376c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 377e412dcbdSMatthew G. Knepley } 3789566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 3799566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 3809566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 3819566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 382d1df6f1dSMatthew G. Knepley } 383d1df6f1dSMatthew G. Knepley if (Nf > 1) { 3849566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 3859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 3869566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 387d1df6f1dSMatthew G. Knepley } 388d1df6f1dSMatthew G. Knepley } 3893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 390e412dcbdSMatthew G. Knepley } 391e412dcbdSMatthew G. Knepley 392d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 393d71ae5a4SJacob Faibussowitsch { 3946913077dSMatthew G. Knepley DM dm; 3956913077dSMatthew G. Knepley PetscDraw draw; 3966913077dSMatthew G. Knepley PetscInt dim; 3976913077dSMatthew G. Knepley PetscBool isnull; 3986913077dSMatthew G. Knepley 3996913077dSMatthew G. Knepley PetscFunctionBegin; 4009566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4019566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 4023ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 4036913077dSMatthew G. Knepley 4049566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 4066913077dSMatthew G. Knepley switch (dim) { 407d71ae5a4SJacob Faibussowitsch case 1: 408d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 409d71ae5a4SJacob Faibussowitsch break; 410d71ae5a4SJacob Faibussowitsch case 2: 411d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 412d71ae5a4SJacob Faibussowitsch break; 413d71ae5a4SJacob Faibussowitsch default: 414d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 4156913077dSMatthew G. Knepley } 4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4176913077dSMatthew G. Knepley } 4186913077dSMatthew G. Knepley 419d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 420d71ae5a4SJacob Faibussowitsch { 421684b87d9SLisandro Dalcin DM dm; 422684b87d9SLisandro Dalcin Vec locv; 423684b87d9SLisandro Dalcin const char *name; 424684b87d9SLisandro Dalcin PetscSection section; 425684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 426e630c359SToby Isaac PetscInt numFields; 427684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 428684b87d9SLisandro Dalcin 429684b87d9SLisandro Dalcin PetscFunctionBegin; 4309566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4319566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 4329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 4339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 4349566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4359566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 4369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 437e630c359SToby Isaac if (!numFields) { 4389566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 4399566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 440e630c359SToby Isaac } else { 441e630c359SToby Isaac PetscInt f; 442e630c359SToby Isaac 443e630c359SToby Isaac for (f = 0; f < numFields; f++) { 4449566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 445e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 4469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 4479566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 448e630c359SToby Isaac } 4499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 450e630c359SToby Isaac } 4513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 452684b87d9SLisandro Dalcin } 453684b87d9SLisandro Dalcin 454d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 455d71ae5a4SJacob Faibussowitsch { 456552f7358SJed Brown DM dm; 4575f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 458552f7358SJed Brown 459552f7358SJed Brown PetscFunctionBegin; 4609566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 46128b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 4629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 4639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 4649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 4659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 4665f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 4675f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 468684b87d9SLisandro Dalcin PetscInt i, numFields; 469684b87d9SLisandro Dalcin PetscObject fe; 470ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 471684b87d9SLisandro Dalcin Vec locv = v; 472684b87d9SLisandro Dalcin const char *name; 473684b87d9SLisandro Dalcin PetscInt step; 474684b87d9SLisandro Dalcin PetscReal time; 475ef31f671SMatthew G. Knepley 4769566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 477684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 4789566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 4799371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 4809371c9d4SSatish Balay fem = PETSC_TRUE; 4819371c9d4SSatish Balay break; 4829371c9d4SSatish Balay } 483ef31f671SMatthew G. Knepley } 484684b87d9SLisandro Dalcin if (fem) { 485798534f6SMatthew G. Knepley PetscObject isZero; 486798534f6SMatthew G. Knepley 4879566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 4889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 4899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 4909566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 4919566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 4929566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4939566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 4949566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 495ef31f671SMatthew G. Knepley } 496552f7358SJed Brown if (isvtk) { 4979566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 498b136c2c9SMatthew G. Knepley } else if (ishdf5) { 499b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5009566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 501b136c2c9SMatthew G. Knepley #else 502b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 503b136c2c9SMatthew G. Knepley #endif 504f13a32a3SMatthew G. Knepley } else if (isdraw) { 5059566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 506684b87d9SLisandro Dalcin } else if (isglvis) { 5079566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 5089566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 5099566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 5105f34f2dcSJed Brown } else if (iscgns) { 5115f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 5125f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 5135f34f2dcSJed Brown #else 5145f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 5155f34f2dcSJed Brown #endif 516684b87d9SLisandro Dalcin } 517798534f6SMatthew G. Knepley if (fem) { 5189566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 5199566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 520798534f6SMatthew G. Knepley } 521552f7358SJed Brown } else { 522684b87d9SLisandro Dalcin PetscBool isseq; 523684b87d9SLisandro Dalcin 5249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 5259566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5269566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 527552f7358SJed Brown } 5283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 529552f7358SJed Brown } 530552f7358SJed Brown 531d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 532d71ae5a4SJacob Faibussowitsch { 533552f7358SJed Brown DM dm; 5345f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 535552f7358SJed Brown 536552f7358SJed Brown PetscFunctionBegin; 5379566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 53828b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5429566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5435f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 5455f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 546552f7358SJed Brown Vec locv; 547798534f6SMatthew G. Knepley PetscObject isZero; 548552f7358SJed Brown const char *name; 549552f7358SJed Brown 5509566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5519566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5529566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5539566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 5549566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 5559566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 5569566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 5579566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 5599566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 560b136c2c9SMatthew G. Knepley } else if (ishdf5) { 561b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5629566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 563b136c2c9SMatthew G. Knepley #else 564b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 565b136c2c9SMatthew G. Knepley #endif 5666823f3c5SBlaise Bourdin } else if (isexodusii) { 5676823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 5689566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 5696823f3c5SBlaise Bourdin #else 5706823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 5716823f3c5SBlaise Bourdin #endif 572552f7358SJed Brown } else { 573684b87d9SLisandro Dalcin PetscBool isseq; 574684b87d9SLisandro Dalcin 5759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 5769566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5779566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 578552f7358SJed Brown } 5793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 580552f7358SJed Brown } 581552f7358SJed Brown 582d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 583d71ae5a4SJacob Faibussowitsch { 584d930f514SMatthew G. Knepley DM dm; 585d930f514SMatthew G. Knepley MPI_Comm comm; 586d930f514SMatthew G. Knepley PetscViewerFormat format; 587d930f514SMatthew G. Knepley Vec v; 588d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 589d930f514SMatthew G. Knepley 590d930f514SMatthew G. Knepley PetscFunctionBegin; 5919566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 5929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 59328b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5949566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 5959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5969566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 597d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 598a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 599a8ad634aSStefano Zampini /* this need a better fix */ 600a8ad634aSStefano Zampini if (dm->useNatural) { 601a8ad634aSStefano Zampini if (dm->sfNatural) { 602d930f514SMatthew G. Knepley const char *vecname; 603d930f514SMatthew G. Knepley PetscInt n, nroots; 604d930f514SMatthew G. Knepley 6059566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 6069566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 607d930f514SMatthew G. Knepley if (n == nroots) { 608f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 6099566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 6109566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 6119566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 6129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 613d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 614d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 615a8ad634aSStefano Zampini } else v = originalv; 616a8ad634aSStefano Zampini } else v = originalv; 617a8ad634aSStefano Zampini 618d930f514SMatthew G. Knepley if (ishdf5) { 619d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6209566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 621d930f514SMatthew G. Knepley #else 622d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 623d930f514SMatthew G. Knepley #endif 624d930f514SMatthew G. Knepley } else if (isvtk) { 625d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 626d930f514SMatthew G. Knepley } else { 627d930f514SMatthew G. Knepley PetscBool isseq; 628d930f514SMatthew G. Knepley 6299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6309566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6319566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 632d930f514SMatthew G. Knepley } 633f16a8b29SMatthew G. Knepley if (v != originalv) PetscCall(VecDestroy(&v)); 6343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 635d930f514SMatthew G. Knepley } 636d930f514SMatthew G. Knepley 637d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 638d71ae5a4SJacob Faibussowitsch { 6392c40f234SMatthew G. Knepley DM dm; 6402c40f234SMatthew G. Knepley PetscBool ishdf5; 6412c40f234SMatthew G. Knepley 6422c40f234SMatthew G. Knepley PetscFunctionBegin; 6439566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 64428b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6462c40f234SMatthew G. Knepley if (ishdf5) { 6472c40f234SMatthew G. Knepley DM dmBC; 6482c40f234SMatthew G. Knepley Vec gv; 6492c40f234SMatthew G. Knepley const char *name; 6502c40f234SMatthew G. Knepley 6519566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 6529566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 6539566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6549566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 6559566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 6569566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 6579566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 6589566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 6591baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 6603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6612c40f234SMatthew G. Knepley } 6622c40f234SMatthew G. Knepley 663d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 664d71ae5a4SJacob Faibussowitsch { 6652c40f234SMatthew G. Knepley DM dm; 6666823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 6672c40f234SMatthew G. Knepley 6682c40f234SMatthew G. Knepley PetscFunctionBegin; 6699566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 67028b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6732c40f234SMatthew G. Knepley if (ishdf5) { 674878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6759566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 676b136c2c9SMatthew G. Knepley #else 677b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 678878b459fSMatthew G. Knepley #endif 6796823f3c5SBlaise Bourdin } else if (isexodusii) { 6806823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6819566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 6826823f3c5SBlaise Bourdin #else 6836823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6846823f3c5SBlaise Bourdin #endif 6851baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 6863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 687552f7358SJed Brown } 688552f7358SJed Brown 689d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 690d71ae5a4SJacob Faibussowitsch { 691d930f514SMatthew G. Knepley DM dm; 692d930f514SMatthew G. Knepley PetscViewerFormat format; 693d930f514SMatthew G. Knepley PetscBool ishdf5; 694d930f514SMatthew G. Knepley 695d930f514SMatthew G. Knepley PetscFunctionBegin; 6969566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 69728b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6989566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 700d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 701a8ad634aSStefano Zampini if (dm->useNatural) { 702d930f514SMatthew G. Knepley if (dm->sfNatural) { 703d930f514SMatthew G. Knepley if (ishdf5) { 704d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 705d930f514SMatthew G. Knepley Vec v; 706d930f514SMatthew G. Knepley const char *vecname; 707d930f514SMatthew G. Knepley 708f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 7099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 7119566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 7129566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 7139566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 714f16a8b29SMatthew G. Knepley PetscCall(VecDestroy(&v)); 715d930f514SMatthew G. Knepley #else 716d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 717d930f514SMatthew G. Knepley #endif 718d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 719d930f514SMatthew G. Knepley } 7201baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 721d930f514SMatthew G. Knepley } 7223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 723d930f514SMatthew G. Knepley } 724d930f514SMatthew G. Knepley 725d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 726d71ae5a4SJacob Faibussowitsch { 727731e8ddeSMatthew G. Knepley PetscSection coordSection; 728731e8ddeSMatthew G. Knepley Vec coordinates; 729ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 730731e8ddeSMatthew G. Knepley const char *name[4]; 731731e8ddeSMatthew G. Knepley const PetscScalar *a; 732731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 733731e8ddeSMatthew G. Knepley 734731e8ddeSMatthew G. Knepley PetscFunctionBegin; 7359566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 7369566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 7379566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 7399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 7409566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 7419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 7429566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 743731e8ddeSMatthew G. Knepley name[0] = "vertex"; 744731e8ddeSMatthew G. Knepley name[1] = "edge"; 745731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 746731e8ddeSMatthew G. Knepley name[dim] = "cell"; 747731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 748731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 749ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 750731e8ddeSMatthew G. Knepley 7519566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 75263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 7539566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 755731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 756731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 757731e8ddeSMatthew G. Knepley 758731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 7599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 760731e8ddeSMatthew G. Knepley if (!dof) continue; 7619566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 7629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 76363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 764731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 7659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 766731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 7679566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 7689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 769731e8ddeSMatthew G. Knepley } 7709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 771731e8ddeSMatthew G. Knepley } 7729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 773731e8ddeSMatthew G. Knepley } 7749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 776731e8ddeSMatthew G. Knepley } 7779566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 7783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 779731e8ddeSMatthew G. Knepley } 780731e8ddeSMatthew G. Knepley 7819371c9d4SSatish Balay typedef enum { 7829371c9d4SSatish Balay CS_CARTESIAN, 7839371c9d4SSatish Balay CS_POLAR, 7849371c9d4SSatish Balay CS_CYLINDRICAL, 7859371c9d4SSatish Balay CS_SPHERICAL 7869371c9d4SSatish Balay } CoordSystem; 78719ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 78819ad8254SMatthew G. Knepley 789d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 790d71ae5a4SJacob Faibussowitsch { 79119ad8254SMatthew G. Knepley PetscInt i; 79219ad8254SMatthew G. Knepley 79319ad8254SMatthew G. Knepley PetscFunctionBegin; 79419ad8254SMatthew G. Knepley if (dim > 3) { 7959566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 79619ad8254SMatthew G. Knepley } else { 797bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 79819ad8254SMatthew G. Knepley 79919ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 80019ad8254SMatthew G. Knepley switch (cs) { 8019371c9d4SSatish Balay case CS_CARTESIAN: 8029371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 8039371c9d4SSatish Balay break; 80419ad8254SMatthew G. Knepley case CS_POLAR: 80563a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 80619ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 80719ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 80819ad8254SMatthew G. Knepley break; 80919ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 81063a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 81119ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 81219ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 81319ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 81419ad8254SMatthew G. Knepley break; 81519ad8254SMatthew G. Knepley case CS_SPHERICAL: 81663a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 81719ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 81819ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 81919ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 82019ad8254SMatthew G. Knepley break; 82119ad8254SMatthew G. Knepley } 8229566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 82319ad8254SMatthew G. Knepley } 8243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 82519ad8254SMatthew G. Knepley } 82619ad8254SMatthew G. Knepley 827d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 828d71ae5a4SJacob Faibussowitsch { 829552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8306858538eSMatthew G. Knepley DM cdm, cdmCell; 8316858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 8326858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 833552f7358SJed Brown PetscViewerFormat format; 834552f7358SJed Brown 835552f7358SJed Brown PetscFunctionBegin; 8369566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 837552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 838552f7358SJed Brown const char *name; 839f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 8409318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 841552f7358SJed Brown PetscMPIInt rank, size; 842552f7358SJed Brown 8439f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 8449f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8459f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8469f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 8479f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 8489f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 8499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 8519566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 8529566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8539566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 8549566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8559566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 85663a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 85763a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 85863a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 85963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 8609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 86163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 862552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 863552f7358SJed Brown PetscInt dof, off, s; 864552f7358SJed Brown 8659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 86748a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 868552f7358SJed Brown } 8699566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 87063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 87163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 872552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 873552f7358SJed Brown PetscInt dof, off, c; 874552f7358SJed Brown 8759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 8769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 87748a46eb9SPierre 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])); 878552f7358SJed Brown } 8799566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8813d2e540fSStefano Zampini if (coordSection && coordinates) { 88219ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 8836858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 8846858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 88519ad8254SMatthew G. Knepley PetscMPIInt rank; 88619ad8254SMatthew G. Knepley const char *name; 88719ad8254SMatthew G. Knepley 8889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 8899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 8909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 89163a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 8929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 8936858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 8946858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 8956858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 8966858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 8979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 89863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 89963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 9009566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 90119ad8254SMatthew G. Knepley 9029566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 9036858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 9049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 9059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 90619ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 90719ad8254SMatthew G. Knepley PetscInt dof, off; 90819ad8254SMatthew G. Knepley 9096858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 9109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 9119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 9126858538eSMatthew G. Knepley if (dof) { 91363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 9149566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 9159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 91619ad8254SMatthew G. Knepley } 9176858538eSMatthew G. Knepley } 9186858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 9196858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 9206858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 9216858538eSMatthew G. Knepley if (dof) { 9226858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 9236858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 9246858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 9256858538eSMatthew G. Knepley } 9266858538eSMatthew G. Knepley } 9276858538eSMatthew G. Knepley } 9289566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 9309566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 9316858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 9323d2e540fSStefano Zampini } 9339566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 9349566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 9359318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 9369318fe57SMatthew G. Knepley DMLabel label; 9379318fe57SMatthew G. Knepley PetscBool isdepth; 9389318fe57SMatthew G. Knepley const char *name; 9399318fe57SMatthew G. Knepley 9409566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 9419566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 9429318fe57SMatthew G. Knepley if (isdepth) continue; 9439566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 9449566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 9459318fe57SMatthew G. Knepley } 946552f7358SJed Brown if (size > 1) { 947552f7358SJed Brown PetscSF sf; 948552f7358SJed Brown 9499566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9509566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 951552f7358SJed Brown } 9524e2e9504SJed Brown if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer)); 9539566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 954552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 9550588280cSMatthew G. Knepley const char *name, *color; 9560588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 9570588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 958fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 959552f7358SJed Brown PetscReal scale = 2.0; 96078081901SStefano Zampini PetscReal tikzscale = 1.0; 961b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 9620588280cSMatthew G. Knepley double tcoords[3]; 963552f7358SJed Brown PetscScalar *coords; 964b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 965552f7358SJed Brown PetscMPIInt rank, size; 9660588280cSMatthew G. Knepley char **names, **colors, **lcolors; 967b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 968fe1cc32dSStefano Zampini PetscBT wp = NULL; 969fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 970552f7358SJed Brown 9719f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 9729f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9739f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9749f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 9759f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 9769f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 9779566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9799566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 9800588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 9810588280cSMatthew G. Knepley numColors = 10; 9820588280cSMatthew G. Knepley numLColors = 10; 9839566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 9849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 9859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 9869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 987b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 988b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 989b7f6ffafSMatthew G. Knepley n = 4; 9909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 9911dca8a05SBarry 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); 9929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 9931dca8a05SBarry 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); 9949566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 9950588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 9969566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 9970588280cSMatthew G. Knepley if (!useColors) { 9980588280cSMatthew G. Knepley numColors = 3; 9999566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 10000588280cSMatthew G. Knepley } 10019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 10020588280cSMatthew G. Knepley if (!useColors) { 10030588280cSMatthew G. Knepley numLColors = 4; 10049566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 10050588280cSMatthew G. Knepley } 10069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1007b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 10089566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 10091dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1010202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 10119566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1012fe1cc32dSStefano Zampini 1013fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 10149566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 10159566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 10169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 10179566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1018fe1cc32dSStefano Zampini if (lflg) { 1019fe1cc32dSStefano Zampini DMLabel lbl; 1020fe1cc32dSStefano Zampini 10219566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1022fe1cc32dSStefano Zampini if (lbl) { 1023fe1cc32dSStefano Zampini PetscInt val, defval; 1024fe1cc32dSStefano Zampini 10259566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 10269566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1027fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1028fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1029fe1cc32dSStefano Zampini PetscInt closureSize; 1030fe1cc32dSStefano Zampini 10319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1032fe1cc32dSStefano Zampini if (val == defval) continue; 1033fe1cc32dSStefano Zampini 10349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 103548a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 10369566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1037fe1cc32dSStefano Zampini } 1038fe1cc32dSStefano Zampini } 1039fe1cc32dSStefano Zampini } 1040fe1cc32dSStefano Zampini 10419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 10429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 10439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 10449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 10450588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1046552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1047552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1048552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 10495f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 10500588280cSMatthew G. Knepley if (size > 1) { 10519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1052770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 105363a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 105463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1055770b213bSMatthew G Knepley } 10569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 10570588280cSMatthew G. Knepley } 1058b7f6ffafSMatthew G. Knepley if (drawHasse) { 1059b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1060b7f6ffafSMatthew G. Knepley 106163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 106263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 106363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 10649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 106563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 106663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 10679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 106863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 106963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 107063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 107163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 10729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1073b7f6ffafSMatthew G. Knepley } 10749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1075fe1cc32dSStefano Zampini 1076552f7358SJed Brown /* Plot vertices */ 10779566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1079552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1080552f7358SJed Brown PetscInt off, dof, d; 10810588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1082552f7358SJed Brown 1083fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 10849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 10859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 10869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 108763a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 10880588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10890588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1090c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 10910588280cSMatthew G. Knepley } 10920588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 10939371c9d4SSatish Balay if (dim == 3) { 10949371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 10959371c9d4SSatish Balay tcoords[1] = tcoords[2]; 10969371c9d4SSatish Balay tcoords[2] = -tmp; 10979371c9d4SSatish Balay } 1098552f7358SJed Brown for (d = 0; d < dof; ++d) { 10999566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1101552f7358SJed Brown } 1102b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1103b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 11040588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 11050588280cSMatthew G. Knepley PetscInt val; 11069566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 11079371c9d4SSatish Balay if (val >= 0) { 11089371c9d4SSatish Balay color = lcolors[l % numLColors]; 11099371c9d4SSatish Balay isLabeled = PETSC_TRUE; 11109371c9d4SSatish Balay break; 11119371c9d4SSatish Balay } 11120588280cSMatthew G. Knepley } 1113b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 111463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1115b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 111663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 11171baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1118552f7358SJed Brown } 11199566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 11209566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1121b7f6ffafSMatthew G. Knepley /* Plot edges */ 1122b7f6ffafSMatthew G. Knepley if (plotEdges) { 11239566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 11249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1125b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1126b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1127b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1128b7f6ffafSMatthew G. Knepley 1129b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 11309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 113163a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 11329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 11339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 11349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 11359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 11369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1137b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1138b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1139b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1140b7f6ffafSMatthew G. Knepley } 1141b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 11429371c9d4SSatish Balay if (dim == 3) { 11439371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11449371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11459371c9d4SSatish Balay tcoords[2] = -tmp; 11469371c9d4SSatish Balay } 1147b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11489566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1150b7f6ffafSMatthew G. Knepley } 1151b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1152b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1153b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1154b7f6ffafSMatthew G. Knepley PetscInt val; 11559566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 11569371c9d4SSatish Balay if (val >= 0) { 11579371c9d4SSatish Balay color = lcolors[l % numLColors]; 11589371c9d4SSatish Balay break; 11599371c9d4SSatish Balay } 1160b7f6ffafSMatthew G. Knepley } 116163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1162b7f6ffafSMatthew G. Knepley } 11639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 11649566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 11659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1166b7f6ffafSMatthew G. Knepley } 1167846a3e8bSMatthew G. Knepley /* Plot cells */ 1168b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1169846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1170846a3e8bSMatthew G. Knepley const PetscInt *cone; 1171846a3e8bSMatthew G. Knepley 1172fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1173846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1174846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1175846a3e8bSMatthew G. Knepley PetscInt val; 11769566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 11779371c9d4SSatish Balay if (val >= 0) { 11789371c9d4SSatish Balay color = lcolors[l % numLColors]; 11799371c9d4SSatish Balay break; 11809371c9d4SSatish Balay } 1181846a3e8bSMatthew G. Knepley } 11829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 118363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1184846a3e8bSMatthew G. Knepley } 1185846a3e8bSMatthew G. Knepley } else { 1186b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1187846a3e8bSMatthew G. Knepley 1188b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1189b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1190fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 11919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 11929371c9d4SSatish Balay if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1193b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1194b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1195b7f6ffafSMatthew G. Knepley 11969566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 11979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1198b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1199b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1200b7f6ffafSMatthew G. Knepley 12019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 120263a3b9bcSJacob 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)); 1203b7f6ffafSMatthew G. Knepley } 1204b7f6ffafSMatthew G. Knepley } else { 1205b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1206b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1207b7f6ffafSMatthew G. Knepley 12089566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1209846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1210846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1211846a3e8bSMatthew G. Knepley 1212b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1213846a3e8bSMatthew G. Knepley } 12149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1215b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1216b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1217b7f6ffafSMatthew G. Knepley 1218b7f6ffafSMatthew G. Knepley if (v > 0) { 1219b7f6ffafSMatthew G. Knepley if (plotEdges) { 1220b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1221b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1222b7f6ffafSMatthew G. Knepley 12239371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 12249371c9d4SSatish Balay endpoints[1] = vertex; 12259566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 122663a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 122763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 12289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 12291baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1230b7f6ffafSMatthew G. Knepley } 123163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1232b7f6ffafSMatthew G. Knepley } 12339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 12349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1235846a3e8bSMatthew G. Knepley } 1236846a3e8bSMatthew G. Knepley } 1237b7f6ffafSMatthew G. Knepley } 1238846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1239846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1240846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1241c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1242c713ec31SMatthew G. Knepley const PetscScalar *array; 1243c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1244c713ec31SMatthew G. Knepley PetscBool isDG; 1245846a3e8bSMatthew G. Knepley 1246fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1247c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1248c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1249c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 12509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1251c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1252c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1253c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1254846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1255846a3e8bSMatthew G. Knepley } 1256846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12579371c9d4SSatish Balay if (cdim == 3) { 12589371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12599371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12609371c9d4SSatish Balay tcoords[2] = -tmp; 12619371c9d4SSatish Balay } 1262ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1263846a3e8bSMatthew G. Knepley } 1264ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1265c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1266c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 12679566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1269846a3e8bSMatthew G. Knepley } 1270b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1271b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1272846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1273846a3e8bSMatthew G. Knepley PetscInt val; 12749566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 12759371c9d4SSatish Balay if (val >= 0) { 12769371c9d4SSatish Balay color = lcolors[l % numLColors]; 12779371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12789371c9d4SSatish Balay break; 12799371c9d4SSatish Balay } 1280846a3e8bSMatthew G. Knepley } 1281b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 128263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1283b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 128463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 12851baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1286846a3e8bSMatthew G. Knepley } 1287b7f6ffafSMatthew G. Knepley if (drawHasse) { 1288b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 12899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 12909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 12919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 12939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1294552f7358SJed Brown 1295b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 12969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 12979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 12989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 13009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1301b7f6ffafSMatthew G. Knepley 1302b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 13039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 13049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 13059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 13079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1308b7f6ffafSMatthew G. Knepley 1309b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1310b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1311b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1312b7f6ffafSMatthew G. Knepley 13139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 13149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 131548a46eb9SPierre 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)); 13160588280cSMatthew G. Knepley } 13170588280cSMatthew G. Knepley } 13189566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 13199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 13209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 132163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 13229566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 13239566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 13249566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 13259566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 13269566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 13270f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 13280f7d6e4aSStefano Zampini Vec cown, acown; 13290f7d6e4aSStefano Zampini VecScatter sct; 13300f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 13310f7d6e4aSStefano Zampini IS gid, acis; 13320f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 13330f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 13340f7d6e4aSStefano Zampini PetscScalar *array, nid; 13350f7d6e4aSStefano Zampini const PetscInt *idxs; 13360f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 13370f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 13380f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 13390f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 13400f7d6e4aSStefano Zampini 13419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 13429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1343b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 13449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 13450f7d6e4aSStefano Zampini #endif 13460f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 13479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 13489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 13490f7d6e4aSStefano Zampini d1 = 0; 13509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 13510f7d6e4aSStefano Zampini nid = d2; 13529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 13539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 13549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 13550f7d6e4aSStefano Zampini } else nid = 0.0; 13560f7d6e4aSStefano Zampini 13570f7d6e4aSStefano Zampini /* Get connectivity */ 13589566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 13599566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 13600f7d6e4aSStefano Zampini 13610f7d6e4aSStefano Zampini /* filter overlapped local cells */ 13629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 13639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 13649566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 13659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 13660f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 13670f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 13680f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 13690f7d6e4aSStefano Zampini } 13709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 137163a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 13729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13739566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 13740f7d6e4aSStefano Zampini 13750f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 13769566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 13779566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 13789566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 13799566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 13800f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 13819566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 13829566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 13839566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 13849566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 13859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 13869566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 13879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 13880f7d6e4aSStefano Zampini 13890f7d6e4aSStefano Zampini /* compute edgeCut */ 13900f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 13919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 13929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 13939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 13949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13959566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 13960f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 13970f7d6e4aSStefano Zampini PetscInt totl; 13980f7d6e4aSStefano Zampini 13990f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 14009566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 14010f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 14020f7d6e4aSStefano Zampini if (work[i] < 0) { 14030f7d6e4aSStefano Zampini ect += 1; 14040f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 14050f7d6e4aSStefano Zampini } 14060f7d6e4aSStefano Zampini } 14070f7d6e4aSStefano Zampini } 14089566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 14099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 14100f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 14110f7d6e4aSStefano Zampini lm[1] = -numVertices; 14121c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 141363a3b9bcSJacob 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])); 14140f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 14150f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 14160f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 14171c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 141863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1419b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 142063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)(gm[1])) / ((double)gm[0]) : 1.)); 14210f7d6e4aSStefano Zampini #else 142263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 14230f7d6e4aSStefano Zampini #endif 14249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 14259566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 14269566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 14279566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1428552f7358SJed Brown } else { 1429412e9a14SMatthew G. Knepley const char *name; 1430d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1431412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1432d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1433ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 14349318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1435412e9a14SMatthew G. Knepley MPI_Comm comm; 1436412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1437552f7358SJed Brown 14389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 14409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 14419566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 14429566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 144463a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 144563a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 144663a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 14479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 14481c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 14492827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1450d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 14519566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 14529566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1453412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1454412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1455412e9a14SMatthew G. Knepley 14569566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 14579566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1458412e9a14SMatthew G. Knepley ict = ct0; 14599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1460412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1461412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1462412e9a14SMatthew G. Knepley DMPolytopeType ct; 1463412e9a14SMatthew G. Knepley 14649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1465412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1466412e9a14SMatthew G. Knepley else ++Nc[1]; 1467412e9a14SMatthew G. Knepley } 1468ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 14699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 14709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 14719566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 147263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1473834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1474dd400576SPatrick Sanan if (rank == 0) { 147563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 147663a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 147763a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1478834065abSMatthew G. Knepley } 1479cbb7f117SMark Adams } 1480ca7bf7eeSMatthew G. Knepley } else { 1481ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1482ca7bf7eeSMatthew G. Knepley 14839371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 14849371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 14859566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 14869371c9d4SSatish Balay locMinMax[0] = Nc[1]; 14879371c9d4SSatish Balay locMinMax[1] = Nc[1]; 14889566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1489ca7bf7eeSMatthew G. Knepley if (d == depth) { 14909371c9d4SSatish Balay locMinMax[0] = gcNum; 14919371c9d4SSatish Balay locMinMax[1] = gcNum; 14929566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1493ca7bf7eeSMatthew G. Knepley } 149463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 14959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 14969566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 14979566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1498ca7bf7eeSMatthew G. Knepley } 14999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1500552f7358SJed Brown } 15019566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 15029318fe57SMatthew G. Knepley { 15039318fe57SMatthew G. Knepley const PetscReal *maxCell; 15049318fe57SMatthew G. Knepley const PetscReal *L; 15056858538eSMatthew G. Knepley PetscBool localized; 15069318fe57SMatthew G. Knepley 15074fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 15089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 15096858538eSMatthew G. Knepley if (L || localized) { 15106858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 15119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 15126858538eSMatthew G. Knepley if (L) { 15136858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 15149318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 15156858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 15166858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 15179318fe57SMatthew G. Knepley } 15186858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 15196858538eSMatthew G. Knepley } 15206858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 15219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 15229318fe57SMatthew G. Knepley } 15239318fe57SMatthew G. Knepley } 15249566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 15259566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1526a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1527a57dd577SMatthew G Knepley DMLabel label; 1528a57dd577SMatthew G Knepley const char *name; 1529a57dd577SMatthew G Knepley IS valueIS; 1530a57dd577SMatthew G Knepley const PetscInt *values; 1531a57dd577SMatthew G Knepley PetscInt numValues, v; 1532a57dd577SMatthew G Knepley 15339566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 15349566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 15359566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 153663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 15379566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 15389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 15399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1540a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1541a57dd577SMatthew G Knepley PetscInt size; 1542a57dd577SMatthew G Knepley 15439566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 15449566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 154563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1546a57dd577SMatthew G Knepley } 15479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 15489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 15499566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 15509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1551a57dd577SMatthew G Knepley } 1552c1cad2e7SMatthew G. Knepley { 1553c1cad2e7SMatthew G. Knepley char **labelNames; 1554c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1555c1cad2e7SMatthew G. Knepley PetscBool flg; 1556c1cad2e7SMatthew G. Knepley 15579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 15589566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1559c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1560c1cad2e7SMatthew G. Knepley DMLabel label; 1561c1cad2e7SMatthew G. Knepley 15629566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1563c1cad2e7SMatthew G. Knepley if (flg) { 15649566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 15659566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1566c1cad2e7SMatthew G. Knepley } 15679566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1568c1cad2e7SMatthew G. Knepley } 15699566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1570c1cad2e7SMatthew G. Knepley } 157134aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 157234aa8a36SMatthew G. Knepley if (dm->Nf) { 157334aa8a36SMatthew G. Knepley PetscInt f; 157434aa8a36SMatthew G. Knepley 157534aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 157634aa8a36SMatthew G. Knepley const char *name; 157734aa8a36SMatthew G. Knepley 15789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 15799566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 15809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15819566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 158234aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 15839566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 15849566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 158534aa8a36SMatthew G. Knepley } else { 15869566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 15879566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 158834aa8a36SMatthew G. Knepley } 15899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 159034aa8a36SMatthew G. Knepley } 159134aa8a36SMatthew G. Knepley } 15929566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 15938e7ff633SMatthew G. Knepley if (cdm) { 15949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15959f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 15969566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 15979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 15988e7ff633SMatthew G. Knepley } 1599552f7358SJed Brown } 16003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1601552f7358SJed Brown } 1602552f7358SJed Brown 1603d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1604d71ae5a4SJacob Faibussowitsch { 1605e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1606e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1607a12d352dSMatthew G. Knepley PetscInt cdim; 1608e5c487bfSMatthew G. Knepley 1609e5c487bfSMatthew G. Knepley PetscFunctionBegin; 16109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 16119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 16129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1613e5c487bfSMatthew G. Knepley switch (ct) { 1614a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1615a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1616a12d352dSMatthew G. Knepley switch (cdim) { 16179371c9d4SSatish Balay case 1: { 1618a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1619a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1620a12d352dSMatthew G. Knepley 16219566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 16229566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 16239566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 16249371c9d4SSatish Balay } break; 16259371c9d4SSatish Balay case 2: { 1626a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1627a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1628a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1629a12d352dSMatthew G. Knepley 16309566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16319566063dSJacob 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)); 16329566063dSJacob 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)); 16339371c9d4SSatish Balay } break; 1634d71ae5a4SJacob Faibussowitsch default: 1635d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1636a12d352dSMatthew G. Knepley } 1637a12d352dSMatthew G. Knepley break; 1638e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 16399371c9d4SSatish 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)); 16409566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16419566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 16429566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1643e5c487bfSMatthew G. Knepley break; 1644e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 16459371c9d4SSatish 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)); 16469371c9d4SSatish 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)); 16479566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16489566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 16499566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 16509566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1651e5c487bfSMatthew G. Knepley break; 16529f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 16539f4ada15SMatthew 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)); 16549f4ada15SMatthew 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)); 16559f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16569f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 16579f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 16589f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 16599f4ada15SMatthew G. Knepley break; 1660d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1661d71ae5a4SJacob Faibussowitsch break; 1662d71ae5a4SJacob Faibussowitsch default: 1663d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1664e5c487bfSMatthew G. Knepley } 16653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1666e5c487bfSMatthew G. Knepley } 1667e5c487bfSMatthew G. Knepley 1668d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1669d71ae5a4SJacob Faibussowitsch { 1670e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1671e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1672e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1673e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1674e5c487bfSMatthew G. Knepley 1675e5c487bfSMatthew G. Knepley PetscFunctionBegin; 16769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 16779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1678e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1679e5c487bfSMatthew G. Knepley switch (ct) { 16809371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 1681e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1682e5c487bfSMatthew G. Knepley 16839371c9d4SSatish Balay for (v = 0; v < 3; ++v) { 16849371c9d4SSatish Balay centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.; 16859371c9d4SSatish Balay centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.; 16869371c9d4SSatish Balay } 1687e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1688e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1689e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1690e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1691e5c487bfSMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv; 1692e5c487bfSMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv; 1693e5c487bfSMatthew G. Knepley } 16949566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1695e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 16969566063dSJacob 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)); 16979566063dSJacob 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)); 1698e5c487bfSMatthew G. Knepley } 1699e5c487bfSMatthew G. Knepley } 17009371c9d4SSatish Balay } break; 1701d71ae5a4SJacob Faibussowitsch default: 1702d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1703e5c487bfSMatthew G. Knepley } 17043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1705e5c487bfSMatthew G. Knepley } 1706e5c487bfSMatthew G. Knepley 1707d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1708d71ae5a4SJacob Faibussowitsch { 1709e412dcbdSMatthew G. Knepley PetscDraw draw; 1710e412dcbdSMatthew G. Knepley DM cdm; 1711e412dcbdSMatthew G. Knepley PetscSection coordSection; 1712e412dcbdSMatthew G. Knepley Vec coordinates; 1713c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1714e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1715e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1716c9c77995SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, edgeDiv = 4; 1717e412dcbdSMatthew G. Knepley 1718e412dcbdSMatthew G. Knepley PetscFunctionBegin; 17199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 172063a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 17219566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 17229566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 17239566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 17249566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 17259566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 17269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 17279566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1728e412dcbdSMatthew G. Knepley 17299566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 17309566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 17313ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 17329566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1733e412dcbdSMatthew G. Knepley 1734c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 17359566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 17369566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1737e412dcbdSMatthew G. Knepley 1738cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1739cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1740c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1741ba2698f1SMatthew G. Knepley PetscInt numCoords; 1742c9c77995SMatthew G. Knepley PetscBool isDG; 1743cf3064d3SMatthew G. Knepley 1744c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 17451baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 17461baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1747c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1748cf3064d3SMatthew G. Knepley } 17499566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 17509566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 17519566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 17529566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 17533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1754e412dcbdSMatthew G. Knepley } 1755e412dcbdSMatthew G. Knepley 17561e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17571e50132fSMatthew G. Knepley #include <exodusII.h> 17586823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 17591e50132fSMatthew G. Knepley #endif 17601e50132fSMatthew G. Knepley 1761d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1762d71ae5a4SJacob Faibussowitsch { 17635f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1764002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1765552f7358SJed Brown 1766552f7358SJed Brown PetscFunctionBegin; 1767552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1768552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 17709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 17719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 17729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 17739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 17749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 17755f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1776552f7358SJed Brown if (iascii) { 17778135c375SStefano Zampini PetscViewerFormat format; 17789566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 17791baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 17801baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1781c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1782c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 17839566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1784c6ccd67eSMatthew G. Knepley #else 1785c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1786552f7358SJed Brown #endif 1787e412dcbdSMatthew G. Knepley } else if (isvtk) { 17889566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1789e412dcbdSMatthew G. Knepley } else if (isdraw) { 17909566063dSJacob Faibussowitsch PetscCall(DMPlexView_Draw(dm, viewer)); 17918135c375SStefano Zampini } else if (isglvis) { 17929566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 17931e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17941e50132fSMatthew G. Knepley } else if (isexodus) { 17956823f3c5SBlaise Bourdin /* 17966823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 17976823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 1798da81f932SPierre Jolivet with ID 1, containing all cells. 17996823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 18006823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 18016823f3c5SBlaise Bourdin */ 18026823f3c5SBlaise Bourdin PetscInt numCS; 18039566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 18046823f3c5SBlaise Bourdin if (!numCS) { 18051e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 18069566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 18079566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 18089566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 18096823f3c5SBlaise Bourdin } 18109566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 18111e50132fSMatthew G. Knepley #endif 18125f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 18135f34f2dcSJed Brown } else if (iscgns) { 18145f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 18155f34f2dcSJed Brown #endif 18161baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1817cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 18189566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1819cb3ba0daSMatthew G. Knepley if (flg) { 1820cb3ba0daSMatthew G. Knepley Vec ranks; 18219566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 18229566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 18239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1824cb3ba0daSMatthew G. Knepley } 1825002a2709SMatthew G. Knepley /* Optionally view a label */ 18269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1827002a2709SMatthew G. Knepley if (flg) { 1828002a2709SMatthew G. Knepley DMLabel label; 1829002a2709SMatthew G. Knepley Vec val; 1830002a2709SMatthew G. Knepley 18319566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 183228b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 18339566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 18349566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 18359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1836002a2709SMatthew G. Knepley } 18373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1838552f7358SJed Brown } 1839552f7358SJed Brown 18407f96f51bSksagiyam /*@ 1841a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 18427f96f51bSksagiyam 184320f4b53cSBarry Smith Collective 18447f96f51bSksagiyam 18457f96f51bSksagiyam Input Parameters: 1846a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 1847a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 18487f96f51bSksagiyam 18497f96f51bSksagiyam Level: advanced 18507f96f51bSksagiyam 18511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 18527f96f51bSksagiyam @*/ 1853d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1854d71ae5a4SJacob Faibussowitsch { 18557f96f51bSksagiyam PetscBool ishdf5; 18567f96f51bSksagiyam 18577f96f51bSksagiyam PetscFunctionBegin; 18587f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 18597f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 18619566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 18627f96f51bSksagiyam if (ishdf5) { 18637f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 18647f96f51bSksagiyam PetscViewerFormat format; 18659566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 18667f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18677f96f51bSksagiyam IS globalPointNumbering; 18687f96f51bSksagiyam 18699566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18709566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 187298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 18737f96f51bSksagiyam #else 18747f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 18757f96f51bSksagiyam #endif 18767f96f51bSksagiyam } 18779566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 18783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18797f96f51bSksagiyam } 18807f96f51bSksagiyam 188177b8e257Sksagiyam /*@ 1882a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 188377b8e257Sksagiyam 188420f4b53cSBarry Smith Collective 188577b8e257Sksagiyam 188677b8e257Sksagiyam Input Parameters: 1887a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 1888a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 188977b8e257Sksagiyam 189077b8e257Sksagiyam Level: advanced 189177b8e257Sksagiyam 18921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 189377b8e257Sksagiyam @*/ 1894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1895d71ae5a4SJacob Faibussowitsch { 189677b8e257Sksagiyam PetscBool ishdf5; 189777b8e257Sksagiyam 189877b8e257Sksagiyam PetscFunctionBegin; 189977b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 190077b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 190377b8e257Sksagiyam if (ishdf5) { 190477b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 190577b8e257Sksagiyam PetscViewerFormat format; 19069566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 190777b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 19089566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 1909fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 191077b8e257Sksagiyam #else 191177b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 191277b8e257Sksagiyam #endif 191377b8e257Sksagiyam } 19149566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 19153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 191677b8e257Sksagiyam } 191777b8e257Sksagiyam 1918bd6565f1Sksagiyam /*@ 1919a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 1920bd6565f1Sksagiyam 192120f4b53cSBarry Smith Collective 1922bd6565f1Sksagiyam 1923bd6565f1Sksagiyam Input Parameters: 1924a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 1925a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 1926bd6565f1Sksagiyam 1927bd6565f1Sksagiyam Level: advanced 1928bd6565f1Sksagiyam 19291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 1930bd6565f1Sksagiyam @*/ 1931d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1932d71ae5a4SJacob Faibussowitsch { 1933bd6565f1Sksagiyam PetscBool ishdf5; 1934bd6565f1Sksagiyam 1935bd6565f1Sksagiyam PetscFunctionBegin; 1936bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1937bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19399566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 1940bd6565f1Sksagiyam if (ishdf5) { 1941bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 1942bd6565f1Sksagiyam IS globalPointNumbering; 1943bd6565f1Sksagiyam PetscViewerFormat format; 1944bd6565f1Sksagiyam 19459566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 1946bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 19479566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 19489566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 19499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 195098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1951bd6565f1Sksagiyam #else 1952bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1953bd6565f1Sksagiyam #endif 1954bd6565f1Sksagiyam } 19559566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 19563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1957bd6565f1Sksagiyam } 1958bd6565f1Sksagiyam 1959021affd3Sksagiyam /*@ 1960a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 1961021affd3Sksagiyam 196220f4b53cSBarry Smith Collective 1963021affd3Sksagiyam 1964021affd3Sksagiyam Input Parameters: 1965a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 1966a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 1967a1cb98faSBarry Smith - sectiondm - The `DM` that contains the section to be saved 1968021affd3Sksagiyam 1969021affd3Sksagiyam Level: advanced 1970021affd3Sksagiyam 1971021affd3Sksagiyam Notes: 1972a1cb98faSBarry 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. 1973021affd3Sksagiyam 1974a1cb98faSBarry Smith In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1975021affd3Sksagiyam 19761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 1977021affd3Sksagiyam @*/ 1978d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1979d71ae5a4SJacob Faibussowitsch { 1980021affd3Sksagiyam PetscBool ishdf5; 1981021affd3Sksagiyam 1982021affd3Sksagiyam PetscFunctionBegin; 1983021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1984021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1985021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19879566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 1988021affd3Sksagiyam if (ishdf5) { 1989021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 19909566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 1991021affd3Sksagiyam #else 1992021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1993021affd3Sksagiyam #endif 1994021affd3Sksagiyam } 19959566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 19963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1997021affd3Sksagiyam } 1998021affd3Sksagiyam 19993e97647fSksagiyam /*@ 20003e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 20013e97647fSksagiyam 200220f4b53cSBarry Smith Collective 20033e97647fSksagiyam 20043e97647fSksagiyam Input Parameters: 2005a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2006a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 2007a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 20083e97647fSksagiyam - vec - The global vector to be saved 20093e97647fSksagiyam 20103e97647fSksagiyam Level: advanced 20113e97647fSksagiyam 20123e97647fSksagiyam Notes: 2013a1cb98faSBarry Smith In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 20143e97647fSksagiyam 201560225df5SJacob Faibussowitsch Calling sequence: 2016a1cb98faSBarry Smith .vb 2017a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2018a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2019a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2020a1cb98faSBarry Smith DMClone(dm, §iondm); 2021a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2022a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2023a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2024a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2025a1cb98faSBarry Smith PetscSectionSetUp(section); 2026a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2027a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2028a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2029a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2030a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2031a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2032a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2033a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2034a1cb98faSBarry Smith DMDestroy(§iondm); 2035a1cb98faSBarry Smith DMDestroy(&dm); 2036a1cb98faSBarry Smith .ve 20373e97647fSksagiyam 20381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 20393e97647fSksagiyam @*/ 2040d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2041d71ae5a4SJacob Faibussowitsch { 20423e97647fSksagiyam PetscBool ishdf5; 20433e97647fSksagiyam 20443e97647fSksagiyam PetscFunctionBegin; 20453e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20463e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20473e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 20483e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 20493e97647fSksagiyam /* Check consistency */ 20503e97647fSksagiyam { 20513e97647fSksagiyam PetscSection section; 20523e97647fSksagiyam PetscBool includesConstraints; 20533e97647fSksagiyam PetscInt m, m1; 20543e97647fSksagiyam 20559566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 20569566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 20579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 20589566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 20599566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 206063a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 20613e97647fSksagiyam } 20629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 20643e97647fSksagiyam if (ishdf5) { 20653e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 20669566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20673e97647fSksagiyam #else 20683e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20693e97647fSksagiyam #endif 20703e97647fSksagiyam } 20719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 20723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20733e97647fSksagiyam } 20743e97647fSksagiyam 20753e97647fSksagiyam /*@ 20763e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 20773e97647fSksagiyam 207820f4b53cSBarry Smith Collective 20793e97647fSksagiyam 20803e97647fSksagiyam Input Parameters: 2081a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2082a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 208320f4b53cSBarry Smith . sectiondm - The `DM` that contains the local section on which `vec` is defined; may be the same as `dm` 20843e97647fSksagiyam - vec - The local vector to be saved 20853e97647fSksagiyam 20863e97647fSksagiyam Level: advanced 20873e97647fSksagiyam 2088a1cb98faSBarry Smith Note: 208920f4b53cSBarry Smith In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 20903e97647fSksagiyam 209160225df5SJacob Faibussowitsch Calling sequence: 2092a1cb98faSBarry Smith .vb 2093a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2094a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2095a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2096a1cb98faSBarry Smith DMClone(dm, §iondm); 2097a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2098a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2099a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2100a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2101a1cb98faSBarry Smith PetscSectionSetUp(section); 2102a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2103a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2104a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2105a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2106a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2107a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2108a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2109a1cb98faSBarry Smith DMDestroy(§iondm); 2110a1cb98faSBarry Smith DMDestroy(&dm); 2111a1cb98faSBarry Smith .ve 21123e97647fSksagiyam 21131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 21143e97647fSksagiyam @*/ 2115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2116d71ae5a4SJacob Faibussowitsch { 21173e97647fSksagiyam PetscBool ishdf5; 21183e97647fSksagiyam 21193e97647fSksagiyam PetscFunctionBegin; 21203e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21213e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21223e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21233e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 21243e97647fSksagiyam /* Check consistency */ 21253e97647fSksagiyam { 21263e97647fSksagiyam PetscSection section; 21273e97647fSksagiyam PetscBool includesConstraints; 21283e97647fSksagiyam PetscInt m, m1; 21293e97647fSksagiyam 21309566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 21319566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 21329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 21339566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 21349566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 213563a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 21363e97647fSksagiyam } 21379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21389566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 21393e97647fSksagiyam if (ishdf5) { 21403e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 21419566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 21423e97647fSksagiyam #else 21433e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21443e97647fSksagiyam #endif 21453e97647fSksagiyam } 21469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 21473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21483e97647fSksagiyam } 21493e97647fSksagiyam 2150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2151d71ae5a4SJacob Faibussowitsch { 2152d4f5a9a0SVaclav Hapla PetscBool ishdf5; 21532c40f234SMatthew G. Knepley 21542c40f234SMatthew G. Knepley PetscFunctionBegin; 21552c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21562c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2158d4f5a9a0SVaclav Hapla if (ishdf5) { 21592c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 21609c48423bSVaclav Hapla PetscViewerFormat format; 21619566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 21629c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 21639566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2164509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21659566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 216698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 21673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21682c40f234SMatthew G. Knepley #else 21692c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2170552f7358SJed Brown #endif 217198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2172552f7358SJed Brown } 2173552f7358SJed Brown 2174ea8e1828Sksagiyam /*@ 2175a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2176ea8e1828Sksagiyam 217720f4b53cSBarry Smith Collective 2178ea8e1828Sksagiyam 2179ea8e1828Sksagiyam Input Parameters: 2180a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2181a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2182ea8e1828Sksagiyam 21832fe279fdSBarry Smith Output Parameter: 218420f4b53cSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded `DMPLEX`, where N is the global number of points; `NULL` if unneeded 2185dec9e869Sksagiyam 2186ea8e1828Sksagiyam Level: advanced 2187ea8e1828Sksagiyam 21881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2189a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2190ea8e1828Sksagiyam @*/ 2191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2192d71ae5a4SJacob Faibussowitsch { 2193ea8e1828Sksagiyam PetscBool ishdf5; 2194ea8e1828Sksagiyam 2195ea8e1828Sksagiyam PetscFunctionBegin; 2196ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2197ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21984f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 21999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22009566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2201ea8e1828Sksagiyam if (ishdf5) { 2202ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2203ea8e1828Sksagiyam PetscViewerFormat format; 22049566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2205ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22069566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 220798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2208ea8e1828Sksagiyam #else 2209ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2210ea8e1828Sksagiyam #endif 2211ea8e1828Sksagiyam } 22129566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 22133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2214ea8e1828Sksagiyam } 2215ea8e1828Sksagiyam 22163e701f1cSksagiyam /*@ 2217a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 22183e701f1cSksagiyam 221920f4b53cSBarry Smith Collective 22203e701f1cSksagiyam 22213e701f1cSksagiyam Input Parameters: 2222a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2223a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2224a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 22253e701f1cSksagiyam 22263e701f1cSksagiyam Level: advanced 22273e701f1cSksagiyam 22281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2229a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 22303e701f1cSksagiyam @*/ 2231d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2232d71ae5a4SJacob Faibussowitsch { 22333e701f1cSksagiyam PetscBool ishdf5; 22343e701f1cSksagiyam 22353e701f1cSksagiyam PetscFunctionBegin; 22363e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22373e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2238c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 22413e701f1cSksagiyam if (ishdf5) { 22423e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 22433e701f1cSksagiyam PetscViewerFormat format; 22449566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 22453e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22469566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 224798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 22483e701f1cSksagiyam #else 22493e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22503e701f1cSksagiyam #endif 22513e701f1cSksagiyam } 22529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 22533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22543e701f1cSksagiyam } 22553e701f1cSksagiyam 2256b08ad5deSksagiyam /*@ 2257a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2258b08ad5deSksagiyam 225920f4b53cSBarry Smith Collective 2260b08ad5deSksagiyam 2261b08ad5deSksagiyam Input Parameters: 2262a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2263a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 226420f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2265b08ad5deSksagiyam 2266b08ad5deSksagiyam Level: advanced 2267b08ad5deSksagiyam 2268a1cb98faSBarry Smith Note: 2269a1cb98faSBarry Smith The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs. 2270e6368b79SVaclav Hapla 22711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2272a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2273b08ad5deSksagiyam @*/ 2274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2275d71ae5a4SJacob Faibussowitsch { 2276b08ad5deSksagiyam PetscBool ishdf5; 2277b08ad5deSksagiyam 2278b08ad5deSksagiyam PetscFunctionBegin; 2279b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2280b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2281e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22839566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2284b08ad5deSksagiyam if (ishdf5) { 2285b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2286b08ad5deSksagiyam PetscViewerFormat format; 2287b08ad5deSksagiyam 22889566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2289b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22909566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 229198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2292b08ad5deSksagiyam #else 2293b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2294b08ad5deSksagiyam #endif 2295b08ad5deSksagiyam } 22969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 22973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2298b08ad5deSksagiyam } 2299b08ad5deSksagiyam 2300f84dd6b4Sksagiyam /*@ 2301a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2302f84dd6b4Sksagiyam 230320f4b53cSBarry Smith Collective 2304f84dd6b4Sksagiyam 2305f84dd6b4Sksagiyam Input Parameters: 2306a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2307a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 2308a1cb98faSBarry Smith . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated 2309a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2310f84dd6b4Sksagiyam 2311a4e35b19SJacob Faibussowitsch Output Parameters: 231220f4b53cSBarry 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) 231320f4b53cSBarry 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) 2314f84dd6b4Sksagiyam 2315f84dd6b4Sksagiyam Level: advanced 2316f84dd6b4Sksagiyam 2317f84dd6b4Sksagiyam Notes: 231820f4b53cSBarry 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. 2319f84dd6b4Sksagiyam 232020f4b53cSBarry Smith In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2321f84dd6b4Sksagiyam 232220f4b53cSBarry 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. 2323f84dd6b4Sksagiyam 2324f84dd6b4Sksagiyam Example using 2 processes: 2325a1cb98faSBarry Smith .vb 2326a1cb98faSBarry Smith NX (number of points on dm): 4 2327a1cb98faSBarry Smith sectionA : the on-disk section 2328a1cb98faSBarry Smith vecA : a vector associated with sectionA 2329a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2330a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2331a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2332f84dd6b4Sksagiyam 2333a1cb98faSBarry Smith rank 0 rank 1 2334a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2335a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2336a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2337a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2338a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2339a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2340a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2341a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2342a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2343a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2344a1cb98faSBarry Smith .ve 2345a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2346a1cb98faSBarry Smith 23471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2348f84dd6b4Sksagiyam @*/ 2349d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2350d71ae5a4SJacob Faibussowitsch { 2351f84dd6b4Sksagiyam PetscBool ishdf5; 2352f84dd6b4Sksagiyam 2353f84dd6b4Sksagiyam PetscFunctionBegin; 2354f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2355f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2356f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2357f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 23584f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 23594f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 23609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23619566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2362f84dd6b4Sksagiyam if (ishdf5) { 2363f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 23649566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2365f84dd6b4Sksagiyam #else 2366f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2367f84dd6b4Sksagiyam #endif 2368f84dd6b4Sksagiyam } 23699566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 23703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2371f84dd6b4Sksagiyam } 2372f84dd6b4Sksagiyam 23738be3dfe1Sksagiyam /*@ 23748be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 23758be3dfe1Sksagiyam 237620f4b53cSBarry Smith Collective 23778be3dfe1Sksagiyam 23788be3dfe1Sksagiyam Input Parameters: 2379a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2380a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2381a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 2382a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 23838be3dfe1Sksagiyam - vec - The global vector to set values of 23848be3dfe1Sksagiyam 23858be3dfe1Sksagiyam Level: advanced 23868be3dfe1Sksagiyam 23878be3dfe1Sksagiyam Notes: 2388a1cb98faSBarry Smith In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 23898be3dfe1Sksagiyam 239060225df5SJacob Faibussowitsch Calling sequence: 2391a1cb98faSBarry Smith .vb 2392a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2393a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2394a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2395a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2396a1cb98faSBarry Smith DMClone(dm, §iondm); 2397a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2398a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2399a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2400a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2401a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2402a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2403a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2404a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2405a1cb98faSBarry Smith DMDestroy(§iondm); 2406a1cb98faSBarry Smith DMDestroy(&dm); 2407a1cb98faSBarry Smith .ve 24088be3dfe1Sksagiyam 24091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2410a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 24118be3dfe1Sksagiyam @*/ 2412d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2413d71ae5a4SJacob Faibussowitsch { 24148be3dfe1Sksagiyam PetscBool ishdf5; 24158be3dfe1Sksagiyam 24168be3dfe1Sksagiyam PetscFunctionBegin; 24178be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24188be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24198be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24208be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24218be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24228be3dfe1Sksagiyam /* Check consistency */ 24238be3dfe1Sksagiyam { 24248be3dfe1Sksagiyam PetscSection section; 24258be3dfe1Sksagiyam PetscBool includesConstraints; 24268be3dfe1Sksagiyam PetscInt m, m1; 24278be3dfe1Sksagiyam 24289566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 24299566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 24309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24319566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 24329566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 243363a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 24348be3dfe1Sksagiyam } 24359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24369566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 24378be3dfe1Sksagiyam if (ishdf5) { 24388be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 24399566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 24408be3dfe1Sksagiyam #else 24418be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24428be3dfe1Sksagiyam #endif 24438be3dfe1Sksagiyam } 24449566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 24453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24468be3dfe1Sksagiyam } 24478be3dfe1Sksagiyam 24488be3dfe1Sksagiyam /*@ 24498be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 24508be3dfe1Sksagiyam 245120f4b53cSBarry Smith Collective 24528be3dfe1Sksagiyam 24538be3dfe1Sksagiyam Input Parameters: 2454a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2455a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2456a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined 2457a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 24588be3dfe1Sksagiyam - vec - The local vector to set values of 24598be3dfe1Sksagiyam 24608be3dfe1Sksagiyam Level: advanced 24618be3dfe1Sksagiyam 24628be3dfe1Sksagiyam Notes: 246320f4b53cSBarry Smith In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 24648be3dfe1Sksagiyam 246560225df5SJacob Faibussowitsch Calling sequence: 2466a1cb98faSBarry Smith .vb 2467a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2468a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2469a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2470a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2471a1cb98faSBarry Smith DMClone(dm, §iondm); 2472a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2473a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2474a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2475a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2476a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2477a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2478a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2479a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2480a1cb98faSBarry Smith DMDestroy(§iondm); 2481a1cb98faSBarry Smith DMDestroy(&dm); 2482a1cb98faSBarry Smith .ve 24838be3dfe1Sksagiyam 24841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2485a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 24868be3dfe1Sksagiyam @*/ 2487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2488d71ae5a4SJacob Faibussowitsch { 24898be3dfe1Sksagiyam PetscBool ishdf5; 24908be3dfe1Sksagiyam 24918be3dfe1Sksagiyam PetscFunctionBegin; 24928be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24938be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24948be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24958be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24968be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24978be3dfe1Sksagiyam /* Check consistency */ 24988be3dfe1Sksagiyam { 24998be3dfe1Sksagiyam PetscSection section; 25008be3dfe1Sksagiyam PetscBool includesConstraints; 25018be3dfe1Sksagiyam PetscInt m, m1; 25028be3dfe1Sksagiyam 25039566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 25049566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 25059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 25069566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 25079566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 250863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 25098be3dfe1Sksagiyam } 25109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25119566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 25128be3dfe1Sksagiyam if (ishdf5) { 25138be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 25149566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 25158be3dfe1Sksagiyam #else 25168be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 25178be3dfe1Sksagiyam #endif 25188be3dfe1Sksagiyam } 25199566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 25203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25218be3dfe1Sksagiyam } 25228be3dfe1Sksagiyam 2523d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2524d71ae5a4SJacob Faibussowitsch { 2525552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2526552f7358SJed Brown 2527552f7358SJed Brown PetscFunctionBegin; 25289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 25299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 25309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 25319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 25322e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", NULL)); 25332e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 25342e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 25352e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 25362e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 25376bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 25386bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2539c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2540c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 25415f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 25423ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 25439566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 25449566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 25459566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 25469566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 25479566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 25489566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 254921027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 25509f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 25519566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 25529566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 25539566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 25541d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 25559566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 25569566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 25579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 25589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 25599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 25604e2e9504SJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.face_sf)); 25616725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 25626725e60dSJed Brown PetscCall(ISDestroy(&mesh->periodic.periodic_points)); 25639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 25649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 25659566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 25669566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 25679566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 25689566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 25699566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 25709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 25719566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 25729566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 25739566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2574552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 25759566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 25763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2577552f7358SJed Brown } 2578552f7358SJed Brown 2579d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2580d71ae5a4SJacob Faibussowitsch { 25818d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2582acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 25839fca9976SJed Brown PetscInt localSize, localStart = 0; 2584837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2585b412c318SBarry Smith MatType mtype; 25861428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2587552f7358SJed Brown 2588552f7358SJed Brown PetscFunctionBegin; 25899566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2590b412c318SBarry Smith mtype = dm->mattype; 25919566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 25929566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 25939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 25949fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 25959566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 25969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 25979566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 25989566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 25999566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2600acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 26019566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 26029566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 26039566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 26049566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 26059566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 26069566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 26079566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 26089566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2609552f7358SJed Brown if (!isShell) { 2610837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 26119fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2612863027abSJed Brown PetscInt pStart, pEnd, p, dof, cdof, num_fields; 2613552f7358SJed Brown 26149566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 26159fca9976SJed Brown 26169fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 26179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2618863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 2619e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2620863027abSJed Brown switch (dm->blocking_type) { 26210e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 26229fca9976SJed Brown PetscInt bdof, offset; 2623a9d99c84SMatthew G. Knepley 26249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 26259fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 26269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 26279371c9d4SSatish Balay for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof; 26281d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 26291d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 26301d17a0a3SMatthew G. Knepley if (dof) { 26319371c9d4SSatish Balay if (bs < 0) { 26329371c9d4SSatish Balay bs = bdof; 26339371c9d4SSatish Balay } else if (bs != bdof) { 26349371c9d4SSatish Balay bs = 1; 26359371c9d4SSatish Balay } 2636552f7358SJed Brown } 2637863027abSJed Brown } break; 2638863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2639863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2640863027abSJed Brown PetscInt num_comp, bdof, offset; 2641863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2642863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2643863027abSJed Brown if (dof < 0) continue; 2644863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2645863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2646863027abSJed 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); 2647863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2648863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2649863027abSJed Brown // Handle possibly constant block size (unlikely) 2650863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2651863027abSJed Brown if (dof) { 2652863027abSJed Brown if (bs < 0) { 2653863027abSJed Brown bs = bdof; 2654863027abSJed Brown } else if (bs != bdof) { 2655863027abSJed Brown bs = 1; 2656863027abSJed Brown } 2657863027abSJed Brown } 2658863027abSJed Brown } 2659863027abSJed Brown } break; 2660863027abSJed Brown } 26612a28c762SMatthew G Knepley } 26622a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2663e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2664e432b41dSStefano Zampini bsLocal[1] = bs; 26659566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2666e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2667e432b41dSStefano Zampini else bs = bsMinMax[0]; 26686fd5c86aSStefano Zampini bs = PetscMax(1, bs); 26699566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 26700682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 26719566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 26729566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 26730682b8bbSJed Brown } else { 26749566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 26759566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 26769566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2677552f7358SJed Brown } 26789fca9976SJed Brown { // Consolidate blocks 26799fca9976SJed Brown PetscInt nblocks = 0; 26809fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 26819fca9976SJed Brown if (pblocks[i] == 0) continue; 26829fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2683ad540459SPierre Jolivet for (PetscInt j = 1; j < pblocks[i]; j++) PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i + j]); 26849fca9976SJed Brown } 26859fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 26869fca9976SJed Brown } 26879fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2688aa0f6e3cSJed Brown } 26899566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 26903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2691552f7358SJed Brown } 2692552f7358SJed Brown 26937cd05799SMatthew G. Knepley /*@ 2694a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2695be36d101SStefano Zampini 2696a1cb98faSBarry Smith Not Collective 2697be36d101SStefano Zampini 2698be36d101SStefano Zampini Input Parameter: 269960225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2700be36d101SStefano Zampini 27012fe279fdSBarry Smith Output Parameter: 2702be36d101SStefano Zampini . subsection - The subdomain section 2703be36d101SStefano Zampini 2704be36d101SStefano Zampini Level: developer 2705be36d101SStefano Zampini 27061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 27077cd05799SMatthew G. Knepley @*/ 2708d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2709d71ae5a4SJacob Faibussowitsch { 2710be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2711be36d101SStefano Zampini 2712be36d101SStefano Zampini PetscFunctionBegin; 2713be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2714be36d101SStefano Zampini if (!mesh->subdomainSection) { 2715be36d101SStefano Zampini PetscSection section; 2716be36d101SStefano Zampini PetscSF sf; 2717be36d101SStefano Zampini 27189566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 27199566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 27209566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 27219566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2722be36d101SStefano Zampini } 2723be36d101SStefano Zampini *subsection = mesh->subdomainSection; 27243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2725be36d101SStefano Zampini } 2726be36d101SStefano Zampini 2727552f7358SJed Brown /*@ 272820f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2729552f7358SJed Brown 2730a1cb98faSBarry Smith Not Collective 2731552f7358SJed Brown 2732552f7358SJed Brown Input Parameter: 273360225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2734552f7358SJed Brown 2735552f7358SJed Brown Output Parameters: 2736552f7358SJed Brown + pStart - The first mesh point 2737552f7358SJed Brown - pEnd - The upper bound for mesh points 2738552f7358SJed Brown 2739552f7358SJed Brown Level: beginner 2740552f7358SJed Brown 27411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2742552f7358SJed Brown @*/ 2743d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2744d71ae5a4SJacob Faibussowitsch { 2745552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2746552f7358SJed Brown 2747552f7358SJed Brown PetscFunctionBegin; 2748552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27499f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 27509f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 27513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2752552f7358SJed Brown } 2753552f7358SJed Brown 2754552f7358SJed Brown /*@ 275520f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 2756552f7358SJed Brown 2757a1cb98faSBarry Smith Not Collective 2758552f7358SJed Brown 2759552f7358SJed Brown Input Parameters: 276060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2761552f7358SJed Brown . pStart - The first mesh point 2762552f7358SJed Brown - pEnd - The upper bound for mesh points 2763552f7358SJed Brown 2764552f7358SJed Brown Level: beginner 2765552f7358SJed Brown 27661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2767552f7358SJed Brown @*/ 2768d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2769d71ae5a4SJacob Faibussowitsch { 2770552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2771552f7358SJed Brown 2772552f7358SJed Brown PetscFunctionBegin; 2773552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 27759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 277621027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 27773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2778552f7358SJed Brown } 2779552f7358SJed Brown 2780552f7358SJed Brown /*@ 2781eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2782552f7358SJed Brown 2783a1cb98faSBarry Smith Not Collective 2784552f7358SJed Brown 2785552f7358SJed Brown Input Parameters: 278660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2787a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2788552f7358SJed Brown 2789552f7358SJed Brown Output Parameter: 279020f4b53cSBarry Smith . size - The cone size for point `p` 2791552f7358SJed Brown 2792552f7358SJed Brown Level: beginner 2793552f7358SJed Brown 27941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2795552f7358SJed Brown @*/ 2796d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2797d71ae5a4SJacob Faibussowitsch { 2798552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2799552f7358SJed Brown 2800552f7358SJed Brown PetscFunctionBegin; 2801552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28024f572ea9SToby Isaac PetscAssertPointer(size, 3); 28039f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 28049f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 28053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2806552f7358SJed Brown } 2807552f7358SJed Brown 2808552f7358SJed Brown /*@ 2809eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2810552f7358SJed Brown 2811a1cb98faSBarry Smith Not Collective 2812552f7358SJed Brown 2813552f7358SJed Brown Input Parameters: 281460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2815a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 281620f4b53cSBarry Smith - size - The cone size for point `p` 2817552f7358SJed Brown 2818552f7358SJed Brown Level: beginner 2819552f7358SJed Brown 2820a1cb98faSBarry Smith Note: 2821a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 2822a1cb98faSBarry Smith 28231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2824552f7358SJed Brown @*/ 2825d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2826d71ae5a4SJacob Faibussowitsch { 2827552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2828552f7358SJed Brown 2829552f7358SJed Brown PetscFunctionBegin; 2830552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28319f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 28329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 28333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2834552f7358SJed Brown } 2835552f7358SJed Brown 2836552f7358SJed Brown /*@C 2837eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2838552f7358SJed Brown 2839a1cb98faSBarry Smith Not Collective 2840552f7358SJed Brown 2841552f7358SJed Brown Input Parameters: 2842a1cb98faSBarry Smith + dm - The `DMPLEX` 2843a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2844552f7358SJed Brown 2845552f7358SJed Brown Output Parameter: 284620f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p` 2847552f7358SJed Brown 2848552f7358SJed Brown Level: beginner 2849552f7358SJed Brown 285060225df5SJacob Faibussowitsch Fortran Notes: 2851a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 2852a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 28533813dfbdSMatthew G Knepley 28541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 2855552f7358SJed Brown @*/ 2856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2857d71ae5a4SJacob Faibussowitsch { 2858552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2859552f7358SJed Brown PetscInt off; 2860552f7358SJed Brown 2861552f7358SJed Brown PetscFunctionBegin; 2862552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28634f572ea9SToby Isaac PetscAssertPointer(cone, 3); 28649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 2865552f7358SJed Brown *cone = &mesh->cones[off]; 28663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2867552f7358SJed Brown } 2868552f7358SJed Brown 28690ce7577fSVaclav Hapla /*@C 28700ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 28710ce7577fSVaclav Hapla 2872a1cb98faSBarry Smith Not Collective 28730ce7577fSVaclav Hapla 28740ce7577fSVaclav Hapla Input Parameters: 2875a1cb98faSBarry Smith + dm - The `DMPLEX` 2876a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 28770ce7577fSVaclav Hapla 2878d8d19677SJose E. Roman Output Parameters: 287920f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 288020f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p` 28810ce7577fSVaclav Hapla 28820ce7577fSVaclav Hapla Level: intermediate 28830ce7577fSVaclav Hapla 28841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 28850ce7577fSVaclav Hapla @*/ 2886d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2887d71ae5a4SJacob Faibussowitsch { 28880ce7577fSVaclav Hapla PetscSection cs, newcs; 28890ce7577fSVaclav Hapla PetscInt *cones; 28900ce7577fSVaclav Hapla PetscInt *newarr = NULL; 28910ce7577fSVaclav Hapla PetscInt n; 28920ce7577fSVaclav Hapla 28930ce7577fSVaclav Hapla PetscFunctionBegin; 28949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 28959566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 28969566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 28970ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 28980ce7577fSVaclav Hapla if (pCones) { 28999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 29009566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 29010ce7577fSVaclav Hapla } 29023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29030ce7577fSVaclav Hapla } 29040ce7577fSVaclav Hapla 2905af9eab45SVaclav Hapla /*@ 2906af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2907d4636a37SVaclav Hapla 2908a1cb98faSBarry Smith Not Collective 2909d4636a37SVaclav Hapla 2910d4636a37SVaclav Hapla Input Parameters: 2911a1cb98faSBarry Smith + dm - The `DMPLEX` 2912a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 2913d4636a37SVaclav Hapla 2914d4636a37SVaclav Hapla Output Parameter: 2915af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 2916d4636a37SVaclav Hapla 2917d4636a37SVaclav Hapla Level: advanced 2918d4636a37SVaclav Hapla 2919af9eab45SVaclav Hapla Notes: 292020f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 2921af9eab45SVaclav Hapla 2922a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 2923a1cb98faSBarry Smith 29241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 2925a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 2926d4636a37SVaclav Hapla @*/ 2927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2928d71ae5a4SJacob Faibussowitsch { 2929af9eab45SVaclav Hapla IS *expandedPointsAll; 2930af9eab45SVaclav Hapla PetscInt depth; 2931d4636a37SVaclav Hapla 2932d4636a37SVaclav Hapla PetscFunctionBegin; 2933af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2934af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 29354f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 29369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2937af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 29389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 29399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 29403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2941af9eab45SVaclav Hapla } 2942af9eab45SVaclav Hapla 2943af9eab45SVaclav Hapla /*@ 2944af9eab45SVaclav Hapla DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices (DAG points of depth 0, i.e. without cones). 2945af9eab45SVaclav Hapla 2946a1cb98faSBarry Smith Not Collective 2947af9eab45SVaclav Hapla 2948af9eab45SVaclav Hapla Input Parameters: 2949a1cb98faSBarry Smith + dm - The `DMPLEX` 2950a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 2951af9eab45SVaclav Hapla 2952d8d19677SJose E. Roman Output Parameters: 2953a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 2954af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 2955af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2956af9eab45SVaclav Hapla 2957af9eab45SVaclav Hapla Level: advanced 2958af9eab45SVaclav Hapla 2959af9eab45SVaclav Hapla Notes: 2960a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 2961af9eab45SVaclav Hapla 2962a4e35b19SJacob 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. 2963af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2964af9eab45SVaclav Hapla 2965a4e35b19SJacob 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\: 2966a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 2967a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 2968af9eab45SVaclav Hapla 29691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 2970a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 2971af9eab45SVaclav Hapla @*/ 2972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2973d71ae5a4SJacob Faibussowitsch { 2974af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 2975af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 2976af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 2977af9eab45SVaclav Hapla IS *expandedPoints_; 2978af9eab45SVaclav Hapla PetscSection *sections_; 2979af9eab45SVaclav Hapla 2980af9eab45SVaclav Hapla PetscFunctionBegin; 2981af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2982af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 29834f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 29844f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 29854f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 29869566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 29879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 29889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29899566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 29909566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 2991af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 2992af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 29939566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 29949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 2995af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 29969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 2997af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 29989566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 29999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3000af9eab45SVaclav Hapla } else { 30019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3002af9eab45SVaclav Hapla } 3003af9eab45SVaclav Hapla } 30049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 30059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 30069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3007af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 30089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 30099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3010af9eab45SVaclav Hapla if (cn > 1) { 30119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 30129566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3013af9eab45SVaclav Hapla } else { 3014af9eab45SVaclav Hapla newarr[co] = arr[i]; 3015af9eab45SVaclav Hapla } 3016af9eab45SVaclav Hapla } 30179566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3018af9eab45SVaclav Hapla arr = newarr; 3019af9eab45SVaclav Hapla n = newn; 3020af9eab45SVaclav Hapla } 30219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3022af9eab45SVaclav Hapla *depth = depth_; 3023af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3024af9eab45SVaclav Hapla else { 30259566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 30269566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3027af9eab45SVaclav Hapla } 3028af9eab45SVaclav Hapla if (sections) *sections = sections_; 3029af9eab45SVaclav Hapla else { 30309566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 30319566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3032af9eab45SVaclav Hapla } 30333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3034af9eab45SVaclav Hapla } 3035af9eab45SVaclav Hapla 3036af9eab45SVaclav Hapla /*@ 3037a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3038af9eab45SVaclav Hapla 3039a1cb98faSBarry Smith Not Collective 3040af9eab45SVaclav Hapla 3041af9eab45SVaclav Hapla Input Parameters: 3042a1cb98faSBarry Smith + dm - The `DMPLEX` 3043a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3044af9eab45SVaclav Hapla 3045d8d19677SJose E. Roman Output Parameters: 3046a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3047af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3048af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3049af9eab45SVaclav Hapla 3050af9eab45SVaclav Hapla Level: advanced 3051af9eab45SVaclav Hapla 3052a1cb98faSBarry Smith Note: 3053a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3054af9eab45SVaclav Hapla 30551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3056a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3057af9eab45SVaclav Hapla @*/ 3058d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3059d71ae5a4SJacob Faibussowitsch { 3060af9eab45SVaclav Hapla PetscInt d, depth_; 3061af9eab45SVaclav Hapla 3062af9eab45SVaclav Hapla PetscFunctionBegin; 30639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 30641dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3065af9eab45SVaclav Hapla if (depth) *depth = 0; 3066af9eab45SVaclav Hapla if (expandedPoints) { 30679566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 30689566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3069af9eab45SVaclav Hapla } 3070af9eab45SVaclav Hapla if (sections) { 30719566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 30729566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3073af9eab45SVaclav Hapla } 30743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3075d4636a37SVaclav Hapla } 3076d4636a37SVaclav Hapla 3077552f7358SJed Brown /*@ 307892371b87SBarry 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 3079552f7358SJed Brown 3080a1cb98faSBarry Smith Not Collective 3081552f7358SJed Brown 3082552f7358SJed Brown Input Parameters: 308360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3084a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 308520f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p` 3086552f7358SJed Brown 3087552f7358SJed Brown Level: beginner 3088552f7358SJed Brown 3089a1cb98faSBarry Smith Note: 3090a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3091a1cb98faSBarry Smith 30921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3093552f7358SJed Brown @*/ 3094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3095d71ae5a4SJacob Faibussowitsch { 3096552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3097552f7358SJed Brown PetscInt dof, off, c; 3098552f7358SJed Brown 3099552f7358SJed Brown PetscFunctionBegin; 3100552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31024f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 31039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3104db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3105db485b19SStefano Zampini PetscInt pStart, pEnd; 3106db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 310763a3b9bcSJacob 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); 3108552f7358SJed Brown for (c = 0; c < dof; ++c) { 310963a3b9bcSJacob 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); 3110552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3111552f7358SJed Brown } 3112db485b19SStefano Zampini } else { 3113db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3114db485b19SStefano Zampini } 31153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3116552f7358SJed Brown } 3117552f7358SJed Brown 3118552f7358SJed Brown /*@C 3119eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3120552f7358SJed Brown 3121a1cb98faSBarry Smith Not Collective 3122552f7358SJed Brown 3123552f7358SJed Brown Input Parameters: 312460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3125a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3126552f7358SJed Brown 3127552f7358SJed Brown Output Parameter: 312820f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 3129b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3130552f7358SJed Brown 3131552f7358SJed Brown Level: beginner 3132552f7358SJed Brown 3133a1cb98faSBarry Smith Note: 3134b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3135b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3136a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3137b5a892a1SMatthew G. Knepley with the identity. 3138b5a892a1SMatthew G. Knepley 313960225df5SJacob Faibussowitsch Fortran Notes: 3140a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3141a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 31423813dfbdSMatthew G Knepley 31431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3144552f7358SJed Brown @*/ 3145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3146d71ae5a4SJacob Faibussowitsch { 3147552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3148552f7358SJed Brown PetscInt off; 3149552f7358SJed Brown 3150552f7358SJed Brown PetscFunctionBegin; 3151552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 315276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3153552f7358SJed Brown PetscInt dof; 31549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31554f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3156552f7358SJed Brown } 31579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 31580d644c17SKarl Rupp 3159552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 31603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3161552f7358SJed Brown } 3162552f7358SJed Brown 3163552f7358SJed Brown /*@ 3164eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3165552f7358SJed Brown 3166a1cb98faSBarry Smith Not Collective 3167552f7358SJed Brown 3168552f7358SJed Brown Input Parameters: 316960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3170a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3171b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3172b5a892a1SMatthew G. Knepley 3173552f7358SJed Brown Level: beginner 3174552f7358SJed Brown 3175a1cb98faSBarry Smith Notes: 3176a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3177a1cb98faSBarry Smith 3178a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3179a1cb98faSBarry Smith 31801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3181552f7358SJed Brown @*/ 3182d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3183d71ae5a4SJacob Faibussowitsch { 3184552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3185552f7358SJed Brown PetscInt pStart, pEnd; 3186552f7358SJed Brown PetscInt dof, off, c; 3187552f7358SJed Brown 3188552f7358SJed Brown PetscFunctionBegin; 3189552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31914f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 31929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3193db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3194db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 319563a3b9bcSJacob 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); 3196552f7358SJed Brown for (c = 0; c < dof; ++c) { 3197552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3198552f7358SJed Brown 31999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 32001dca8a05SBarry 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); 3201552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3202552f7358SJed Brown } 3203db485b19SStefano Zampini } else { 3204db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3205db485b19SStefano Zampini } 32063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3207552f7358SJed Brown } 3208552f7358SJed Brown 32097cd05799SMatthew G. Knepley /*@ 3210eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 32117cd05799SMatthew G. Knepley 3212a1cb98faSBarry Smith Not Collective 32137cd05799SMatthew G. Knepley 32147cd05799SMatthew G. Knepley Input Parameters: 321560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3216a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 32177cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 32187cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 32197cd05799SMatthew G. Knepley 32207cd05799SMatthew G. Knepley Level: beginner 32217cd05799SMatthew G. Knepley 32221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 32237cd05799SMatthew G. Knepley @*/ 3224d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3225d71ae5a4SJacob Faibussowitsch { 3226552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3227552f7358SJed Brown PetscInt pStart, pEnd; 3228552f7358SJed Brown PetscInt dof, off; 3229552f7358SJed Brown 3230552f7358SJed Brown PetscFunctionBegin; 3231552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3232a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 32339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 323463a3b9bcSJacob 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); 323563a3b9bcSJacob 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); 32369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 323763a3b9bcSJacob 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); 3238a03d55ffSStefano Zampini } 3239a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3240552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 32413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3242552f7358SJed Brown } 3243552f7358SJed Brown 32447cd05799SMatthew G. Knepley /*@ 3245eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 32467cd05799SMatthew G. Knepley 3247a1cb98faSBarry Smith Not Collective 32487cd05799SMatthew G. Knepley 32497cd05799SMatthew G. Knepley Input Parameters: 325060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3251a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 32527cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 32537cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 32547cd05799SMatthew G. Knepley 32557cd05799SMatthew G. Knepley Level: beginner 32567cd05799SMatthew G. Knepley 3257a1cb98faSBarry Smith Note: 3258a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3259b5a892a1SMatthew G. Knepley 32601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 32617cd05799SMatthew G. Knepley @*/ 3262d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3263d71ae5a4SJacob Faibussowitsch { 326477c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 326577c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 326677c88f5bSMatthew G Knepley PetscInt dof, off; 326777c88f5bSMatthew G Knepley 326877c88f5bSMatthew G Knepley PetscFunctionBegin; 326977c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3270a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 32719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 327263a3b9bcSJacob 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); 32739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 327463a3b9bcSJacob 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); 3275a03d55ffSStefano Zampini } 3276a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 327777c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 32783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 327977c88f5bSMatthew G Knepley } 328077c88f5bSMatthew G Knepley 32819f4ada15SMatthew G. Knepley /*@C 32829f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 32839f4ada15SMatthew G. Knepley 32849f4ada15SMatthew G. Knepley Not collective 32859f4ada15SMatthew G. Knepley 32869f4ada15SMatthew G. Knepley Input Parameters: 32879f4ada15SMatthew G. Knepley + dm - The DMPlex 32889f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 32899f4ada15SMatthew G. Knepley 32909f4ada15SMatthew G. Knepley Output Parameters: 329120f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 329220f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 32939f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 32949f4ada15SMatthew G. Knepley 32959f4ada15SMatthew G. Knepley Level: beginner 32969f4ada15SMatthew G. Knepley 32979f4ada15SMatthew G. Knepley Notes: 32989f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 32999f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 330020f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 33019f4ada15SMatthew G. Knepley with the identity. 33029f4ada15SMatthew G. Knepley 33039f4ada15SMatthew G. Knepley Fortran Notes: 330420f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 330520f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 33069f4ada15SMatthew G. Knepley 33071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 33089f4ada15SMatthew G. Knepley @*/ 33099f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 33109f4ada15SMatthew G. Knepley { 33119f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 33129f4ada15SMatthew G. Knepley 33139f4ada15SMatthew G. Knepley PetscFunctionBegin; 33149f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33159f4ada15SMatthew G. Knepley if (mesh->tr) { 33169f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 33179f4ada15SMatthew G. Knepley } else { 33189f4ada15SMatthew G. Knepley PetscInt off; 33199f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 33209f4ada15SMatthew G. Knepley PetscInt dof; 33219f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33229f4ada15SMatthew G. Knepley if (dof) { 33234f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 33244f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 33259f4ada15SMatthew G. Knepley } 33269f4ada15SMatthew G. Knepley } 33279f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3328072f5ffdSStefano Zampini if (cone) *cone = mesh->cones ? mesh->cones + off : NULL; // NULL + 0 is UB 3329072f5ffdSStefano Zampini if (ornt) *ornt = mesh->coneOrientations ? mesh->coneOrientations + off : NULL; 33309f4ada15SMatthew G. Knepley } 33313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33329f4ada15SMatthew G. Knepley } 33339f4ada15SMatthew G. Knepley 33349f4ada15SMatthew G. Knepley /*@C 33359f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 33369f4ada15SMatthew G. Knepley 333720f4b53cSBarry Smith Not Collective 33389f4ada15SMatthew G. Knepley 33399f4ada15SMatthew G. Knepley Input Parameters: 33409f4ada15SMatthew G. Knepley + dm - The DMPlex 334120f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33429f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 334320f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 33449f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 33459f4ada15SMatthew G. Knepley 33469f4ada15SMatthew G. Knepley Level: beginner 33479f4ada15SMatthew G. Knepley 33489f4ada15SMatthew G. Knepley Notes: 33499f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 33509f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 335120f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 33529f4ada15SMatthew G. Knepley with the identity. 33539f4ada15SMatthew G. Knepley 335460225df5SJacob Faibussowitsch Fortran Notes: 335520f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 335620f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 33579f4ada15SMatthew G. Knepley 33581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 33599f4ada15SMatthew G. Knepley @*/ 33609f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 33619f4ada15SMatthew G. Knepley { 33629f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 33639f4ada15SMatthew G. Knepley 33649f4ada15SMatthew G. Knepley PetscFunctionBegin; 33659f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33669f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 33673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33689f4ada15SMatthew G. Knepley } 33699f4ada15SMatthew G. Knepley 3370552f7358SJed Brown /*@ 3371eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3372552f7358SJed Brown 3373a1cb98faSBarry Smith Not Collective 3374552f7358SJed Brown 3375552f7358SJed Brown Input Parameters: 337660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3377a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3378552f7358SJed Brown 3379552f7358SJed Brown Output Parameter: 338020f4b53cSBarry Smith . size - The support size for point `p` 3381552f7358SJed Brown 3382552f7358SJed Brown Level: beginner 3383552f7358SJed Brown 33841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3385552f7358SJed Brown @*/ 3386d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3387d71ae5a4SJacob Faibussowitsch { 3388552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3389552f7358SJed Brown 3390552f7358SJed Brown PetscFunctionBegin; 3391552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33924f572ea9SToby Isaac PetscAssertPointer(size, 3); 33939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 33943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3395552f7358SJed Brown } 3396552f7358SJed Brown 3397552f7358SJed Brown /*@ 3398eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3399552f7358SJed Brown 3400a1cb98faSBarry Smith Not Collective 3401552f7358SJed Brown 3402552f7358SJed Brown Input Parameters: 340360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3404a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 340520f4b53cSBarry Smith - size - The support size for point `p` 3406552f7358SJed Brown 3407a1cb98faSBarry Smith Level: beginner 3408552f7358SJed Brown 3409552f7358SJed Brown Note: 341020f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3411552f7358SJed Brown 34121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3413552f7358SJed Brown @*/ 3414d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3415d71ae5a4SJacob Faibussowitsch { 3416552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3417552f7358SJed Brown 3418552f7358SJed Brown PetscFunctionBegin; 3419552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 34213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3422552f7358SJed Brown } 3423552f7358SJed Brown 3424552f7358SJed Brown /*@C 3425eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3426552f7358SJed Brown 3427a1cb98faSBarry Smith Not Collective 3428552f7358SJed Brown 3429552f7358SJed Brown Input Parameters: 343060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3431a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3432552f7358SJed Brown 3433552f7358SJed Brown Output Parameter: 343420f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p` 3435552f7358SJed Brown 3436552f7358SJed Brown Level: beginner 3437552f7358SJed Brown 343860225df5SJacob Faibussowitsch Fortran Notes: 3439a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3440a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 34413813dfbdSMatthew G Knepley 34421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3443552f7358SJed Brown @*/ 3444d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3445d71ae5a4SJacob Faibussowitsch { 3446552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3447552f7358SJed Brown PetscInt off; 3448552f7358SJed Brown 3449552f7358SJed Brown PetscFunctionBegin; 3450552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34514f572ea9SToby Isaac PetscAssertPointer(support, 3); 34529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3453072f5ffdSStefano Zampini *support = mesh->supports ? mesh->supports + off : NULL; //NULL + 0 is UB 34543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3455552f7358SJed Brown } 3456552f7358SJed Brown 3457552f7358SJed Brown /*@ 345892371b87SBarry 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 3459552f7358SJed Brown 3460a1cb98faSBarry Smith Not Collective 3461552f7358SJed Brown 3462552f7358SJed Brown Input Parameters: 346360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3464a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 346520f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p` 3466552f7358SJed Brown 3467552f7358SJed Brown Level: beginner 3468552f7358SJed Brown 3469a1cb98faSBarry Smith Note: 3470a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3471a1cb98faSBarry Smith 34721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3473552f7358SJed Brown @*/ 3474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3475d71ae5a4SJacob Faibussowitsch { 3476552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3477552f7358SJed Brown PetscInt pStart, pEnd; 3478552f7358SJed Brown PetscInt dof, off, c; 3479552f7358SJed Brown 3480552f7358SJed Brown PetscFunctionBegin; 3481552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 34839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 34844f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 34859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 348663a3b9bcSJacob 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); 3487552f7358SJed Brown for (c = 0; c < dof; ++c) { 348863a3b9bcSJacob 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); 3489552f7358SJed Brown mesh->supports[off + c] = support[c]; 3490552f7358SJed Brown } 34913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3492552f7358SJed Brown } 3493552f7358SJed Brown 34947cd05799SMatthew G. Knepley /*@ 3495eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 34967cd05799SMatthew G. Knepley 3497a1cb98faSBarry Smith Not Collective 34987cd05799SMatthew G. Knepley 34997cd05799SMatthew G. Knepley Input Parameters: 350060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3501a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35027cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 35037cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 35047cd05799SMatthew G. Knepley 35057cd05799SMatthew G. Knepley Level: beginner 35067cd05799SMatthew G. Knepley 35071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 35087cd05799SMatthew G. Knepley @*/ 3509d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3510d71ae5a4SJacob Faibussowitsch { 3511552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3512552f7358SJed Brown PetscInt pStart, pEnd; 3513552f7358SJed Brown PetscInt dof, off; 3514552f7358SJed Brown 3515552f7358SJed Brown PetscFunctionBegin; 3516552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 35189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 35199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 352063a3b9bcSJacob 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); 352163a3b9bcSJacob 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); 352263a3b9bcSJacob 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); 3523552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 35243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3525552f7358SJed Brown } 3526552f7358SJed Brown 3527b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3528d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3529d71ae5a4SJacob Faibussowitsch { 3530b5a892a1SMatthew G. Knepley switch (ct) { 3531b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3532b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3533b5a892a1SMatthew G. Knepley break; 3534b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3535b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3536b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3537b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3538b5a892a1SMatthew G. Knepley break; 3539b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3540b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3541b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3542b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3543b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3544b5a892a1SMatthew G. Knepley break; 3545d71ae5a4SJacob Faibussowitsch default: 3546d71ae5a4SJacob Faibussowitsch return o; 3547b5a892a1SMatthew G. Knepley } 3548b5a892a1SMatthew G. Knepley return o; 3549b5a892a1SMatthew G. Knepley } 3550b5a892a1SMatthew G. Knepley 3551b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3552d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3553d71ae5a4SJacob Faibussowitsch { 3554b5a892a1SMatthew G. Knepley switch (ct) { 3555b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3556b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3557b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3558b5a892a1SMatthew G. Knepley break; 3559b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3560b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3561b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3562b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3563b5a892a1SMatthew G. Knepley break; 3564b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3565b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3566b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3567b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3568b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3569b5a892a1SMatthew G. Knepley break; 3570d71ae5a4SJacob Faibussowitsch default: 3571d71ae5a4SJacob Faibussowitsch return o; 3572b5a892a1SMatthew G. Knepley } 3573b5a892a1SMatthew G. Knepley return o; 3574b5a892a1SMatthew G. Knepley } 3575b5a892a1SMatthew G. Knepley 3576b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3577d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3578d71ae5a4SJacob Faibussowitsch { 3579b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3580b5a892a1SMatthew G. Knepley 3581b5a892a1SMatthew G. Knepley PetscFunctionBegin; 35829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3583b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3584b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3585b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3586b5a892a1SMatthew G. Knepley 35879566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 35889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 35899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3590b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3591b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3592b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3593b5a892a1SMatthew G. Knepley 35949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3595b5a892a1SMatthew G. Knepley switch (ct) { 3596b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 35979566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 35989566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3599b5a892a1SMatthew G. Knepley break; 3600b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 36019566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 36029566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 36039566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3604b5a892a1SMatthew G. Knepley break; 3605b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 36069566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 36079566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 36089566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 36099566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3610b5a892a1SMatthew G. Knepley break; 3611d71ae5a4SJacob Faibussowitsch default: 3612d71ae5a4SJacob Faibussowitsch break; 3613b5a892a1SMatthew G. Knepley } 3614b5a892a1SMatthew G. Knepley } 3615b5a892a1SMatthew G. Knepley } 36163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3617b5a892a1SMatthew G. Knepley } 3618b5a892a1SMatthew G. Knepley 361909015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 362009015e70SStefano Zampini { 362109015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 362209015e70SStefano Zampini 362309015e70SStefano Zampini PetscFunctionBeginHot; 362409015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 362509015e70SStefano Zampini if (useCone) { 362609015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 362709015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 362809015e70SStefano Zampini } else { 362909015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 363009015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 363109015e70SStefano Zampini } 363209015e70SStefano Zampini } else { 363309015e70SStefano Zampini if (useCone) { 363409015e70SStefano Zampini const PetscSection s = mesh->coneSection; 363509015e70SStefano Zampini const PetscInt ps = p - s->pStart; 363609015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 363709015e70SStefano Zampini 363809015e70SStefano Zampini *size = s->atlasDof[ps]; 363909015e70SStefano Zampini *arr = mesh->cones + off; 364009015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 364109015e70SStefano Zampini } else { 364209015e70SStefano Zampini const PetscSection s = mesh->supportSection; 364309015e70SStefano Zampini const PetscInt ps = p - s->pStart; 364409015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 364509015e70SStefano Zampini 364609015e70SStefano Zampini *size = s->atlasDof[ps]; 364709015e70SStefano Zampini *arr = mesh->supports + off; 364809015e70SStefano Zampini } 364909015e70SStefano Zampini } 365009015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 365109015e70SStefano Zampini } 365209015e70SStefano Zampini 365309015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 365409015e70SStefano Zampini { 365509015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 365609015e70SStefano Zampini 365709015e70SStefano Zampini PetscFunctionBeginHot; 365809015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 365909015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 366009015e70SStefano Zampini } 366109015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 366209015e70SStefano Zampini } 366309015e70SStefano Zampini 3664d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3665d71ae5a4SJacob Faibussowitsch { 3666b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3667b5a892a1SMatthew G. Knepley PetscInt *closure; 3668b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3669b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3670b5a892a1SMatthew G. Knepley 3671b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3672b5a892a1SMatthew G. Knepley if (ornt) { 36739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3674b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3675b5a892a1SMatthew G. Knepley } 3676b5a892a1SMatthew G. Knepley if (*points) { 3677b5a892a1SMatthew G. Knepley closure = *points; 3678b5a892a1SMatthew G. Knepley } else { 3679b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 36809566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 36819566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3682b5a892a1SMatthew G. Knepley } 368309015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3684b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3685b5a892a1SMatthew G. Knepley closure[off++] = p; 3686b5a892a1SMatthew G. Knepley closure[off++] = 0; 3687b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3688b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3689b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3690b5a892a1SMatthew G. Knepley } 3691b5a892a1SMatthew G. Knepley } else { 36925f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3693b5a892a1SMatthew G. Knepley 3694b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3695b5a892a1SMatthew G. Knepley closure[off++] = p; 3696b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3697b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3698b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3699b5a892a1SMatthew G. Knepley 37009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3701b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3702b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3703b5a892a1SMatthew G. Knepley } 3704b5a892a1SMatthew G. Knepley } 370509015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3706b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3707b5a892a1SMatthew G. Knepley if (points) *points = closure; 37083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3709b5a892a1SMatthew G. Knepley } 3710b5a892a1SMatthew G. Knepley 3711d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3712d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3713d71ae5a4SJacob Faibussowitsch { 3714b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3715b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3716b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3717b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3718b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3719b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3720b5a892a1SMatthew G. Knepley 3721b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 37229566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 372309015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 37249566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3725b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3726b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3727b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 37289371c9d4SSatish Balay if (*points) { 37299371c9d4SSatish Balay pts = *points; 37309371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3731b5a892a1SMatthew G. Knepley c = 0; 3732b5a892a1SMatthew G. Knepley pts[c++] = point; 3733b5a892a1SMatthew G. Knepley pts[c++] = o; 37349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 37359566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 37369371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 37379371c9d4SSatish Balay pts[c++] = closure[cl]; 37389371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 37399371c9d4SSatish Balay } 37409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 37419371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 37429371c9d4SSatish Balay pts[c++] = closure[cl]; 37439371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 37449371c9d4SSatish Balay } 37459566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3746b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 37479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3748b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3749b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3750b5a892a1SMatthew G. Knepley } 375109015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 3752b5a892a1SMatthew G. Knepley if (dim >= 3) { 3753b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3754b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3755b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3756b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3757b5a892a1SMatthew G. Knepley 37589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3759b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 376009015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3761b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3762b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3763b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3764b5a892a1SMatthew G. Knepley 37659371c9d4SSatish Balay for (i = 0; i < c; i += 2) 37669371c9d4SSatish Balay if (pts[i] == cp) break; 3767b5a892a1SMatthew G. Knepley if (i == c) { 37689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3769b5a892a1SMatthew G. Knepley pts[c++] = cp; 3770b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3771b5a892a1SMatthew G. Knepley } 3772b5a892a1SMatthew G. Knepley } 377309015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3774b5a892a1SMatthew G. Knepley } 3775b5a892a1SMatthew G. Knepley } 3776b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3777b5a892a1SMatthew G. Knepley *points = pts; 37783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3779b5a892a1SMatthew G. Knepley } 3780b5a892a1SMatthew G. Knepley 3781d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3782d71ae5a4SJacob Faibussowitsch { 3783b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3784b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3785b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3786b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3787b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3788b5a892a1SMatthew G. Knepley 3789b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 37909566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3791b5a892a1SMatthew G. Knepley if (depth == 1) { 37929566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 37933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3794b5a892a1SMatthew G. Knepley } 37959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3796b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3797b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 37989566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 37993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3800b5a892a1SMatthew G. Knepley } 38019566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3802b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3803b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3804b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 38059566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 38069371c9d4SSatish Balay if (*points) { 38079371c9d4SSatish Balay closure = *points; 38089371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3809b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3810b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3811b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3812b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3813b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3814b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3815b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3816b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3817b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3818b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 3819b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 382009015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 3821b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3822b5a892a1SMatthew G. Knepley 3823b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3824b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2; 382563a3b9bcSJacob 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); 3826b5a892a1SMatthew G. Knepley } 382709015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 3828b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3829b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 3830b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 3831b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 38329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3833b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3834b5a892a1SMatthew G. Knepley PetscInt c; 3835b5a892a1SMatthew G. Knepley 3836b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3837b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3838b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3839b5a892a1SMatthew G. Knepley } 3840b5a892a1SMatthew G. Knepley if (c == closureSize) { 3841b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3842b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3843b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3844b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3845b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3846b5a892a1SMatthew G. Knepley } 3847b5a892a1SMatthew G. Knepley } 384809015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 3849b5a892a1SMatthew G. Knepley } 38509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 3851b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 3852b5a892a1SMatthew G. Knepley if (points) *points = closure; 38533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3854b5a892a1SMatthew G. Knepley } 3855b5a892a1SMatthew G. Knepley 3856552f7358SJed Brown /*@C 3857eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3858552f7358SJed Brown 3859a1cb98faSBarry Smith Not Collective 3860552f7358SJed Brown 3861552f7358SJed Brown Input Parameters: 3862a1cb98faSBarry Smith + dm - The `DMPLEX` 3863b5a892a1SMatthew G. Knepley . p - The mesh point 3864a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 3865552f7358SJed Brown 38666b867d5aSJose E. Roman Input/Output Parameter: 38676b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 386820f4b53cSBarry Smith if `NULL` on input, internal storage will be returned, otherwise the provided array is used 38696b867d5aSJose E. Roman 38706b867d5aSJose E. Roman Output Parameter: 387120f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 3872552f7358SJed Brown 3873a1cb98faSBarry Smith Level: beginner 3874a1cb98faSBarry Smith 3875552f7358SJed Brown Note: 387620f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 3877552f7358SJed Brown 387860225df5SJacob Faibussowitsch Fortran Notes: 387920f4b53cSBarry Smith The `numPoints` argument is not present in the Fortran binding since it is internal to the array. 38803813dfbdSMatthew G Knepley 38811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3882552f7358SJed Brown @*/ 3883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3884d71ae5a4SJacob Faibussowitsch { 3885b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3886552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38874f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 38884f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 38899566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 38903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38919bf0dad6SMatthew G. Knepley } 38929bf0dad6SMatthew G. Knepley 3893552f7358SJed Brown /*@C 3894eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3895552f7358SJed Brown 3896a1cb98faSBarry Smith Not Collective 3897552f7358SJed Brown 3898552f7358SJed Brown Input Parameters: 3899a1cb98faSBarry Smith + dm - The `DMPLEX` 3900b5a892a1SMatthew G. Knepley . p - The mesh point 3901a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 390220f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 3903b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3904552f7358SJed Brown 3905a1cb98faSBarry Smith Level: beginner 3906a1cb98faSBarry Smith 3907552f7358SJed Brown Note: 390820f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 3909552f7358SJed Brown 39101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3911552f7358SJed Brown @*/ 3912d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3913d71ae5a4SJacob Faibussowitsch { 3914b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3915552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39164ff43b2cSJed Brown if (numPoints) *numPoints = 0; 39179566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 39183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3919552f7358SJed Brown } 3920552f7358SJed Brown 3921552f7358SJed Brown /*@ 3922eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3923552f7358SJed Brown 3924a1cb98faSBarry Smith Not Collective 3925552f7358SJed Brown 3926552f7358SJed Brown Input Parameter: 392760225df5SJacob Faibussowitsch . dm - The `DMPLEX` 3928552f7358SJed Brown 3929552f7358SJed Brown Output Parameters: 3930552f7358SJed Brown + maxConeSize - The maximum number of in-edges 3931552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 3932552f7358SJed Brown 3933552f7358SJed Brown Level: beginner 3934552f7358SJed Brown 39351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3936552f7358SJed Brown @*/ 3937d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3938d71ae5a4SJacob Faibussowitsch { 3939552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3940552f7358SJed Brown 3941552f7358SJed Brown PetscFunctionBegin; 3942552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39431baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 39441baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 39453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3946552f7358SJed Brown } 3947552f7358SJed Brown 3948d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 3949d71ae5a4SJacob Faibussowitsch { 3950552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 39516302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 3952552f7358SJed Brown 3953552f7358SJed Brown PetscFunctionBegin; 3954552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 39569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 39579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 39589566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 39596302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 39606302a7fbSVaclav Hapla if (maxSupportSize) { 39619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 39629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 39639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 3964552f7358SJed Brown } 39653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3966552f7358SJed Brown } 3967552f7358SJed Brown 3968d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3969d71ae5a4SJacob Faibussowitsch { 3970552f7358SJed Brown PetscFunctionBegin; 39719566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 39729566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 3973ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 3974736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 397595602cf2SAlexis Marboeuf PetscSF sfNatural; 3976f94b4a02SBlaise Bourdin 39773dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 39789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 397995602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 3980c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 3981f94b4a02SBlaise Bourdin } 39823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3983552f7358SJed Brown } 3984552f7358SJed Brown 3985d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3986d71ae5a4SJacob Faibussowitsch { 39873dcd263cSBlaise Bourdin PetscInt i = 0; 39882adcc780SMatthew G. Knepley 39892adcc780SMatthew G. Knepley PetscFunctionBegin; 39909566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 39919566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 3992c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 39933dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 39943dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 399595602cf2SAlexis Marboeuf PetscSF sfNatural; 39963dcd263cSBlaise Bourdin 39973dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 39989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 3999c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 400095602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4001c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 40023dcd263cSBlaise Bourdin break; 40033dcd263cSBlaise Bourdin } 40043dcd263cSBlaise Bourdin } 40053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40062adcc780SMatthew G. Knepley } 40072adcc780SMatthew G. Knepley 4008552f7358SJed Brown /*@ 4009eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4010552f7358SJed Brown 4011a1cb98faSBarry Smith Not Collective 4012552f7358SJed Brown 4013552f7358SJed Brown Input Parameter: 401460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4015552f7358SJed Brown 4016552f7358SJed Brown Level: beginner 4017552f7358SJed Brown 4018a1cb98faSBarry Smith Note: 4019a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4020a1cb98faSBarry Smith 40211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4022552f7358SJed Brown @*/ 4023d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4024d71ae5a4SJacob Faibussowitsch { 4025552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4026552f7358SJed Brown PetscInt *offsets; 4027552f7358SJed Brown PetscInt supportSize; 4028552f7358SJed Brown PetscInt pStart, pEnd, p; 4029552f7358SJed Brown 4030552f7358SJed Brown PetscFunctionBegin; 4031552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 403228b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 40339566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4034552f7358SJed Brown /* Calculate support sizes */ 40359566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4036552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4037552f7358SJed Brown PetscInt dof, off, c; 4038552f7358SJed Brown 40399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 40409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 404148a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4042552f7358SJed Brown } 40439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4044552f7358SJed Brown /* Calculate supports */ 40459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 40469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 40479566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4048552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4049552f7358SJed Brown PetscInt dof, off, c; 4050552f7358SJed Brown 40519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 40529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4053552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4054552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4055552f7358SJed Brown PetscInt offS; 4056552f7358SJed Brown 40579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 40580d644c17SKarl Rupp 4059552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4060552f7358SJed Brown ++offsets[q]; 4061552f7358SJed Brown } 4062552f7358SJed Brown } 40639566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 40649566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 40653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4066552f7358SJed Brown } 4067552f7358SJed Brown 4068d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4069d71ae5a4SJacob Faibussowitsch { 4070277ea44aSLisandro Dalcin IS stratumIS; 4071277ea44aSLisandro Dalcin 4072277ea44aSLisandro Dalcin PetscFunctionBegin; 40733ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 407476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4075277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4076277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 40779566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4078277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 40799566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 40809371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 40819371c9d4SSatish Balay overlap = PETSC_TRUE; 40829371c9d4SSatish Balay break; 40839371c9d4SSatish Balay } 4084277ea44aSLisandro Dalcin } 408563a3b9bcSJacob 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); 4086277ea44aSLisandro Dalcin } 40879566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 40889566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 40899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 40903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4091277ea44aSLisandro Dalcin } 4092277ea44aSLisandro Dalcin 4093552f7358SJed Brown /*@ 4094a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4095552f7358SJed Brown 409620f4b53cSBarry Smith Collective 4097552f7358SJed Brown 4098552f7358SJed Brown Input Parameter: 409960225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4100552f7358SJed Brown 4101a1cb98faSBarry Smith Level: beginner 4102552f7358SJed Brown 4103552f7358SJed Brown Notes: 4104a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4105a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4106a4e35b19SJacob Faibussowitsch 4107a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4108a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4109a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4110b1bb481bSMatthew 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 4111a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4112a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4113a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4114552f7358SJed Brown 4115b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4116b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4117b1bb481bSMatthew 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 4118b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4119a1cb98faSBarry Smith .vb 4120a1cb98faSBarry Smith cone(c0) = {e0, v2} 4121a1cb98faSBarry Smith cone(e0) = {v0, v1} 4122a1cb98faSBarry Smith .ve 4123a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4124a1cb98faSBarry Smith .vb 4125a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4126a1cb98faSBarry Smith depth 1 = {e0, c0} 4127a1cb98faSBarry Smith .ve 4128b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4129b1bb481bSMatthew Knepley 4130a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4131552f7358SJed Brown 41321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4133552f7358SJed Brown @*/ 4134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4135d71ae5a4SJacob Faibussowitsch { 4136df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4137aa50250dSMatthew G. Knepley DMLabel label; 4138552f7358SJed Brown PetscInt pStart, pEnd, p; 4139552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 4140552f7358SJed Brown 4141552f7358SJed Brown PetscFunctionBegin; 4142552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4144277ea44aSLisandro Dalcin 4145277ea44aSLisandro Dalcin /* Create depth label */ 41469566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 41479566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 41489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4149277ea44aSLisandro Dalcin 4150277ea44aSLisandro Dalcin { 4151552f7358SJed Brown /* Initialize roots and count leaves */ 4152277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4153277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 4154552f7358SJed Brown PetscInt coneSize, supportSize; 4155552f7358SJed Brown 4156277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 41579566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 41589566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4159552f7358SJed Brown if (!coneSize && supportSize) { 4160277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4161277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4162552f7358SJed Brown ++numRoots; 4163552f7358SJed Brown } else if (!supportSize && coneSize) { 4164552f7358SJed Brown ++numLeaves; 4165552f7358SJed Brown } else if (!supportSize && !coneSize) { 4166552f7358SJed Brown /* Isolated points */ 4167277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4168277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4169552f7358SJed Brown } 4170552f7358SJed Brown } 41719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4172277ea44aSLisandro Dalcin } 4173277ea44aSLisandro Dalcin 4174552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 4175277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4176277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 4177552f7358SJed Brown PetscInt coneSize, supportSize; 4178552f7358SJed Brown 4179277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 41809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 41819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4182552f7358SJed Brown if (!supportSize && coneSize) { 4183277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4184277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4185552f7358SJed Brown } 4186552f7358SJed Brown } 41879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4188552f7358SJed Brown } else { 4189277ea44aSLisandro Dalcin PetscInt level = 0; 4190277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 4191552f7358SJed Brown 41929566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4193277ea44aSLisandro Dalcin while (qEnd > qStart) { 4194277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4195277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 419674ef644bSMatthew G. Knepley 4197277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 419874ef644bSMatthew G. Knepley const PetscInt *support; 419974ef644bSMatthew G. Knepley PetscInt supportSize, s; 420074ef644bSMatthew G. Knepley 42019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 42029566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &support)); 420374ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 4204277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 4205277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 4206552f7358SJed Brown } 4207552f7358SJed Brown } 42089566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &level)); 42099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 42109566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 421174ef644bSMatthew G. Knepley } 421274ef644bSMatthew G. Knepley } 4213bf4602e4SToby Isaac { /* just in case there is an empty process */ 4214bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4215bf4602e4SToby Isaac 42169566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4217712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 421848a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4219bf4602e4SToby Isaac } 42209566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 42219566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 42223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4223552f7358SJed Brown } 4224552f7358SJed Brown 4225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4226d71ae5a4SJacob Faibussowitsch { 4227412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4228412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4229ba2698f1SMatthew G. Knepley 4230412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 42319566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 42329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 42339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4234ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4235ba2698f1SMatthew G. Knepley if (depth <= 1) { 4236ba2698f1SMatthew G. Knepley switch (pdepth) { 4237d71ae5a4SJacob Faibussowitsch case 0: 4238d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4239d71ae5a4SJacob Faibussowitsch break; 4240ba2698f1SMatthew G. Knepley case 1: 4241ba2698f1SMatthew G. Knepley switch (coneSize) { 4242d71ae5a4SJacob Faibussowitsch case 2: 4243d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4244d71ae5a4SJacob Faibussowitsch break; 4245d71ae5a4SJacob Faibussowitsch case 3: 4246d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4247d71ae5a4SJacob Faibussowitsch break; 4248ba2698f1SMatthew G. Knepley case 4: 4249ba2698f1SMatthew G. Knepley switch (dim) { 4250d71ae5a4SJacob Faibussowitsch case 2: 4251d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4252d71ae5a4SJacob Faibussowitsch break; 4253d71ae5a4SJacob Faibussowitsch case 3: 4254d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4255d71ae5a4SJacob Faibussowitsch break; 4256d71ae5a4SJacob Faibussowitsch default: 4257d71ae5a4SJacob Faibussowitsch break; 4258ba2698f1SMatthew G. Knepley } 4259ba2698f1SMatthew G. Knepley break; 4260d71ae5a4SJacob Faibussowitsch case 5: 4261d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4262d71ae5a4SJacob Faibussowitsch break; 4263d71ae5a4SJacob Faibussowitsch case 6: 4264d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4265d71ae5a4SJacob Faibussowitsch break; 4266d71ae5a4SJacob Faibussowitsch case 8: 4267d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4268d71ae5a4SJacob Faibussowitsch break; 4269d71ae5a4SJacob Faibussowitsch default: 4270d71ae5a4SJacob Faibussowitsch break; 4271ba2698f1SMatthew G. Knepley } 4272ba2698f1SMatthew G. Knepley } 4273ba2698f1SMatthew G. Knepley } else { 4274ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4275ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4276ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4277ba2698f1SMatthew G. Knepley switch (dim) { 4278ba2698f1SMatthew G. Knepley case 1: 4279ba2698f1SMatthew G. Knepley switch (coneSize) { 4280d71ae5a4SJacob Faibussowitsch case 2: 4281d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4282d71ae5a4SJacob Faibussowitsch break; 4283d71ae5a4SJacob Faibussowitsch default: 4284d71ae5a4SJacob Faibussowitsch break; 4285ba2698f1SMatthew G. Knepley } 4286ba2698f1SMatthew G. Knepley break; 4287ba2698f1SMatthew G. Knepley case 2: 4288ba2698f1SMatthew G. Knepley switch (coneSize) { 4289d71ae5a4SJacob Faibussowitsch case 3: 4290d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4291d71ae5a4SJacob Faibussowitsch break; 4292d71ae5a4SJacob Faibussowitsch case 4: 4293d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4294d71ae5a4SJacob Faibussowitsch break; 4295d71ae5a4SJacob Faibussowitsch default: 4296d71ae5a4SJacob Faibussowitsch break; 4297ba2698f1SMatthew G. Knepley } 4298ba2698f1SMatthew G. Knepley break; 4299ba2698f1SMatthew G. Knepley case 3: 4300ba2698f1SMatthew G. Knepley switch (coneSize) { 4301d71ae5a4SJacob Faibussowitsch case 4: 4302d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4303d71ae5a4SJacob Faibussowitsch break; 43049371c9d4SSatish Balay case 5: { 4305da9060c4SMatthew G. Knepley const PetscInt *cone; 4306da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4307da9060c4SMatthew G. Knepley 43089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 43099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4310da9060c4SMatthew G. Knepley switch (faceConeSize) { 4311d71ae5a4SJacob Faibussowitsch case 3: 4312d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4313d71ae5a4SJacob Faibussowitsch break; 4314d71ae5a4SJacob Faibussowitsch case 4: 4315d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4316d71ae5a4SJacob Faibussowitsch break; 4317da9060c4SMatthew G. Knepley } 43189371c9d4SSatish Balay } break; 4319d71ae5a4SJacob Faibussowitsch case 6: 4320d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4321d71ae5a4SJacob Faibussowitsch break; 4322d71ae5a4SJacob Faibussowitsch default: 4323d71ae5a4SJacob Faibussowitsch break; 4324ba2698f1SMatthew G. Knepley } 4325ba2698f1SMatthew G. Knepley break; 4326d71ae5a4SJacob Faibussowitsch default: 4327d71ae5a4SJacob Faibussowitsch break; 4328ba2698f1SMatthew G. Knepley } 4329ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4330ba2698f1SMatthew G. Knepley switch (coneSize) { 4331d71ae5a4SJacob Faibussowitsch case 2: 4332d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4333d71ae5a4SJacob Faibussowitsch break; 4334d71ae5a4SJacob Faibussowitsch case 3: 4335d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4336d71ae5a4SJacob Faibussowitsch break; 4337d71ae5a4SJacob Faibussowitsch case 4: 4338d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4339d71ae5a4SJacob Faibussowitsch break; 4340d71ae5a4SJacob Faibussowitsch default: 4341d71ae5a4SJacob Faibussowitsch break; 4342ba2698f1SMatthew G. Knepley } 4343ba2698f1SMatthew G. Knepley } 4344ba2698f1SMatthew G. Knepley } 4345412e9a14SMatthew G. Knepley *pt = ct; 43463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4347ba2698f1SMatthew G. Knepley } 4348412e9a14SMatthew G. Knepley 4349412e9a14SMatthew G. Knepley /*@ 4350412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4351412e9a14SMatthew G. Knepley 435220f4b53cSBarry Smith Collective 4353412e9a14SMatthew G. Knepley 4354412e9a14SMatthew G. Knepley Input Parameter: 435560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4356412e9a14SMatthew G. Knepley 4357412e9a14SMatthew G. Knepley Level: developer 4358412e9a14SMatthew G. Knepley 4359a1cb98faSBarry Smith Note: 4360a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4361a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4362a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4363412e9a14SMatthew G. Knepley 4364a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4365a1cb98faSBarry Smith 43661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4367412e9a14SMatthew G. Knepley @*/ 4368d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4369d71ae5a4SJacob Faibussowitsch { 4370412e9a14SMatthew G. Knepley DM_Plex *mesh; 4371412e9a14SMatthew G. Knepley DMLabel ctLabel; 4372412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4373412e9a14SMatthew G. Knepley 4374412e9a14SMatthew G. Knepley PetscFunctionBegin; 4375412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4376412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 43779566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 43789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 43799566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 438021027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 438121027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4382412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4383327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4384412e9a14SMatthew G. Knepley PetscInt pdepth; 4385412e9a14SMatthew G. Knepley 43869566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 43879566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 438863a3b9bcSJacob Faibussowitsch PetscCheck(ct != DM_POLYTOPE_UNKNOWN, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 43899566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 439021027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = ct; 4391412e9a14SMatthew G. Knepley } 43929566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 43939566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 43943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4395ba2698f1SMatthew G. Knepley } 4396ba2698f1SMatthew G. Knepley 4397552f7358SJed Brown /*@C 4398552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4399552f7358SJed Brown 4400552f7358SJed Brown Not Collective 4401552f7358SJed Brown 4402552f7358SJed Brown Input Parameters: 4403a1cb98faSBarry Smith + dm - The `DMPLEX` object 4404552f7358SJed Brown . numPoints - The number of input points for the join 4405552f7358SJed Brown - points - The input points 4406552f7358SJed Brown 4407552f7358SJed Brown Output Parameters: 4408552f7358SJed Brown + numCoveredPoints - The number of points in the join 4409552f7358SJed Brown - coveredPoints - The points in the join 4410552f7358SJed Brown 4411552f7358SJed Brown Level: intermediate 4412552f7358SJed Brown 4413a1cb98faSBarry Smith Note: 4414a1cb98faSBarry Smith Currently, this is restricted to a single level join 4415552f7358SJed Brown 441660225df5SJacob Faibussowitsch Fortran Notes: 441720f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 44183813dfbdSMatthew G Knepley 44191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4420552f7358SJed Brown @*/ 4421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4422d71ae5a4SJacob Faibussowitsch { 4423552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4424552f7358SJed Brown PetscInt *join[2]; 4425552f7358SJed Brown PetscInt joinSize, i = 0; 4426552f7358SJed Brown PetscInt dof, off, p, c, m; 44276302a7fbSVaclav Hapla PetscInt maxSupportSize; 4428552f7358SJed Brown 4429552f7358SJed Brown PetscFunctionBegin; 4430552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 44314f572ea9SToby Isaac PetscAssertPointer(points, 3); 44324f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 44334f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 44346302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 44356302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 44366302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4437552f7358SJed Brown /* Copy in support of first point */ 44389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 44399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4440ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4441552f7358SJed Brown /* Check each successive support */ 4442552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4443552f7358SJed Brown PetscInt newJoinSize = 0; 4444552f7358SJed Brown 44459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 44469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4447552f7358SJed Brown for (c = 0; c < dof; ++c) { 4448552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4449552f7358SJed Brown 4450552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4451552f7358SJed Brown if (point == join[i][m]) { 4452552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4453552f7358SJed Brown break; 4454552f7358SJed Brown } 4455552f7358SJed Brown } 4456552f7358SJed Brown } 4457552f7358SJed Brown joinSize = newJoinSize; 4458552f7358SJed Brown i = 1 - i; 4459552f7358SJed Brown } 4460552f7358SJed Brown *numCoveredPoints = joinSize; 4461552f7358SJed Brown *coveredPoints = join[i]; 44626302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 44633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4464552f7358SJed Brown } 4465552f7358SJed Brown 4466552f7358SJed Brown /*@C 4467552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4468552f7358SJed Brown 4469552f7358SJed Brown Not Collective 4470552f7358SJed Brown 4471552f7358SJed Brown Input Parameters: 4472a1cb98faSBarry Smith + dm - The `DMPLEX` object 4473552f7358SJed Brown . numPoints - The number of input points for the join 4474552f7358SJed Brown - points - The input points 4475552f7358SJed Brown 4476552f7358SJed Brown Output Parameters: 4477552f7358SJed Brown + numCoveredPoints - The number of points in the join 4478552f7358SJed Brown - coveredPoints - The points in the join 4479552f7358SJed Brown 4480552f7358SJed Brown Level: intermediate 4481552f7358SJed Brown 448260225df5SJacob Faibussowitsch Fortran Notes: 448320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4484a1cb98faSBarry Smith 44851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4486552f7358SJed Brown @*/ 4487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4488d71ae5a4SJacob Faibussowitsch { 4489552f7358SJed Brown PetscFunctionBegin; 4490552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 44914f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 44924f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 44934f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 44949566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4495d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 44963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4497552f7358SJed Brown } 4498552f7358SJed Brown 4499552f7358SJed Brown /*@C 4500552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4501552f7358SJed Brown 4502552f7358SJed Brown Not Collective 4503552f7358SJed Brown 4504552f7358SJed Brown Input Parameters: 4505a1cb98faSBarry Smith + dm - The `DMPLEX` object 4506552f7358SJed Brown . numPoints - The number of input points for the join 4507552f7358SJed Brown - points - The input points 4508552f7358SJed Brown 4509552f7358SJed Brown Output Parameters: 4510552f7358SJed Brown + numCoveredPoints - The number of points in the join 4511552f7358SJed Brown - coveredPoints - The points in the join 4512552f7358SJed Brown 4513552f7358SJed Brown Level: intermediate 4514552f7358SJed Brown 451560225df5SJacob Faibussowitsch Fortran Notes: 451620f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4517a1cb98faSBarry Smith 45181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4519552f7358SJed Brown @*/ 4520d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4521d71ae5a4SJacob Faibussowitsch { 4522552f7358SJed Brown PetscInt *offsets, **closures; 4523552f7358SJed Brown PetscInt *join[2]; 4524552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 452524c766afSToby Isaac PetscInt p, d, c, m, ms; 4526552f7358SJed Brown 4527552f7358SJed Brown PetscFunctionBegin; 4528552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 45294f572ea9SToby Isaac PetscAssertPointer(points, 3); 45304f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 45314f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4532552f7358SJed Brown 45339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 45349566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 45359566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 45366302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 453724c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 45389566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 45399566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4540552f7358SJed Brown 4541552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4542552f7358SJed Brown PetscInt closureSize; 4543552f7358SJed Brown 45449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 45450d644c17SKarl Rupp 4546552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4547552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4548552f7358SJed Brown PetscInt pStart, pEnd, i; 4549552f7358SJed Brown 45509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4551552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4552552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4553552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4554552f7358SJed Brown break; 4555552f7358SJed Brown } 4556552f7358SJed Brown } 4557552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4558552f7358SJed Brown } 455963a3b9bcSJacob 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); 4560552f7358SJed Brown } 4561552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4562552f7358SJed Brown PetscInt dof; 4563552f7358SJed Brown 4564552f7358SJed Brown /* Copy in support of first point */ 4565552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4566ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4567552f7358SJed Brown /* Check each successive cone */ 4568552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4569552f7358SJed Brown PetscInt newJoinSize = 0; 4570552f7358SJed Brown 4571552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4572552f7358SJed Brown for (c = 0; c < dof; ++c) { 4573552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4574552f7358SJed Brown 4575552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4576552f7358SJed Brown if (point == join[i][m]) { 4577552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4578552f7358SJed Brown break; 4579552f7358SJed Brown } 4580552f7358SJed Brown } 4581552f7358SJed Brown } 4582552f7358SJed Brown joinSize = newJoinSize; 4583552f7358SJed Brown i = 1 - i; 4584552f7358SJed Brown } 4585552f7358SJed Brown if (joinSize) break; 4586552f7358SJed Brown } 4587552f7358SJed Brown *numCoveredPoints = joinSize; 4588552f7358SJed Brown *coveredPoints = join[i]; 458948a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 45909566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 45919566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 45926302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 45933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4594552f7358SJed Brown } 4595552f7358SJed Brown 4596552f7358SJed Brown /*@C 4597552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4598552f7358SJed Brown 4599552f7358SJed Brown Not Collective 4600552f7358SJed Brown 4601552f7358SJed Brown Input Parameters: 4602a1cb98faSBarry Smith + dm - The `DMPLEX` object 4603552f7358SJed Brown . numPoints - The number of input points for the meet 4604552f7358SJed Brown - points - The input points 4605552f7358SJed Brown 4606552f7358SJed Brown Output Parameters: 460760225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 460860225df5SJacob Faibussowitsch - coveringPoints - The points in the meet 4609552f7358SJed Brown 4610552f7358SJed Brown Level: intermediate 4611552f7358SJed Brown 4612a1cb98faSBarry Smith Note: 4613a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4614552f7358SJed Brown 46153813dfbdSMatthew G Knepley Fortran Notes: 461620f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 46173813dfbdSMatthew G Knepley 46181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4619552f7358SJed Brown @*/ 4620d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4621d71ae5a4SJacob Faibussowitsch { 4622552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4623552f7358SJed Brown PetscInt *meet[2]; 4624552f7358SJed Brown PetscInt meetSize, i = 0; 4625552f7358SJed Brown PetscInt dof, off, p, c, m; 46266302a7fbSVaclav Hapla PetscInt maxConeSize; 4627552f7358SJed Brown 4628552f7358SJed Brown PetscFunctionBegin; 4629552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46304f572ea9SToby Isaac PetscAssertPointer(points, 3); 46314f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 46324f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 46336302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 46346302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 46356302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4636552f7358SJed Brown /* Copy in cone of first point */ 46379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 46389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4639ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4640552f7358SJed Brown /* Check each successive cone */ 4641552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4642552f7358SJed Brown PetscInt newMeetSize = 0; 4643552f7358SJed Brown 46449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 46459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4646552f7358SJed Brown for (c = 0; c < dof; ++c) { 4647552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4648552f7358SJed Brown 4649552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4650552f7358SJed Brown if (point == meet[i][m]) { 4651552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4652552f7358SJed Brown break; 4653552f7358SJed Brown } 4654552f7358SJed Brown } 4655552f7358SJed Brown } 4656552f7358SJed Brown meetSize = newMeetSize; 4657552f7358SJed Brown i = 1 - i; 4658552f7358SJed Brown } 4659552f7358SJed Brown *numCoveringPoints = meetSize; 4660552f7358SJed Brown *coveringPoints = meet[i]; 46616302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 46623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4663552f7358SJed Brown } 4664552f7358SJed Brown 4665552f7358SJed Brown /*@C 4666552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4667552f7358SJed Brown 4668552f7358SJed Brown Not Collective 4669552f7358SJed Brown 4670552f7358SJed Brown Input Parameters: 4671a1cb98faSBarry Smith + dm - The `DMPLEX` object 4672552f7358SJed Brown . numPoints - The number of input points for the meet 4673552f7358SJed Brown - points - The input points 4674552f7358SJed Brown 4675552f7358SJed Brown Output Parameters: 4676552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4677552f7358SJed Brown - coveredPoints - The points in the meet 4678552f7358SJed Brown 4679552f7358SJed Brown Level: intermediate 4680552f7358SJed Brown 468160225df5SJacob Faibussowitsch Fortran Notes: 468220f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 46833813dfbdSMatthew G Knepley 46841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4685552f7358SJed Brown @*/ 4686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4687d71ae5a4SJacob Faibussowitsch { 4688552f7358SJed Brown PetscFunctionBegin; 4689552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46904f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 46914f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 46924f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46939566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4694d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 46953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4696552f7358SJed Brown } 4697552f7358SJed Brown 4698552f7358SJed Brown /*@C 4699552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4700552f7358SJed Brown 4701552f7358SJed Brown Not Collective 4702552f7358SJed Brown 4703552f7358SJed Brown Input Parameters: 4704a1cb98faSBarry Smith + dm - The `DMPLEX` object 4705552f7358SJed Brown . numPoints - The number of input points for the meet 4706552f7358SJed Brown - points - The input points 4707552f7358SJed Brown 4708552f7358SJed Brown Output Parameters: 4709552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4710552f7358SJed Brown - coveredPoints - The points in the meet 4711552f7358SJed Brown 4712552f7358SJed Brown Level: intermediate 4713552f7358SJed Brown 471460225df5SJacob Faibussowitsch Fortran Notes: 471520f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 47163813dfbdSMatthew G Knepley 47171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4718552f7358SJed Brown @*/ 4719d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4720d71ae5a4SJacob Faibussowitsch { 4721552f7358SJed Brown PetscInt *offsets, **closures; 4722552f7358SJed Brown PetscInt *meet[2]; 4723552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 472424c766afSToby Isaac PetscInt p, h, c, m, mc; 4725552f7358SJed Brown 4726552f7358SJed Brown PetscFunctionBegin; 4727552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47284f572ea9SToby Isaac PetscAssertPointer(points, 3); 47294f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 47304f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4731552f7358SJed Brown 47329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 47339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 47349566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 47356302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 473624c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 47379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 47389566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4739552f7358SJed Brown 4740552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4741552f7358SJed Brown PetscInt closureSize; 4742552f7358SJed Brown 47439566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 47440d644c17SKarl Rupp 4745552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4746552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4747552f7358SJed Brown PetscInt pStart, pEnd, i; 4748552f7358SJed Brown 47499566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4750552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4751552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4752552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4753552f7358SJed Brown break; 4754552f7358SJed Brown } 4755552f7358SJed Brown } 4756552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4757552f7358SJed Brown } 475863a3b9bcSJacob 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); 4759552f7358SJed Brown } 4760552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4761552f7358SJed Brown PetscInt dof; 4762552f7358SJed Brown 4763552f7358SJed Brown /* Copy in cone of first point */ 4764552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 4765ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 4766552f7358SJed Brown /* Check each successive cone */ 4767552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4768552f7358SJed Brown PetscInt newMeetSize = 0; 4769552f7358SJed Brown 4770552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 4771552f7358SJed Brown for (c = 0; c < dof; ++c) { 4772552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 4773552f7358SJed Brown 4774552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4775552f7358SJed Brown if (point == meet[i][m]) { 4776552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4777552f7358SJed Brown break; 4778552f7358SJed Brown } 4779552f7358SJed Brown } 4780552f7358SJed Brown } 4781552f7358SJed Brown meetSize = newMeetSize; 4782552f7358SJed Brown i = 1 - i; 4783552f7358SJed Brown } 4784552f7358SJed Brown if (meetSize) break; 4785552f7358SJed Brown } 4786552f7358SJed Brown *numCoveredPoints = meetSize; 4787552f7358SJed Brown *coveredPoints = meet[i]; 478848a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 47899566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 47909566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 47916302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 47923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4793552f7358SJed Brown } 4794552f7358SJed Brown 47954e3744c5SMatthew G. Knepley /*@C 4796a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 47974e3744c5SMatthew G. Knepley 47984e3744c5SMatthew G. Knepley Not Collective 47994e3744c5SMatthew G. Knepley 48004e3744c5SMatthew G. Knepley Input Parameters: 4801a1cb98faSBarry Smith + dmA - A `DMPLEX` object 4802a1cb98faSBarry Smith - dmB - A `DMPLEX` object 48034e3744c5SMatthew G. Knepley 48042fe279fdSBarry Smith Output Parameter: 4805a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 48064e3744c5SMatthew G. Knepley 48074e3744c5SMatthew G. Knepley Level: intermediate 48084e3744c5SMatthew G. Knepley 4809a1cb98faSBarry Smith Note: 48103c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 48114e3744c5SMatthew G. Knepley 48121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 48134e3744c5SMatthew G. Knepley @*/ 4814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4815d71ae5a4SJacob Faibussowitsch { 48164e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 48174e3744c5SMatthew G. Knepley 48184e3744c5SMatthew G. Knepley PetscFunctionBegin; 48194e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 48204e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 48214f572ea9SToby Isaac PetscAssertPointer(equal, 3); 48224e3744c5SMatthew G. Knepley 48234e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 48249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 48259566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 48263ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 48279566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 48289566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 48293ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 48304e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 48314e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 48324e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 48334e3744c5SMatthew G. Knepley 48349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 48359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 48369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 48379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 48389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 48399566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 48403ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 48414e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 48423ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 48433ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 48444e3744c5SMatthew G. Knepley } 48459566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 48469566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 48479566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 48489566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 48493ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 48504e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 48513ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 48524e3744c5SMatthew G. Knepley } 48534e3744c5SMatthew G. Knepley } 48544e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 48553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48564e3744c5SMatthew G. Knepley } 48574e3744c5SMatthew G. Knepley 48587cd05799SMatthew G. Knepley /*@C 48597cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 48607cd05799SMatthew G. Knepley 48617cd05799SMatthew G. Knepley Not Collective 48627cd05799SMatthew G. Knepley 48637cd05799SMatthew G. Knepley Input Parameters: 4864a1cb98faSBarry Smith + dm - The `DMPLEX` 48657cd05799SMatthew G. Knepley . cellDim - The cell dimension 48667cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 48677cd05799SMatthew G. Knepley 48682fe279fdSBarry Smith Output Parameter: 48697cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 48707cd05799SMatthew G. Knepley 48717cd05799SMatthew G. Knepley Level: developer 48727cd05799SMatthew G. Knepley 4873a1cb98faSBarry Smith Note: 48747cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 48757cd05799SMatthew G. Knepley 48761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 48777cd05799SMatthew G. Knepley @*/ 4878d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4879d71ae5a4SJacob Faibussowitsch { 488082f516ccSBarry Smith MPI_Comm comm; 4881552f7358SJed Brown 4882552f7358SJed Brown PetscFunctionBegin; 48839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 48844f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 4885552f7358SJed Brown switch (cellDim) { 4886d71ae5a4SJacob Faibussowitsch case 0: 4887d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 4888d71ae5a4SJacob Faibussowitsch break; 4889d71ae5a4SJacob Faibussowitsch case 1: 4890d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 4891d71ae5a4SJacob Faibussowitsch break; 4892552f7358SJed Brown case 2: 4893552f7358SJed Brown switch (numCorners) { 489419436ca2SJed Brown case 3: /* triangle */ 489519436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4896552f7358SJed Brown break; 489719436ca2SJed Brown case 4: /* quadrilateral */ 489819436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4899552f7358SJed Brown break; 490019436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 490119436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4902552f7358SJed Brown break; 490319436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 490419436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4905552f7358SJed Brown break; 4906d71ae5a4SJacob Faibussowitsch default: 4907d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4908552f7358SJed Brown } 4909552f7358SJed Brown break; 4910552f7358SJed Brown case 3: 4911552f7358SJed Brown switch (numCorners) { 491219436ca2SJed Brown case 4: /* tetradehdron */ 491319436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 4914552f7358SJed Brown break; 491519436ca2SJed Brown case 6: /* tet cohesive cells */ 491619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4917552f7358SJed Brown break; 491819436ca2SJed Brown case 8: /* hexahedron */ 491919436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4920552f7358SJed Brown break; 492119436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 492219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4923552f7358SJed Brown break; 492419436ca2SJed Brown case 10: /* quadratic tetrahedron */ 492519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4926552f7358SJed Brown break; 492719436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 492819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4929552f7358SJed Brown break; 493019436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 493119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4932552f7358SJed Brown break; 493319436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 493419436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 4935552f7358SJed Brown break; 4936d71ae5a4SJacob Faibussowitsch default: 4937d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4938552f7358SJed Brown } 4939552f7358SJed Brown break; 4940d71ae5a4SJacob Faibussowitsch default: 4941d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 4942552f7358SJed Brown } 49433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4944552f7358SJed Brown } 4945552f7358SJed Brown 4946552f7358SJed Brown /*@ 4947a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 4948552f7358SJed Brown 4949552f7358SJed Brown Not Collective 4950552f7358SJed Brown 4951aa50250dSMatthew G. Knepley Input Parameter: 4952a1cb98faSBarry Smith . dm - The `DMPLEX` object 4953552f7358SJed Brown 4954aa50250dSMatthew G. Knepley Output Parameter: 4955a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 4956552f7358SJed Brown 4957552f7358SJed Brown Level: developer 4958552f7358SJed Brown 49591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 4960aa50250dSMatthew G. Knepley @*/ 4961d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4962d71ae5a4SJacob Faibussowitsch { 4963aa50250dSMatthew G. Knepley PetscFunctionBegin; 4964aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49654f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 4966c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 49673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4968aa50250dSMatthew G. Knepley } 4969aa50250dSMatthew G. Knepley 4970aa50250dSMatthew G. Knepley /*@ 4971aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 4972aa50250dSMatthew G. Knepley 4973aa50250dSMatthew G. Knepley Not Collective 4974aa50250dSMatthew G. Knepley 4975aa50250dSMatthew G. Knepley Input Parameter: 4976a1cb98faSBarry Smith . dm - The `DMPLEX` object 4977aa50250dSMatthew G. Knepley 4978aa50250dSMatthew G. Knepley Output Parameter: 4979aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 4980aa50250dSMatthew G. Knepley 4981aa50250dSMatthew G. Knepley Level: developer 4982552f7358SJed Brown 4983b1bb481bSMatthew Knepley Notes: 4984a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 4985a1cb98faSBarry Smith 4986a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 4987a1cb98faSBarry Smith 4988dc287ab2SVaclav Hapla An empty mesh gives -1. 4989b1bb481bSMatthew Knepley 49901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 4991552f7358SJed Brown @*/ 4992d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4993d71ae5a4SJacob Faibussowitsch { 49949f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4995aa50250dSMatthew G. Knepley DMLabel label; 4996aa50250dSMatthew G. Knepley PetscInt d = 0; 4997552f7358SJed Brown 4998552f7358SJed Brown PetscFunctionBegin; 4999552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50004f572ea9SToby Isaac PetscAssertPointer(depth, 2); 50019f4ada15SMatthew G. Knepley if (mesh->tr) { 50029f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 50039f4ada15SMatthew G. Knepley } else { 50049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 50059566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 5006552f7358SJed Brown *depth = d - 1; 50079f4ada15SMatthew G. Knepley } 50083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5009552f7358SJed Brown } 5010552f7358SJed Brown 5011552f7358SJed Brown /*@ 501220f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5013552f7358SJed Brown 5014552f7358SJed Brown Not Collective 5015552f7358SJed Brown 5016552f7358SJed Brown Input Parameters: 5017a1cb98faSBarry Smith + dm - The `DMPLEX` object 5018570fa34dSVaclav Hapla - depth - The requested depth 5019552f7358SJed Brown 5020552f7358SJed Brown Output Parameters: 502120f4b53cSBarry Smith + start - The first point at this `depth` 502220f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5023552f7358SJed Brown 5024552f7358SJed Brown Level: developer 5025552f7358SJed Brown 5026a1cb98faSBarry Smith Notes: 5027a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5028a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5029a1cb98faSBarry Smith higher dimension, e.g., "edges". 5030a1cb98faSBarry Smith 50312827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5032552f7358SJed Brown @*/ 5033d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5034d71ae5a4SJacob Faibussowitsch { 50359f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5036aa50250dSMatthew G. Knepley DMLabel label; 503763d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5038552f7358SJed Brown 5039552f7358SJed Brown PetscFunctionBegin; 5040552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50419371c9d4SSatish Balay if (start) { 50424f572ea9SToby Isaac PetscAssertPointer(start, 3); 50439371c9d4SSatish Balay *start = 0; 50449371c9d4SSatish Balay } 50459371c9d4SSatish Balay if (end) { 50464f572ea9SToby Isaac PetscAssertPointer(end, 4); 50479371c9d4SSatish Balay *end = 0; 50489371c9d4SSatish Balay } 50499566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 50503ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5051570fa34dSVaclav Hapla if (depth < 0) { 505263d1a920SMatthew G. Knepley if (start) *start = pStart; 505363d1a920SMatthew G. Knepley if (end) *end = pEnd; 50543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5055552f7358SJed Brown } 50569f4ada15SMatthew G. Knepley if (mesh->tr) { 50579f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 50589f4ada15SMatthew G. Knepley } else { 50599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 506028b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5061570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 50629f4ada15SMatthew G. Knepley } 50633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5064552f7358SJed Brown } 5065552f7358SJed Brown 5066552f7358SJed Brown /*@ 506720f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5068552f7358SJed Brown 5069552f7358SJed Brown Not Collective 5070552f7358SJed Brown 5071552f7358SJed Brown Input Parameters: 5072a1cb98faSBarry Smith + dm - The `DMPLEX` object 5073570fa34dSVaclav Hapla - height - The requested height 5074552f7358SJed Brown 5075552f7358SJed Brown Output Parameters: 507620f4b53cSBarry Smith + start - The first point at this `height` 507720f4b53cSBarry Smith - end - One beyond the last point at this `height` 5078552f7358SJed Brown 5079552f7358SJed Brown Level: developer 5080552f7358SJed Brown 5081a1cb98faSBarry Smith Notes: 5082a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5083a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5084a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5085a1cb98faSBarry Smith 50862827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5087552f7358SJed Brown @*/ 5088d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5089d71ae5a4SJacob Faibussowitsch { 5090aa50250dSMatthew G. Knepley DMLabel label; 509163d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5092552f7358SJed Brown 5093552f7358SJed Brown PetscFunctionBegin; 5094552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50959371c9d4SSatish Balay if (start) { 50964f572ea9SToby Isaac PetscAssertPointer(start, 3); 50979371c9d4SSatish Balay *start = 0; 50989371c9d4SSatish Balay } 50999371c9d4SSatish Balay if (end) { 51004f572ea9SToby Isaac PetscAssertPointer(end, 4); 51019371c9d4SSatish Balay *end = 0; 51029371c9d4SSatish Balay } 51039566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 51043ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5105570fa34dSVaclav Hapla if (height < 0) { 510663d1a920SMatthew G. Knepley if (start) *start = pStart; 510763d1a920SMatthew G. Knepley if (end) *end = pEnd; 51083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5109552f7358SJed Brown } 51109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 511159e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 511259e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 511359e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 511459e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 51153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5116552f7358SJed Brown } 5117552f7358SJed Brown 5118ba2698f1SMatthew G. Knepley /*@ 511920f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5120ba2698f1SMatthew G. Knepley 5121ba2698f1SMatthew G. Knepley Not Collective 5122ba2698f1SMatthew G. Knepley 5123d8d19677SJose E. Roman Input Parameters: 5124a1cb98faSBarry Smith + dm - The `DMPLEX` object 5125ba2698f1SMatthew G. Knepley - point - The point 5126ba2698f1SMatthew G. Knepley 5127ba2698f1SMatthew G. Knepley Output Parameter: 512820f4b53cSBarry Smith . depth - The depth of the `point` 5129ba2698f1SMatthew G. Knepley 5130ba2698f1SMatthew G. Knepley Level: intermediate 5131ba2698f1SMatthew G. Knepley 51321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5133ba2698f1SMatthew G. Knepley @*/ 5134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5135d71ae5a4SJacob Faibussowitsch { 5136ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5137ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51384f572ea9SToby Isaac PetscAssertPointer(depth, 3); 51399566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 51403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5141ba2698f1SMatthew G. Knepley } 5142ba2698f1SMatthew G. Knepley 5143ba2698f1SMatthew G. Knepley /*@ 514420f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 51450c0a32dcSVaclav Hapla 51460c0a32dcSVaclav Hapla Not Collective 51470c0a32dcSVaclav Hapla 5148d8d19677SJose E. Roman Input Parameters: 5149a1cb98faSBarry Smith + dm - The `DMPLEX` object 51500c0a32dcSVaclav Hapla - point - The point 51510c0a32dcSVaclav Hapla 51520c0a32dcSVaclav Hapla Output Parameter: 515320f4b53cSBarry Smith . height - The height of the `point` 51540c0a32dcSVaclav Hapla 51550c0a32dcSVaclav Hapla Level: intermediate 51560c0a32dcSVaclav Hapla 51571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 51580c0a32dcSVaclav Hapla @*/ 5159d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5160d71ae5a4SJacob Faibussowitsch { 51610c0a32dcSVaclav Hapla PetscInt n, pDepth; 51620c0a32dcSVaclav Hapla 51630c0a32dcSVaclav Hapla PetscFunctionBegin; 51640c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51654f572ea9SToby Isaac PetscAssertPointer(height, 3); 51669566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 51679566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 51680c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 51693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51700c0a32dcSVaclav Hapla } 51710c0a32dcSVaclav Hapla 51720c0a32dcSVaclav Hapla /*@ 5173a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5174ba2698f1SMatthew G. Knepley 5175ba2698f1SMatthew G. Knepley Not Collective 5176ba2698f1SMatthew G. Knepley 5177ba2698f1SMatthew G. Knepley Input Parameter: 5178a1cb98faSBarry Smith . dm - The `DMPLEX` object 5179ba2698f1SMatthew G. Knepley 5180ba2698f1SMatthew G. Knepley Output Parameter: 5181a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5182412e9a14SMatthew G. Knepley 5183ba2698f1SMatthew G. Knepley Level: developer 5184ba2698f1SMatthew G. Knepley 5185a1cb98faSBarry Smith Note: 5186a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5187a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5188a1cb98faSBarry Smith 51891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5190ba2698f1SMatthew G. Knepley @*/ 5191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5192d71ae5a4SJacob Faibussowitsch { 5193ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5194ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51954f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 51969566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5197ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 51983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5199ba2698f1SMatthew G. Knepley } 5200ba2698f1SMatthew G. Knepley 5201ba2698f1SMatthew G. Knepley /*@ 5202ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5203ba2698f1SMatthew G. Knepley 5204ba2698f1SMatthew G. Knepley Not Collective 5205ba2698f1SMatthew G. Knepley 5206d8d19677SJose E. Roman Input Parameters: 5207a1cb98faSBarry Smith + dm - The `DMPLEX` object 5208ba2698f1SMatthew G. Knepley - cell - The cell 5209ba2698f1SMatthew G. Knepley 5210ba2698f1SMatthew G. Knepley Output Parameter: 5211ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5212ba2698f1SMatthew G. Knepley 5213ba2698f1SMatthew G. Knepley Level: intermediate 5214ba2698f1SMatthew G. Knepley 52151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5216ba2698f1SMatthew G. Knepley @*/ 5217d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5218d71ae5a4SJacob Faibussowitsch { 52199f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5220ba2698f1SMatthew G. Knepley DMLabel label; 5221ba2698f1SMatthew G. Knepley PetscInt ct; 5222ba2698f1SMatthew G. Knepley 5223ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5224ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52254f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 52269f4ada15SMatthew G. Knepley if (mesh->tr) { 52279f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 52289f4ada15SMatthew G. Knepley } else { 522921027e53SStefano Zampini PetscInt pStart, pEnd; 523021027e53SStefano Zampini 523121027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 523221027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 523321027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 523421027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 523521027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 523621027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 523721027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 523821027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct; 523921027e53SStefano Zampini } 524021027e53SStefano Zampini } 524121027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 524221027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 52439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 52449566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 524563a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5246936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 524721027e53SStefano Zampini } 52489f4ada15SMatthew G. Knepley } 52493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5250ba2698f1SMatthew G. Knepley } 5251ba2698f1SMatthew G. Knepley 5252412e9a14SMatthew G. Knepley /*@ 5253412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5254412e9a14SMatthew G. Knepley 5255412e9a14SMatthew G. Knepley Not Collective 5256412e9a14SMatthew G. Knepley 5257412e9a14SMatthew G. Knepley Input Parameters: 5258a1cb98faSBarry Smith + dm - The `DMPLEX` object 5259412e9a14SMatthew G. Knepley . cell - The cell 5260412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5261412e9a14SMatthew G. Knepley 5262a1cb98faSBarry Smith Level: advanced 5263a1cb98faSBarry Smith 5264a1cb98faSBarry Smith Note: 5265a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5266412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5267412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5268db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5269412e9a14SMatthew G. Knepley 52701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5271412e9a14SMatthew G. Knepley @*/ 5272d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5273d71ae5a4SJacob Faibussowitsch { 527421027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5275412e9a14SMatthew G. Knepley DMLabel label; 527621027e53SStefano Zampini PetscInt pStart, pEnd; 5277412e9a14SMatthew G. Knepley 5278412e9a14SMatthew G. Knepley PetscFunctionBegin; 5279412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 528021027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 52819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 52829566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 528321027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 528421027e53SStefano Zampini mesh->cellTypes[cell - pStart].value_as_uint8 = celltype; 52853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5286412e9a14SMatthew G. Knepley } 5287412e9a14SMatthew G. Knepley 5288d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5289d71ae5a4SJacob Faibussowitsch { 5290efe440bfSMatthew G. Knepley PetscSection section, s; 5291efe440bfSMatthew G. Knepley Mat m; 52923e922f36SToby Isaac PetscInt maxHeight; 5293dd4c3f67SMatthew G. Knepley const char *prefix; 5294552f7358SJed Brown 5295552f7358SJed Brown PetscFunctionBegin; 52969566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5297dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5298dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5299dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 53009566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 53019566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 53029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 53039566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 53049566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 53059566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 53069566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 53079566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 53089566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 53099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 53108f4c458bSMatthew G. Knepley 53119566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 53129566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5313dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5314dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 53153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5316552f7358SJed Brown } 5317552f7358SJed Brown 5318d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5319d71ae5a4SJacob Faibussowitsch { 53206858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 53216858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5322f19dbd58SToby Isaac 5323f19dbd58SToby Isaac PetscFunctionBegin; 5324f19dbd58SToby Isaac *field = NULL; 53259566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 53269566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 53276858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 53286858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5329f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 53306858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 53316858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5332f19dbd58SToby Isaac } 53333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5334f19dbd58SToby Isaac } 5335f19dbd58SToby Isaac 53367cd05799SMatthew G. Knepley /*@C 53377cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 53387cd05799SMatthew G. Knepley 53397cd05799SMatthew G. Knepley Not Collective 53407cd05799SMatthew G. Knepley 53412fe279fdSBarry Smith Input Parameter: 5342a1cb98faSBarry Smith . dm - The `DMPLEX` object 53437cd05799SMatthew G. Knepley 53447cd05799SMatthew G. Knepley Output Parameter: 5345a1cb98faSBarry Smith . section - The `PetscSection` object 53467cd05799SMatthew G. Knepley 53477cd05799SMatthew G. Knepley Level: developer 53487cd05799SMatthew G. Knepley 53491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 53507cd05799SMatthew G. Knepley @*/ 5351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5352d71ae5a4SJacob Faibussowitsch { 5353552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5354552f7358SJed Brown 5355552f7358SJed Brown PetscFunctionBegin; 5356552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5357552f7358SJed Brown if (section) *section = mesh->coneSection; 53583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5359552f7358SJed Brown } 5360552f7358SJed Brown 53617cd05799SMatthew G. Knepley /*@C 53627cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 53637cd05799SMatthew G. Knepley 53647cd05799SMatthew G. Knepley Not Collective 53657cd05799SMatthew G. Knepley 53662fe279fdSBarry Smith Input Parameter: 5367a1cb98faSBarry Smith . dm - The `DMPLEX` object 53687cd05799SMatthew G. Knepley 53697cd05799SMatthew G. Knepley Output Parameter: 5370a1cb98faSBarry Smith . section - The `PetscSection` object 53717cd05799SMatthew G. Knepley 53727cd05799SMatthew G. Knepley Level: developer 53737cd05799SMatthew G. Knepley 53741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 53757cd05799SMatthew G. Knepley @*/ 5376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5377d71ae5a4SJacob Faibussowitsch { 53788cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 53798cb4d582SMatthew G. Knepley 53808cb4d582SMatthew G. Knepley PetscFunctionBegin; 53818cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53828cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 53833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53848cb4d582SMatthew G. Knepley } 53858cb4d582SMatthew G. Knepley 53867cd05799SMatthew G. Knepley /*@C 53877cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 53887cd05799SMatthew G. Knepley 53897cd05799SMatthew G. Knepley Not Collective 53907cd05799SMatthew G. Knepley 53912fe279fdSBarry Smith Input Parameter: 5392a1cb98faSBarry Smith . dm - The `DMPLEX` object 53937cd05799SMatthew G. Knepley 53947cd05799SMatthew G. Knepley Output Parameter: 53957cd05799SMatthew G. Knepley . cones - The cone for each point 53967cd05799SMatthew G. Knepley 53977cd05799SMatthew G. Knepley Level: developer 53987cd05799SMatthew G. Knepley 53991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 54007cd05799SMatthew G. Knepley @*/ 5401d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5402d71ae5a4SJacob Faibussowitsch { 5403552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5404552f7358SJed Brown 5405552f7358SJed Brown PetscFunctionBegin; 5406552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5407552f7358SJed Brown if (cones) *cones = mesh->cones; 54083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5409552f7358SJed Brown } 5410552f7358SJed Brown 54117cd05799SMatthew G. Knepley /*@C 54127cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 54137cd05799SMatthew G. Knepley 54147cd05799SMatthew G. Knepley Not Collective 54157cd05799SMatthew G. Knepley 54162fe279fdSBarry Smith Input Parameter: 5417a1cb98faSBarry Smith . dm - The `DMPLEX` object 54187cd05799SMatthew G. Knepley 54197cd05799SMatthew G. Knepley Output Parameter: 5420b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 54217cd05799SMatthew G. Knepley 54227cd05799SMatthew G. Knepley Level: developer 54237cd05799SMatthew G. Knepley 5424b5a892a1SMatthew G. Knepley Notes: 5425a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5426b5a892a1SMatthew G. Knepley 5427a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5428b5a892a1SMatthew G. Knepley 54291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 54307cd05799SMatthew G. Knepley @*/ 5431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5432d71ae5a4SJacob Faibussowitsch { 5433552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5434552f7358SJed Brown 5435552f7358SJed Brown PetscFunctionBegin; 5436552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5437552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 54383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5439552f7358SJed Brown } 5440552f7358SJed Brown 5441552f7358SJed Brown /******************************** FEM Support **********************************/ 5442552f7358SJed Brown 54439e8305c2SJed Brown /* 54449e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 54459e8305c2SJed Brown representing a line in the section. 54469e8305c2SJed Brown */ 5447d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section, PetscInt field, PetscInt line, PetscBool vertexchart, PetscInt *Nc, PetscInt *k) 5448d71ae5a4SJacob Faibussowitsch { 54499e8305c2SJed Brown PetscFunctionBeginHot; 54509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5451a433471fSStefano Zampini if (line < 0) { 5452a433471fSStefano Zampini *k = 0; 5453a433471fSStefano Zampini *Nc = 0; 5454a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 54559e8305c2SJed Brown *k = 1; 54569e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 54579e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 54589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 54599e8305c2SJed Brown *k = *k / *Nc + 1; 54609e8305c2SJed Brown } 54613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54629e8305c2SJed Brown } 54639e8305c2SJed Brown 5464a4355906SMatthew Knepley /*@ 5465bc1eb3faSJed Brown 5466bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5467bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 546820f4b53cSBarry Smith section provided (or the section of the `DM`). 5469a4355906SMatthew Knepley 5470a4355906SMatthew Knepley Input Parameters: 547120f4b53cSBarry Smith + dm - The `DM` 547220f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 547320f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5474a4355906SMatthew Knepley 5475bc1eb3faSJed Brown Example: 5476bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5477bc1eb3faSJed Brown .vb 5478bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5479bc1eb3faSJed Brown 5480bc1eb3faSJed Brown v4 -- e6 -- v3 5481bc1eb3faSJed Brown | | 5482bc1eb3faSJed Brown e7 c0 e8 5483bc1eb3faSJed Brown | | 5484bc1eb3faSJed Brown v1 -- e5 -- v2 5485bc1eb3faSJed Brown .ve 5486bc1eb3faSJed Brown 5487bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5488bc1eb3faSJed Brown dofs in the order of points, e.g., 5489bc1eb3faSJed Brown .vb 5490bc1eb3faSJed Brown c0 -> [0,1,2,3] 5491bc1eb3faSJed Brown v1 -> [4] 5492bc1eb3faSJed Brown ... 5493bc1eb3faSJed Brown e5 -> [8, 9] 5494bc1eb3faSJed Brown .ve 5495bc1eb3faSJed Brown 5496bc1eb3faSJed Brown which corresponds to the dofs 5497bc1eb3faSJed Brown .vb 5498bc1eb3faSJed Brown 6 10 11 7 5499bc1eb3faSJed Brown 13 2 3 15 5500bc1eb3faSJed Brown 12 0 1 14 5501bc1eb3faSJed Brown 4 8 9 5 5502bc1eb3faSJed Brown .ve 5503bc1eb3faSJed Brown 5504bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5505bc1eb3faSJed Brown .vb 5506bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5507bc1eb3faSJed Brown .ve 5508bc1eb3faSJed Brown 5509bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5510bc1eb3faSJed Brown .vb 5511bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5512bc1eb3faSJed Brown .ve 5513bc1eb3faSJed Brown 5514a4355906SMatthew Knepley Level: developer 5515a4355906SMatthew Knepley 5516da9ac489SAlbert Cowie Notes: 5517a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5518a1cb98faSBarry Smith degree of the basis. 5519a1cb98faSBarry Smith 5520da9ac489SAlbert Cowie This is required to run with libCEED. 5521da9ac489SAlbert Cowie 55221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5523a4355906SMatthew Knepley @*/ 5524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5525d71ae5a4SJacob Faibussowitsch { 55267391a63aSMatthew G. Knepley DMLabel label; 5527bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 55289e8305c2SJed Brown PetscBool vertexchart; 55293194fc30SMatthew G. Knepley 55303194fc30SMatthew G. Knepley PetscFunctionBegin; 55319566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 55323ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5533a433471fSStefano Zampini if (point < 0) { 5534a433471fSStefano Zampini PetscInt sStart, sEnd; 5535a433471fSStefano Zampini 55369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5537a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5538a433471fSStefano Zampini } 55399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 55409566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 55419566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 55429371c9d4SSatish Balay if (depth == 1) { 55439371c9d4SSatish Balay eStart = point; 55449371c9d4SSatish Balay } else if (depth == dim) { 55457391a63aSMatthew G. Knepley const PetscInt *cone; 55467391a63aSMatthew G. Knepley 55479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5548d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5549d4e6627bSStefano Zampini else if (dim == 3) { 5550d4e6627bSStefano Zampini const PetscInt *cone2; 55519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5552d4e6627bSStefano Zampini eStart = cone2[0]; 555363a3b9bcSJacob 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); 555463a3b9bcSJacob 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); 55559e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 55569e8305c2SJed Brown PetscInt pStart, pEnd, cStart, cEnd; 55579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd)); 55589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &cStart, &cEnd)); 5559796d0a68SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5560796d0a68SJed Brown else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5561796d0a68SJed Brown else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 55629e8305c2SJed Brown } 55639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5564bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5565bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5566bb197d40SJed Brown PetscInt *perm; 5567bb197d40SJed Brown 55683194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 55699566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 5570bb197d40SJed Brown size += PetscPowInt(k + 1, d) * Nc; 55713194fc30SMatthew G. Knepley } 55729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 55733194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5574bb197d40SJed Brown switch (d) { 5575babf31e0SJed Brown case 1: 55769566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 5577babf31e0SJed Brown /* 5578babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5579babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5580babf31e0SJed Brown */ 5581babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 55829371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 55839371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5584babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5585babf31e0SJed Brown foffset = offset; 5586babf31e0SJed Brown break; 558789eabcffSMatthew G. Knepley case 2: 55883194fc30SMatthew 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} */ 55899566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 55903194fc30SMatthew G. Knepley /* The SEM order is 55913194fc30SMatthew G. Knepley 55923194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 559389eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 55943194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 55953194fc30SMatthew G. Knepley */ 55963194fc30SMatthew G. Knepley { 55973194fc30SMatthew G. Knepley const PetscInt of = 0; 55983194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 55993194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 56003194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 56013194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 56023194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 56033194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 56043194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 56053194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 56063194fc30SMatthew G. Knepley PetscInt o; 56073194fc30SMatthew G. Knepley 56083194fc30SMatthew G. Knepley /* bottom */ 56093194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 56109371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 56119371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 56123194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 56133194fc30SMatthew G. Knepley /* middle */ 56143194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 56153194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 56169371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 56179371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 56183194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 56193194fc30SMatthew G. Knepley } 56203194fc30SMatthew G. Knepley /* top */ 56213194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 56229371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 56239371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 56243194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 56253194fc30SMatthew G. Knepley foffset = offset; 56263194fc30SMatthew G. Knepley } 562789eabcffSMatthew G. Knepley break; 562889eabcffSMatthew G. Knepley case 3: 562989eabcffSMatthew G. Knepley /* The original hex closure is 563089eabcffSMatthew G. Knepley 563189eabcffSMatthew G. Knepley {c, 563289eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 563389eabcffSMatthew 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, 563489eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 563589eabcffSMatthew G. Knepley */ 56369566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 563789eabcffSMatthew G. Knepley /* The SEM order is 563889eabcffSMatthew G. Knepley Bottom Slice 563989eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 564089eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 564189eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 564289eabcffSMatthew G. Knepley 564389eabcffSMatthew G. Knepley Middle Slice (j) 564489eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 564589eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 564689eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 564789eabcffSMatthew G. Knepley 564889eabcffSMatthew G. Knepley Top Slice 564989eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 565089eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 565189eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 565289eabcffSMatthew G. Knepley */ 565389eabcffSMatthew G. Knepley { 565489eabcffSMatthew G. Knepley const PetscInt oc = 0; 565589eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 565689eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 565789eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 565889eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 565989eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 566089eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 566189eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 566289eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 566389eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 566489eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 566589eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 566689eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 566789eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 566889eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 566989eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 567089eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 567189eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 567289eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 567389eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 567489eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 567589eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 567689eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 567789eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 567889eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 567989eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 568089eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 568189eabcffSMatthew G. Knepley PetscInt o, n; 568289eabcffSMatthew G. Knepley 568389eabcffSMatthew G. Knepley /* Bottom Slice */ 568489eabcffSMatthew G. Knepley /* bottom */ 568589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 56869371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 56879371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 568889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 568989eabcffSMatthew G. Knepley /* middle */ 569089eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 569189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 56929371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 56939371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 56949371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 56959371c9d4SSatish Balay } 569689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 56973194fc30SMatthew G. Knepley } 569889eabcffSMatthew G. Knepley /* top */ 569989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 57009371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 57019371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 570289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 570389eabcffSMatthew G. Knepley 570489eabcffSMatthew G. Knepley /* Middle Slice */ 570589eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 570689eabcffSMatthew G. Knepley /* bottom */ 570789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 57089371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 57099371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 571089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 571189eabcffSMatthew G. Knepley /* middle */ 571289eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 571389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 57149371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 57159371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 571689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 571789eabcffSMatthew G. Knepley } 571889eabcffSMatthew G. Knepley /* top */ 571989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 57209371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 57219371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 572289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 572389eabcffSMatthew G. Knepley } 572489eabcffSMatthew G. Knepley 572589eabcffSMatthew G. Knepley /* Top Slice */ 572689eabcffSMatthew G. Knepley /* bottom */ 572789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 57289371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 57299371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 573089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 573189eabcffSMatthew G. Knepley /* middle */ 573289eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 573389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 57349371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 57359371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 573689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 573789eabcffSMatthew G. Knepley } 573889eabcffSMatthew G. Knepley /* top */ 573989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 57409371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 57419371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 574289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 574389eabcffSMatthew G. Knepley 574489eabcffSMatthew G. Knepley foffset = offset; 574589eabcffSMatthew G. Knepley } 574689eabcffSMatthew G. Knepley break; 5747d71ae5a4SJacob Faibussowitsch default: 5748d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 574989eabcffSMatthew G. Knepley } 575089eabcffSMatthew G. Knepley } 575163a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 57523194fc30SMatthew G. Knepley /* Check permutation */ 57533194fc30SMatthew G. Knepley { 57543194fc30SMatthew G. Knepley PetscInt *check; 57553194fc30SMatthew G. Knepley 57569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 57571dca8a05SBarry Smith for (i = 0; i < size; ++i) { 57581dca8a05SBarry Smith check[i] = -1; 57591dca8a05SBarry 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]); 57601dca8a05SBarry Smith } 57613194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 57621dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 57639566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 57643194fc30SMatthew G. Knepley } 57659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 5766a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5767a05c9aa3SJed Brown PetscInt *loc_perm; 57689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 5769a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 5770a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5771a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 5772a05c9aa3SJed Brown } 57739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 5774a05c9aa3SJed Brown } 5775bb197d40SJed Brown } 57763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57773194fc30SMatthew G. Knepley } 57783194fc30SMatthew G. Knepley 5779d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5780d71ae5a4SJacob Faibussowitsch { 5781e071409bSToby Isaac PetscDS prob; 5782e071409bSToby Isaac PetscInt depth, Nf, h; 5783e071409bSToby Isaac DMLabel label; 5784e071409bSToby Isaac 5785e071409bSToby Isaac PetscFunctionBeginHot; 57869566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 5787e071409bSToby Isaac Nf = prob->Nf; 5788e071409bSToby Isaac label = dm->depthLabel; 5789e071409bSToby Isaac *dspace = NULL; 5790e071409bSToby Isaac if (field < Nf) { 5791e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5792e071409bSToby Isaac 5793e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5794e071409bSToby Isaac PetscDualSpace dsp; 5795e071409bSToby Isaac 57969566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 57979566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 57989566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 5799e071409bSToby Isaac h = depth - 1 - h; 5800e071409bSToby Isaac if (h) { 58019566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 5802e071409bSToby Isaac } else { 5803e071409bSToby Isaac *dspace = dsp; 5804e071409bSToby Isaac } 5805e071409bSToby Isaac } 5806e071409bSToby Isaac } 58073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5808e071409bSToby Isaac } 5809e071409bSToby Isaac 5810d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5811d71ae5a4SJacob Faibussowitsch { 581228351e22SJed Brown PetscScalar *array; 581328351e22SJed Brown const PetscScalar *vArray; 5814d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 58151a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5816552f7358SJed Brown 58171b406b76SMatthew G. Knepley PetscFunctionBeginHot; 58189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 58199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 58209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 58219566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 58223f7cbbe7SMatthew G. Knepley if (!values || !*values) { 58239df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 58249df71ca4SMatthew G. Knepley PetscInt dof; 5825d9917b9dSMatthew G. Knepley 58269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 58279df71ca4SMatthew G. Knepley size += dof; 58289df71ca4SMatthew G. Knepley } 58299df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 58309df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 58312a3aaacfSMatthew G. Knepley PetscInt dof; 58325a1bb5cfSMatthew G. Knepley 58335a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 58349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 58355a1bb5cfSMatthew G. Knepley size += dof; 58365a1bb5cfSMatthew G. Knepley } 58373f7cbbe7SMatthew G. Knepley if (!values) { 58383f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 58393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58403f7cbbe7SMatthew G. Knepley } 58419566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 5842982e9ed1SMatthew G. Knepley } else { 5843982e9ed1SMatthew G. Knepley array = *values; 5844982e9ed1SMatthew G. Knepley } 58459df71ca4SMatthew G. Knepley size = 0; 584628351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 58479df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 58489df71ca4SMatthew G. Knepley PetscInt dof, off, d; 584928351e22SJed Brown const PetscScalar *varr; 5850d9917b9dSMatthew G. Knepley 58519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 58529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 58539df71ca4SMatthew G. Knepley varr = &vArray[off]; 5854ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 58559df71ca4SMatthew G. Knepley size += dof; 58569df71ca4SMatthew G. Knepley } 58579df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 58589df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 58599df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 58605a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 586128351e22SJed Brown const PetscScalar *varr; 58625a1bb5cfSMatthew G. Knepley 586352ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 58649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 58659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 58665a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 58675a1bb5cfSMatthew G. Knepley if (o >= 0) { 5868ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 58695a1bb5cfSMatthew G. Knepley } else { 5870ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 58715a1bb5cfSMatthew G. Knepley } 58729df71ca4SMatthew G. Knepley size += dof; 58735a1bb5cfSMatthew G. Knepley } 587428351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 58759df71ca4SMatthew G. Knepley if (!*values) { 58765a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 58775a1bb5cfSMatthew G. Knepley *values = array; 58789df71ca4SMatthew G. Knepley } else { 587963a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 58808c312ff3SMatthew G. Knepley *csize = size; 58819df71ca4SMatthew G. Knepley } 58823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58835a1bb5cfSMatthew G. Knepley } 5884d9917b9dSMatthew G. Knepley 588527f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 5886d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5887d71ae5a4SJacob Faibussowitsch { 588827f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 588927f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 589027f02ce8SMatthew G. Knepley 58919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 589227f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 589327f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 589427f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 589527f02ce8SMatthew G. Knepley points[q * 2] = r; 589627f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 589727f02ce8SMatthew G. Knepley ++q; 589827f02ce8SMatthew G. Knepley } 589927f02ce8SMatthew G. Knepley } 590027f02ce8SMatthew G. Knepley *numPoints = q; 59013ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 590227f02ce8SMatthew G. Knepley } 590327f02ce8SMatthew G. Knepley 590497529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 590507218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5906d71ae5a4SJacob Faibussowitsch { 590727f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 5908923c78e0SToby Isaac PetscInt np, *pts = NULL; 5909923c78e0SToby Isaac 5910923c78e0SToby Isaac PetscFunctionBeginHot; 59119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 591207218a29SMatthew G. Knepley if (!ornt && *clPoints) { 5913923c78e0SToby Isaac PetscInt dof, off; 5914923c78e0SToby Isaac 59159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 59169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 59179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 5918923c78e0SToby Isaac np = dof / 2; 5919923c78e0SToby Isaac pts = (PetscInt *)&cla[off]; 592027f02ce8SMatthew G. Knepley } else { 592107218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 59229566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 5923923c78e0SToby Isaac } 5924923c78e0SToby Isaac *numPoints = np; 5925923c78e0SToby Isaac *points = pts; 5926923c78e0SToby Isaac *clp = cla; 59273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5928923c78e0SToby Isaac } 5929923c78e0SToby Isaac 5930d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5931d71ae5a4SJacob Faibussowitsch { 5932923c78e0SToby Isaac PetscFunctionBeginHot; 5933923c78e0SToby Isaac if (!*clPoints) { 59349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 5935923c78e0SToby Isaac } else { 59369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 5937923c78e0SToby Isaac } 5938923c78e0SToby Isaac *numPoints = 0; 5939923c78e0SToby Isaac *points = NULL; 5940923c78e0SToby Isaac *clSec = NULL; 5941923c78e0SToby Isaac *clPoints = NULL; 5942923c78e0SToby Isaac *clp = NULL; 59433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5944923c78e0SToby Isaac } 5945923c78e0SToby Isaac 5946d71ae5a4SJacob 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[]) 5947d71ae5a4SJacob Faibussowitsch { 59481a271a75SMatthew G. Knepley PetscInt offset = 0, p; 594997e99dd9SToby Isaac const PetscInt **perms = NULL; 595097e99dd9SToby Isaac const PetscScalar **flips = NULL; 59511a271a75SMatthew G. Knepley 59521a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5953fe02ba77SJed Brown *size = 0; 59549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 595597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 595697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 595797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 595897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 59591a271a75SMatthew G. Knepley PetscInt dof, off, d; 59601a271a75SMatthew G. Knepley const PetscScalar *varr; 59611a271a75SMatthew G. Knepley 59629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 59639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 59641a271a75SMatthew G. Knepley varr = &vArray[off]; 596597e99dd9SToby Isaac if (clperm) { 596697e99dd9SToby Isaac if (perm) { 596797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 59681a271a75SMatthew G. Knepley } else { 596997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 597097e99dd9SToby Isaac } 597197e99dd9SToby Isaac if (flip) { 597297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 597397e99dd9SToby Isaac } 597497e99dd9SToby Isaac } else { 597597e99dd9SToby Isaac if (perm) { 597697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 597797e99dd9SToby Isaac } else { 597897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 597997e99dd9SToby Isaac } 598097e99dd9SToby Isaac if (flip) { 598197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 59821a271a75SMatthew G. Knepley } 59831a271a75SMatthew G. Knepley } 598497e99dd9SToby Isaac offset += dof; 598597e99dd9SToby Isaac } 59869566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 59871a271a75SMatthew G. Knepley *size = offset; 59883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59891a271a75SMatthew G. Knepley } 59901a271a75SMatthew G. Knepley 5991d71ae5a4SJacob 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[]) 5992d71ae5a4SJacob Faibussowitsch { 59931a271a75SMatthew G. Knepley PetscInt offset = 0, f; 59941a271a75SMatthew G. Knepley 59951a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5996fe02ba77SJed Brown *size = 0; 59971a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 599897e99dd9SToby Isaac PetscInt p; 599997e99dd9SToby Isaac const PetscInt **perms = NULL; 600097e99dd9SToby Isaac const PetscScalar **flips = NULL; 60011a271a75SMatthew G. Knepley 60029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 600397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 600497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 600597e99dd9SToby Isaac PetscInt fdof, foff, b; 60061a271a75SMatthew G. Knepley const PetscScalar *varr; 600797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 600897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 60091a271a75SMatthew G. Knepley 60109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 60119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 60121a271a75SMatthew G. Knepley varr = &vArray[foff]; 601397e99dd9SToby Isaac if (clperm) { 60149371c9d4SSatish Balay if (perm) { 6015ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 60161a271a75SMatthew G. Knepley } else { 6017ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 60189371c9d4SSatish Balay } 60199371c9d4SSatish Balay if (flip) { 6020ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 60219371c9d4SSatish Balay } 60229371c9d4SSatish Balay } else { 60239371c9d4SSatish Balay if (perm) { 6024ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 60259371c9d4SSatish Balay } else { 6026ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 60279371c9d4SSatish Balay } 60289371c9d4SSatish Balay if (flip) { 6029ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 60309371c9d4SSatish Balay } 60311a271a75SMatthew G. Knepley } 603297e99dd9SToby Isaac offset += fdof; 60331a271a75SMatthew G. Knepley } 60349566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 60351a271a75SMatthew G. Knepley } 60361a271a75SMatthew G. Knepley *size = offset; 60373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60381a271a75SMatthew G. Knepley } 60391a271a75SMatthew G. Knepley 604007218a29SMatthew G. Knepley PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 604107218a29SMatthew G. Knepley { 604207218a29SMatthew G. Knepley PetscSection clSection; 604307218a29SMatthew G. Knepley IS clPoints; 604407218a29SMatthew G. Knepley PetscInt *points = NULL; 604507218a29SMatthew G. Knepley const PetscInt *clp, *perm; 604607218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 604707218a29SMatthew G. Knepley 604807218a29SMatthew G. Knepley PetscFunctionBeginHot; 604907218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 605007218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 605107218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 605207218a29SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 605307218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 605407218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 605507218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 605607218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 605707218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 605807218a29SMatthew G. Knepley } 605907218a29SMatthew G. Knepley /* Get points */ 606007218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 606107218a29SMatthew G. Knepley /* Get sizes */ 606207218a29SMatthew G. Knepley asize = 0; 606307218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 606407218a29SMatthew G. Knepley PetscInt dof; 606507218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 606607218a29SMatthew G. Knepley asize += dof; 606707218a29SMatthew G. Knepley } 606807218a29SMatthew G. Knepley if (values) { 606907218a29SMatthew G. Knepley const PetscScalar *vArray; 607007218a29SMatthew G. Knepley PetscInt size; 607107218a29SMatthew G. Knepley 607207218a29SMatthew G. Knepley if (*values) { 607307218a29SMatthew 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); 607407218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 607507218a29SMatthew G. Knepley PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 607607218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 607707218a29SMatthew G. Knepley /* Get values */ 607807218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 607907218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 608007218a29SMatthew 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); 608107218a29SMatthew G. Knepley /* Cleanup array */ 608207218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 608307218a29SMatthew G. Knepley } 608407218a29SMatthew G. Knepley if (csize) *csize = asize; 608507218a29SMatthew G. Knepley /* Cleanup points */ 608607218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 608707218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 608807218a29SMatthew G. Knepley } 608907218a29SMatthew G. Knepley 6090552f7358SJed Brown /*@C 6091552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6092552f7358SJed Brown 6093552f7358SJed Brown Not collective 6094552f7358SJed Brown 6095552f7358SJed Brown Input Parameters: 6096a1cb98faSBarry Smith + dm - The `DM` 609720f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6098552f7358SJed Brown . v - The local vector 6099a1cb98faSBarry Smith - point - The point in the `DM` 6100552f7358SJed Brown 61016b867d5aSJose E. Roman Input/Output Parameters: 610220f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 610320f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically; 610420f4b53cSBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed 610522c1ee49SMatthew G. Knepley 6106552f7358SJed Brown Level: intermediate 6107552f7358SJed Brown 6108a1cb98faSBarry Smith Notes: 610920f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6110a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6111a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6112a1cb98faSBarry Smith 6113a1cb98faSBarry Smith A typical use could be 6114a1cb98faSBarry Smith .vb 6115a1cb98faSBarry Smith values = NULL; 6116a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6117a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6118a1cb98faSBarry Smith <Compute on closure> 6119a1cb98faSBarry Smith } 6120a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6121a1cb98faSBarry Smith .ve 6122a1cb98faSBarry Smith or 6123a1cb98faSBarry Smith .vb 6124a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6125a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6126a1cb98faSBarry Smith clSize = clMaxSize; 6127a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6128a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6129a1cb98faSBarry Smith <Compute on closure> 6130a1cb98faSBarry Smith } 6131a1cb98faSBarry Smith } 6132a1cb98faSBarry Smith PetscFree(values); 6133a1cb98faSBarry Smith .ve 6134a1cb98faSBarry Smith 613560225df5SJacob Faibussowitsch Fortran Notes: 613620f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6137a1cb98faSBarry Smith 61381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6139552f7358SJed Brown @*/ 6140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6141d71ae5a4SJacob Faibussowitsch { 6142d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 614307218a29SMatthew G. Knepley PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, v, point, 0, csize, values)); 61443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6145552f7358SJed Brown } 6146552f7358SJed Brown 6147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6148d71ae5a4SJacob Faibussowitsch { 6149e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6150e5c487bfSMatthew G. Knepley PetscSection clSection; 6151e5c487bfSMatthew G. Knepley IS clPoints; 6152e5c487bfSMatthew G. Knepley PetscScalar *array; 6153e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6154e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6155c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6156c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6157e5c487bfSMatthew G. Knepley 6158e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6159e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 61609566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6161e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6162e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 61639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 61649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 61659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6166e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 61679566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 61683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6169e5c487bfSMatthew G. Knepley } 6170e5c487bfSMatthew G. Knepley /* Get points */ 617107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6172c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6173c459fbc1SJed Brown PetscInt dof; 61749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6175c459fbc1SJed Brown clsize += dof; 6176c459fbc1SJed Brown } 61779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6178e5c487bfSMatthew G. Knepley /* Filter points */ 6179e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6180e5c487bfSMatthew G. Knepley PetscInt dep; 6181e5c487bfSMatthew G. Knepley 61829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6183e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6184e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6185e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6186e5c487bfSMatthew G. Knepley ++Np; 6187e5c487bfSMatthew G. Knepley } 6188e5c487bfSMatthew G. Knepley /* Get array */ 6189e5c487bfSMatthew G. Knepley if (!values || !*values) { 6190e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6191e5c487bfSMatthew G. Knepley 6192e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 61939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6194e5c487bfSMatthew G. Knepley asize += dof; 6195e5c487bfSMatthew G. Knepley } 6196e5c487bfSMatthew G. Knepley if (!values) { 61979566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6198e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 61993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6200e5c487bfSMatthew G. Knepley } 62019566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6202e5c487bfSMatthew G. Knepley } else { 6203e5c487bfSMatthew G. Knepley array = *values; 6204e5c487bfSMatthew G. Knepley } 62059566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6206e5c487bfSMatthew G. Knepley /* Get values */ 62079566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 62089566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6209e5c487bfSMatthew G. Knepley /* Cleanup points */ 62109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6211e5c487bfSMatthew G. Knepley /* Cleanup array */ 62129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6213e5c487bfSMatthew G. Knepley if (!*values) { 6214e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6215e5c487bfSMatthew G. Knepley *values = array; 6216e5c487bfSMatthew G. Knepley } else { 621763a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6218e5c487bfSMatthew G. Knepley *csize = size; 6219e5c487bfSMatthew G. Knepley } 62203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6221e5c487bfSMatthew G. Knepley } 6222e5c487bfSMatthew G. Knepley 6223552f7358SJed Brown /*@C 6224552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6225552f7358SJed Brown 6226552f7358SJed Brown Not collective 6227552f7358SJed Brown 6228552f7358SJed Brown Input Parameters: 6229a1cb98faSBarry Smith + dm - The `DM` 623020f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6231552f7358SJed Brown . v - The local vector 6232a1cb98faSBarry Smith . point - The point in the `DM` 623320f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6234552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6235552f7358SJed Brown 6236552f7358SJed Brown Level: intermediate 6237552f7358SJed Brown 6238a1cb98faSBarry Smith Note: 623920f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6240a1cb98faSBarry Smith 624160225df5SJacob Faibussowitsch Fortran Notes: 624220f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6243a1cb98faSBarry Smith 62441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6245552f7358SJed Brown @*/ 6246d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6247d71ae5a4SJacob Faibussowitsch { 6248552f7358SJed Brown PetscInt size = 0; 6249552f7358SJed Brown 6250552f7358SJed Brown PetscFunctionBegin; 6251552f7358SJed Brown /* Should work without recalculating size */ 62529566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6253c9fdaa05SMatthew G. Knepley *values = NULL; 62543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6255552f7358SJed Brown } 6256552f7358SJed Brown 6257d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6258d71ae5a4SJacob Faibussowitsch { 62599371c9d4SSatish Balay *x += y; 62609371c9d4SSatish Balay } 6261d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6262d71ae5a4SJacob Faibussowitsch { 62639371c9d4SSatish Balay *x = y; 62649371c9d4SSatish Balay } 6265552f7358SJed Brown 6266d71ae5a4SJacob 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[]) 6267d71ae5a4SJacob Faibussowitsch { 6268552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6269552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6270552f7358SJed Brown PetscScalar *a; 6271552f7358SJed Brown PetscInt off, cind = 0, k; 6272552f7358SJed Brown 6273552f7358SJed Brown PetscFunctionBegin; 62749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 62759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6276552f7358SJed Brown a = &array[off]; 6277552f7358SJed Brown if (!cdof || setBC) { 627897e99dd9SToby Isaac if (clperm) { 62799371c9d4SSatish Balay if (perm) { 6280ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6281552f7358SJed Brown } else { 6282ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 62839371c9d4SSatish Balay } 62849371c9d4SSatish Balay } else { 62859371c9d4SSatish Balay if (perm) { 6286ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 62879371c9d4SSatish Balay } else { 6288ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 62899371c9d4SSatish Balay } 6290552f7358SJed Brown } 6291552f7358SJed Brown } else { 62929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 629397e99dd9SToby Isaac if (clperm) { 62949371c9d4SSatish Balay if (perm) { 62959371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 62969371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 62979371c9d4SSatish Balay ++cind; 62989371c9d4SSatish Balay continue; 62999371c9d4SSatish Balay } 630097e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6301552f7358SJed Brown } 6302552f7358SJed Brown } else { 6303552f7358SJed Brown for (k = 0; k < dof; ++k) { 63049371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 63059371c9d4SSatish Balay ++cind; 63069371c9d4SSatish Balay continue; 63079371c9d4SSatish Balay } 630897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 630997e99dd9SToby Isaac } 631097e99dd9SToby Isaac } 631197e99dd9SToby Isaac } else { 631297e99dd9SToby Isaac if (perm) { 631397e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 63149371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 63159371c9d4SSatish Balay ++cind; 63169371c9d4SSatish Balay continue; 63179371c9d4SSatish Balay } 631897e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 631997e99dd9SToby Isaac } 632097e99dd9SToby Isaac } else { 632197e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 63229371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 63239371c9d4SSatish Balay ++cind; 63249371c9d4SSatish Balay continue; 63259371c9d4SSatish Balay } 632697e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 632797e99dd9SToby Isaac } 6328552f7358SJed Brown } 6329552f7358SJed Brown } 6330552f7358SJed Brown } 63313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6332552f7358SJed Brown } 6333552f7358SJed Brown 6334d71ae5a4SJacob 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[]) 6335d71ae5a4SJacob Faibussowitsch { 6336a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6337a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6338a5e93ea8SMatthew G. Knepley PetscScalar *a; 6339a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6340a5e93ea8SMatthew G. Knepley 6341a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 63429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 63439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6344a5e93ea8SMatthew G. Knepley a = &array[off]; 6345a5e93ea8SMatthew G. Knepley if (cdof) { 63469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 634797e99dd9SToby Isaac if (clperm) { 634897e99dd9SToby Isaac if (perm) { 6349a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6350a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 635197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 635297e99dd9SToby Isaac cind++; 6353a5e93ea8SMatthew G. Knepley } 6354a5e93ea8SMatthew G. Knepley } 6355a5e93ea8SMatthew G. Knepley } else { 6356a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6357a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 635897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 635997e99dd9SToby Isaac cind++; 636097e99dd9SToby Isaac } 636197e99dd9SToby Isaac } 636297e99dd9SToby Isaac } 636397e99dd9SToby Isaac } else { 636497e99dd9SToby Isaac if (perm) { 636597e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 636697e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 636797e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 636897e99dd9SToby Isaac cind++; 636997e99dd9SToby Isaac } 637097e99dd9SToby Isaac } 637197e99dd9SToby Isaac } else { 637297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 637397e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 637497e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 637597e99dd9SToby Isaac cind++; 637697e99dd9SToby Isaac } 6377a5e93ea8SMatthew G. Knepley } 6378a5e93ea8SMatthew G. Knepley } 6379a5e93ea8SMatthew G. Knepley } 6380a5e93ea8SMatthew G. Knepley } 63813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6382a5e93ea8SMatthew G. Knepley } 6383a5e93ea8SMatthew G. Knepley 6384d71ae5a4SJacob 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[]) 6385d71ae5a4SJacob Faibussowitsch { 6386552f7358SJed Brown PetscScalar *a; 63871a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 63881a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 638997e99dd9SToby Isaac PetscInt cind = 0, b; 6390552f7358SJed Brown 6391552f7358SJed Brown PetscFunctionBegin; 63929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 63939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 63949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 63951a271a75SMatthew G. Knepley a = &array[foff]; 6396552f7358SJed Brown if (!fcdof || setBC) { 639797e99dd9SToby Isaac if (clperm) { 63989371c9d4SSatish Balay if (perm) { 6399ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6400552f7358SJed Brown } else { 6401ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 64029371c9d4SSatish Balay } 64039371c9d4SSatish Balay } else { 64049371c9d4SSatish Balay if (perm) { 6405ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 64069371c9d4SSatish Balay } else { 6407ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 64089371c9d4SSatish Balay } 6409552f7358SJed Brown } 6410552f7358SJed Brown } else { 64119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 641297e99dd9SToby Isaac if (clperm) { 641397e99dd9SToby Isaac if (perm) { 641497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 64159371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 64169371c9d4SSatish Balay ++cind; 64179371c9d4SSatish Balay continue; 64189371c9d4SSatish Balay } 641997e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6420552f7358SJed Brown } 6421552f7358SJed Brown } else { 642297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 64239371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 64249371c9d4SSatish Balay ++cind; 64259371c9d4SSatish Balay continue; 64269371c9d4SSatish Balay } 642797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 642897e99dd9SToby Isaac } 642997e99dd9SToby Isaac } 643097e99dd9SToby Isaac } else { 643197e99dd9SToby Isaac if (perm) { 643297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 64339371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 64349371c9d4SSatish Balay ++cind; 64359371c9d4SSatish Balay continue; 64369371c9d4SSatish Balay } 643797e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 643897e99dd9SToby Isaac } 643997e99dd9SToby Isaac } else { 644097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 64419371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 64429371c9d4SSatish Balay ++cind; 64439371c9d4SSatish Balay continue; 64449371c9d4SSatish Balay } 644597e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6446552f7358SJed Brown } 6447552f7358SJed Brown } 6448552f7358SJed Brown } 6449552f7358SJed Brown } 64501a271a75SMatthew G. Knepley *offset += fdof; 64513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6452552f7358SJed Brown } 6453552f7358SJed Brown 6454d71ae5a4SJacob 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[]) 6455d71ae5a4SJacob Faibussowitsch { 6456a5e93ea8SMatthew G. Knepley PetscScalar *a; 64571a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 64581a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 64595da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6460ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6461a5e93ea8SMatthew G. Knepley 6462a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 64639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 64649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 64659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 64669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 64671a271a75SMatthew G. Knepley a = &array[foff]; 6468a5e93ea8SMatthew G. Knepley if (fcdof) { 6469ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 64709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 647197e99dd9SToby Isaac if (clperm) { 647297e99dd9SToby Isaac if (perm) { 6473ba322698SMatthew G. Knepley if (comps) { 6474ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6475ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 64769371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 64779371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 64789371c9d4SSatish Balay ncSet = PETSC_TRUE; 64799371c9d4SSatish Balay } 64809371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 64819371c9d4SSatish Balay ++cind; 64829371c9d4SSatish Balay fcSet = PETSC_TRUE; 64839371c9d4SSatish Balay } 6484ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6485ba322698SMatthew G. Knepley } 6486ba322698SMatthew G. Knepley } else { 648797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 648897e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 648997e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6490a5e93ea8SMatthew G. Knepley ++cind; 6491a5e93ea8SMatthew G. Knepley } 6492a5e93ea8SMatthew G. Knepley } 6493ba322698SMatthew G. Knepley } 6494ba322698SMatthew G. Knepley } else { 6495ba322698SMatthew G. Knepley if (comps) { 6496ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6497ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 64989371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 64999371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 65009371c9d4SSatish Balay ncSet = PETSC_TRUE; 65019371c9d4SSatish Balay } 65029371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 65039371c9d4SSatish Balay ++cind; 65049371c9d4SSatish Balay fcSet = PETSC_TRUE; 65059371c9d4SSatish Balay } 6506ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6507ba322698SMatthew G. Knepley } 6508a5e93ea8SMatthew G. Knepley } else { 650997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 651097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 651197e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 651297e99dd9SToby Isaac ++cind; 651397e99dd9SToby Isaac } 651497e99dd9SToby Isaac } 651597e99dd9SToby Isaac } 6516ba322698SMatthew G. Knepley } 651797e99dd9SToby Isaac } else { 651897e99dd9SToby Isaac if (perm) { 6519ba322698SMatthew G. Knepley if (comps) { 6520ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6521ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 65229371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 65239371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 65249371c9d4SSatish Balay ncSet = PETSC_TRUE; 65259371c9d4SSatish Balay } 65269371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 65279371c9d4SSatish Balay ++cind; 65289371c9d4SSatish Balay fcSet = PETSC_TRUE; 65299371c9d4SSatish Balay } 6530ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6531ba322698SMatthew G. Knepley } 6532ba322698SMatthew G. Knepley } else { 653397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 653497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 653597e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 653697e99dd9SToby Isaac ++cind; 653797e99dd9SToby Isaac } 653897e99dd9SToby Isaac } 6539ba322698SMatthew G. Knepley } 6540ba322698SMatthew G. Knepley } else { 6541ba322698SMatthew G. Knepley if (comps) { 6542ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6543ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 65449371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 65459371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 65469371c9d4SSatish Balay ncSet = PETSC_TRUE; 65479371c9d4SSatish Balay } 65489371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 65499371c9d4SSatish Balay ++cind; 65509371c9d4SSatish Balay fcSet = PETSC_TRUE; 65519371c9d4SSatish Balay } 6552ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6553ba322698SMatthew G. Knepley } 655497e99dd9SToby Isaac } else { 655597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 655697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 655797e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6558a5e93ea8SMatthew G. Knepley ++cind; 6559a5e93ea8SMatthew G. Knepley } 6560a5e93ea8SMatthew G. Knepley } 6561a5e93ea8SMatthew G. Knepley } 6562a5e93ea8SMatthew G. Knepley } 6563a5e93ea8SMatthew G. Knepley } 6564ba322698SMatthew G. Knepley } 65651a271a75SMatthew G. Knepley *offset += fdof; 65663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6567a5e93ea8SMatthew G. Knepley } 6568a5e93ea8SMatthew G. Knepley 6569d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6570d71ae5a4SJacob Faibussowitsch { 6571552f7358SJed Brown PetscScalar *array; 65721b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 65731b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6574552f7358SJed Brown 65751b406b76SMatthew G. Knepley PetscFunctionBeginHot; 65769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 65779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 65789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 65799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 65809566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6581b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6582b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6583b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6584b6ebb6e6SMatthew G. Knepley 65859371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 65869371c9d4SSatish Balay dof = 0; 65879371c9d4SSatish Balay continue; 65889371c9d4SSatish Balay } 65899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6590b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6591b6ebb6e6SMatthew G. Knepley { 6592b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6593b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6594b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6595b6ebb6e6SMatthew G. Knepley 65969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 65979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6598b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6599b6ebb6e6SMatthew G. Knepley if (!cdof) { 6600b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6601ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6602b6ebb6e6SMatthew G. Knepley } else { 6603ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6604b6ebb6e6SMatthew G. Knepley } 6605b6ebb6e6SMatthew G. Knepley } else { 66069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6607b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6608b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 66099371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66109371c9d4SSatish Balay ++cind; 66119371c9d4SSatish Balay continue; 66129371c9d4SSatish Balay } 6613b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6614b6ebb6e6SMatthew G. Knepley } 6615b6ebb6e6SMatthew G. Knepley } else { 6616b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 66179371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66189371c9d4SSatish Balay ++cind; 66199371c9d4SSatish Balay continue; 66209371c9d4SSatish Balay } 6621b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6622b6ebb6e6SMatthew G. Knepley } 6623b6ebb6e6SMatthew G. Knepley } 6624b6ebb6e6SMatthew G. Knepley } 6625b6ebb6e6SMatthew G. Knepley } 6626b6ebb6e6SMatthew G. Knepley } 66279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 66283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6629b6ebb6e6SMatthew G. Knepley } 66301b406b76SMatthew G. Knepley 66311b406b76SMatthew G. Knepley /*@C 663220f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 66331b406b76SMatthew G. Knepley 66341b406b76SMatthew G. Knepley Not collective 66351b406b76SMatthew G. Knepley 66361b406b76SMatthew G. Knepley Input Parameters: 6637a1cb98faSBarry Smith + dm - The `DM` 663820f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 66391b406b76SMatthew G. Knepley . v - The local vector 664020f4b53cSBarry Smith . point - The point in the `DM` 66411b406b76SMatthew G. Knepley . values - The array of values 6642a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6643a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 66441b406b76SMatthew G. Knepley 66451b406b76SMatthew G. Knepley Level: intermediate 66461b406b76SMatthew G. Knepley 66471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 66481b406b76SMatthew G. Knepley @*/ 6649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6650d71ae5a4SJacob Faibussowitsch { 66511b406b76SMatthew G. Knepley PetscSection clSection; 66521b406b76SMatthew G. Knepley IS clPoints; 66531b406b76SMatthew G. Knepley PetscScalar *array; 66541b406b76SMatthew G. Knepley PetscInt *points = NULL; 665527f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6656c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 66571b406b76SMatthew G. Knepley 66581a271a75SMatthew G. Knepley PetscFunctionBeginHot; 66591b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 66609566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 66611a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 66621a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 66639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 66649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 66651b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 66669566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 66673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66681b406b76SMatthew G. Knepley } 66691a271a75SMatthew G. Knepley /* Get points */ 667007218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6671c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6672c459fbc1SJed Brown PetscInt dof; 66739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6674c459fbc1SJed Brown clsize += dof; 6675c459fbc1SJed Brown } 66769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 66771a271a75SMatthew G. Knepley /* Get array */ 66789566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 66791a271a75SMatthew G. Knepley /* Get values */ 6680ef90cfe2SMatthew G. Knepley if (numFields > 0) { 668197e99dd9SToby Isaac PetscInt offset = 0, f; 6682552f7358SJed Brown for (f = 0; f < numFields; ++f) { 668397e99dd9SToby Isaac const PetscInt **perms = NULL; 668497e99dd9SToby Isaac const PetscScalar **flips = NULL; 668597e99dd9SToby Isaac 66869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6687552f7358SJed Brown switch (mode) { 6688552f7358SJed Brown case INSERT_VALUES: 668997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 669097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 669197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 669297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 66933ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 66949371c9d4SSatish Balay } 66959371c9d4SSatish Balay break; 6696552f7358SJed Brown case INSERT_ALL_VALUES: 669797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 669897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 669997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 670097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67013ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 67029371c9d4SSatish Balay } 67039371c9d4SSatish Balay break; 6704a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 670597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 670697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 670797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 670897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67093ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 67109371c9d4SSatish Balay } 67119371c9d4SSatish Balay break; 6712552f7358SJed Brown case ADD_VALUES: 671397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 671497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 671597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 671697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67173ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 67189371c9d4SSatish Balay } 67199371c9d4SSatish Balay break; 6720552f7358SJed Brown case ADD_ALL_VALUES: 672197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 672297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 672397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 672497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67253ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 67269371c9d4SSatish Balay } 67279371c9d4SSatish Balay break; 6728304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 672997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 673097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 673197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 673297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67333ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 67349371c9d4SSatish Balay } 67359371c9d4SSatish Balay break; 6736d71ae5a4SJacob Faibussowitsch default: 6737d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6738552f7358SJed Brown } 67399566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 67401a271a75SMatthew G. Knepley } 6741552f7358SJed Brown } else { 67421a271a75SMatthew G. Knepley PetscInt dof, off; 674397e99dd9SToby Isaac const PetscInt **perms = NULL; 674497e99dd9SToby Isaac const PetscScalar **flips = NULL; 67451a271a75SMatthew G. Knepley 67469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 6747552f7358SJed Brown switch (mode) { 6748552f7358SJed Brown case INSERT_VALUES: 674997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 675097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 675197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 675297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 67543ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 67559371c9d4SSatish Balay } 67569371c9d4SSatish Balay break; 6757552f7358SJed Brown case INSERT_ALL_VALUES: 675897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 675997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 676097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 676197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 67633ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 67649371c9d4SSatish Balay } 67659371c9d4SSatish Balay break; 6766a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 676797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 676897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 676997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 677097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 67723ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 67739371c9d4SSatish Balay } 67749371c9d4SSatish Balay break; 6775552f7358SJed Brown case ADD_VALUES: 677697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 677797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 677897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 677997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 67813ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 67829371c9d4SSatish Balay } 67839371c9d4SSatish Balay break; 6784552f7358SJed Brown case ADD_ALL_VALUES: 678597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 678697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 678797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 678897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 67903ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 67919371c9d4SSatish Balay } 67929371c9d4SSatish Balay break; 6793304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 679497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 679597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 679697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 679797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 67989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 67993ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 68009371c9d4SSatish Balay } 68019371c9d4SSatish Balay break; 6802d71ae5a4SJacob Faibussowitsch default: 6803d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6804552f7358SJed Brown } 68059566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 6806552f7358SJed Brown } 68071a271a75SMatthew G. Knepley /* Cleanup points */ 68089566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 68091a271a75SMatthew G. Knepley /* Cleanup array */ 68109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 68113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6812552f7358SJed Brown } 6813552f7358SJed Brown 68145f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6815d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 6816d71ae5a4SJacob Faibussowitsch { 68175f790a90SMatthew G. Knepley PetscFunctionBegin; 681811cc89d2SBarry Smith *contains = PETSC_TRUE; 68195f790a90SMatthew G. Knepley if (label) { 6820d6177c40SToby Isaac PetscInt fdof; 68215f790a90SMatthew G. Knepley 682211cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 682311cc89d2SBarry Smith if (!*contains) { 68249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 68255f790a90SMatthew G. Knepley *offset += fdof; 68263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68275f790a90SMatthew G. Knepley } 68285f790a90SMatthew G. Knepley } 68293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68305f790a90SMatthew G. Knepley } 68315f790a90SMatthew G. Knepley 683297529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6833d71ae5a4SJacob 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) 6834d71ae5a4SJacob Faibussowitsch { 6835e07394fbSMatthew G. Knepley PetscSection clSection; 6836e07394fbSMatthew G. Knepley IS clPoints; 6837e07394fbSMatthew G. Knepley PetscScalar *array; 6838e07394fbSMatthew G. Knepley PetscInt *points = NULL; 683997529cf3SJed Brown const PetscInt *clp; 6840e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 684197e99dd9SToby Isaac PetscInt offset = 0, f; 6842e07394fbSMatthew G. Knepley 6843e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 6844e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 68459566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6846e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6847e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 68489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6849e07394fbSMatthew G. Knepley /* Get points */ 685007218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6851e07394fbSMatthew G. Knepley /* Get array */ 68529566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6853e07394fbSMatthew G. Knepley /* Get values */ 6854e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 685597e99dd9SToby Isaac const PetscInt **perms = NULL; 685697e99dd9SToby Isaac const PetscScalar **flips = NULL; 685711cc89d2SBarry Smith PetscBool contains; 685897e99dd9SToby Isaac 6859e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 6860e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6861e07394fbSMatthew G. Knepley PetscInt fdof; 68629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 6863e07394fbSMatthew G. Knepley offset += fdof; 6864e07394fbSMatthew G. Knepley } 6865e07394fbSMatthew G. Knepley continue; 6866e07394fbSMatthew G. Knepley } 68679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6868e07394fbSMatthew G. Knepley switch (mode) { 6869e07394fbSMatthew G. Knepley case INSERT_VALUES: 687097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 687197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 687297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 687397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 687411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 687511cc89d2SBarry Smith if (!contains) continue; 68769566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 68779371c9d4SSatish Balay } 68789371c9d4SSatish Balay break; 6879e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 688097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 688197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 688297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 688397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 688411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 688511cc89d2SBarry Smith if (!contains) continue; 68869566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 68879371c9d4SSatish Balay } 68889371c9d4SSatish Balay break; 6889e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 689097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 689197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 689297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 689397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 689411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 689511cc89d2SBarry Smith if (!contains) continue; 68969566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 68979371c9d4SSatish Balay } 68989371c9d4SSatish Balay break; 6899e07394fbSMatthew G. Knepley case ADD_VALUES: 690097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 690197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 690297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 690397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 690411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 690511cc89d2SBarry Smith if (!contains) continue; 69069566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 69079371c9d4SSatish Balay } 69089371c9d4SSatish Balay break; 6909e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 691097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 691197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 691297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 691397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 691411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 691511cc89d2SBarry Smith if (!contains) continue; 69169566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 69179371c9d4SSatish Balay } 69189371c9d4SSatish Balay break; 6919d71ae5a4SJacob Faibussowitsch default: 6920d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6921e07394fbSMatthew G. Knepley } 69229566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6923e07394fbSMatthew G. Knepley } 6924e07394fbSMatthew G. Knepley /* Cleanup points */ 69259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6926e07394fbSMatthew G. Knepley /* Cleanup array */ 69279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 69283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6929e07394fbSMatthew G. Knepley } 6930e07394fbSMatthew G. Knepley 6931d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6932d71ae5a4SJacob Faibussowitsch { 6933552f7358SJed Brown PetscMPIInt rank; 6934552f7358SJed Brown PetscInt i, j; 6935552f7358SJed Brown 6936552f7358SJed Brown PetscFunctionBegin; 69379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 693863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 693963a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 694063a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 6941b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 69423ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 6943b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 69449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 6945b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 6946519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 69479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 6948552f7358SJed Brown #else 69499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 6950552f7358SJed Brown #endif 6951552f7358SJed Brown } 69529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6953552f7358SJed Brown } 69543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6955552f7358SJed Brown } 6956552f7358SJed Brown 695705586334SMatthew G. Knepley /* 695805586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 695905586334SMatthew G. Knepley 696005586334SMatthew G. Knepley Input Parameters: 696105586334SMatthew G. Knepley + section - The section for this data layout 696236fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 696305586334SMatthew G. Knepley . point - The point contributing dofs with these indices 696405586334SMatthew G. Knepley . off - The global offset of this point 696505586334SMatthew G. Knepley . loff - The local offset of each field 6966a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 696705586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 696805586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 696905586334SMatthew G. Knepley 697005586334SMatthew G. Knepley Output Parameter: 697105586334SMatthew G. Knepley . indices - Indices for dofs on this point 697205586334SMatthew G. Knepley 697305586334SMatthew G. Knepley Level: developer 697405586334SMatthew G. Knepley 697505586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 697605586334SMatthew G. Knepley */ 6977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6978d71ae5a4SJacob Faibussowitsch { 6979e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 6980552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6981552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6982552f7358SJed Brown PetscInt cind = 0, k; 6983552f7358SJed Brown 6984552f7358SJed Brown PetscFunctionBegin; 698508401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 69869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 6988552f7358SJed Brown if (!cdof || setBC) { 698905586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 699005586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 699105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 699205586334SMatthew G. Knepley 699305586334SMatthew G. Knepley indices[ind] = off + k; 6994552f7358SJed Brown } 6995552f7358SJed Brown } else { 69969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 69974acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 699805586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 699905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 700005586334SMatthew G. Knepley 70014acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 70024acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 700305586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 70044acb8e1eSToby Isaac ++cind; 70054acb8e1eSToby Isaac } else { 700636fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7007552f7358SJed Brown } 7008552f7358SJed Brown } 7009552f7358SJed Brown } 7010e6ccafaeSMatthew G Knepley *loff += dof; 70113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7012552f7358SJed Brown } 7013552f7358SJed Brown 70147e29afd2SMatthew G. Knepley /* 701536fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 70167e29afd2SMatthew G. Knepley 701736fa2b79SJed Brown Input Parameters: 701836fa2b79SJed Brown + section - a section (global or local) 701920f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 702036fa2b79SJed Brown . point - point within section 702136fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 702236fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 702336fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 702436fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 702536fa2b79SJed Brown . permsoff - offset 702636fa2b79SJed Brown - indperm - index permutation 702736fa2b79SJed Brown 702836fa2b79SJed Brown Output Parameter: 702936fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 703036fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 703136fa2b79SJed Brown 703236fa2b79SJed Brown Notes: 703336fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 703436fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 703536fa2b79SJed Brown in the local vector. 703636fa2b79SJed Brown 703736fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 703836fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 703936fa2b79SJed Brown 704036fa2b79SJed Brown Developer Note: 704136fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 704236fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 704336fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 704436fa2b79SJed Brown 704536fa2b79SJed Brown Example: 704636fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 704736fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 704836fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 704936fa2b79SJed 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. 705036fa2b79SJed Brown 705136fa2b79SJed Brown Level: developer 70527e29afd2SMatthew G. Knepley */ 7053d71ae5a4SJacob 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[]) 7054d71ae5a4SJacob Faibussowitsch { 7055552f7358SJed Brown PetscInt numFields, foff, f; 7056552f7358SJed Brown 7057552f7358SJed Brown PetscFunctionBegin; 705808401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 70599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7060552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 70614acb8e1eSToby Isaac PetscInt fdof, cfdof; 7062552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 70634acb8e1eSToby Isaac PetscInt cind = 0, b; 70644acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7065552f7358SJed Brown 70669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 70679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7068552f7358SJed Brown if (!cfdof || setBC) { 706905586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 707005586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 707105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 707205586334SMatthew G. Knepley 707305586334SMatthew G. Knepley indices[ind] = off + foff + b; 707405586334SMatthew G. Knepley } 7075552f7358SJed Brown } else { 70769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 707705586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 707805586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 707905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 708005586334SMatthew G. Knepley 70814acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 708205586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7083552f7358SJed Brown ++cind; 7084552f7358SJed Brown } else { 708536fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7086552f7358SJed Brown } 7087552f7358SJed Brown } 7088552f7358SJed Brown } 708936fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7090552f7358SJed Brown foffs[f] += fdof; 7091552f7358SJed Brown } 70923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7093552f7358SJed Brown } 7094552f7358SJed Brown 70957e29afd2SMatthew G. Knepley /* 70967e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 70977e29afd2SMatthew G. Knepley 70987e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7099645102dcSJed Brown 7100645102dcSJed Brown Notes: 7101645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7102645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 71037e29afd2SMatthew G. Knepley */ 7104d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7105d71ae5a4SJacob Faibussowitsch { 71067e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 71077e29afd2SMatthew G. Knepley 71087e29afd2SMatthew G. Knepley PetscFunctionBegin; 71099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 71107e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 71117e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 71127e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 71137e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 71147e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 71157e29afd2SMatthew G. Knepley 71169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 71179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 71189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7119645102dcSJed Brown if (!cfdof) { 712005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 712105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 712205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 712305586334SMatthew G. Knepley 712405586334SMatthew G. Knepley indices[ind] = foff + b; 712505586334SMatthew G. Knepley } 71267e29afd2SMatthew G. Knepley } else { 71279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 712805586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 712905586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 713005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 713105586334SMatthew G. Knepley 71327e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 713305586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 71347e29afd2SMatthew G. Knepley ++cind; 71357e29afd2SMatthew G. Knepley } else { 713605586334SMatthew G. Knepley indices[ind] = foff + b - cind; 71377e29afd2SMatthew G. Knepley } 71387e29afd2SMatthew G. Knepley } 71397e29afd2SMatthew G. Knepley } 71407e29afd2SMatthew G. Knepley foffs[f] += fdof; 71417e29afd2SMatthew G. Knepley } 71423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71437e29afd2SMatthew G. Knepley } 71447e29afd2SMatthew G. Knepley 7145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft) 7146d71ae5a4SJacob Faibussowitsch { 7147d3d1a6afSToby Isaac Mat cMat; 7148d3d1a6afSToby Isaac PetscSection aSec, cSec; 7149d3d1a6afSToby Isaac IS aIS; 7150d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7151d3d1a6afSToby Isaac const PetscInt *anchors; 7152e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 7153d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7154d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 7155d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 7156d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7157d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 7158d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 7159d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 71606ecaa68aSToby Isaac PetscScalar *newValues = NULL, *tmpValues; 7161d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7162d3d1a6afSToby Isaac 7163d3d1a6afSToby Isaac PetscFunctionBegin; 7164d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7165d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 71669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7167d3d1a6afSToby Isaac 71689566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7169d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7170d3d1a6afSToby Isaac if (aSec) { 71719566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 71729566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 71739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7174d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7175d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7176d3d1a6afSToby Isaac * into the global matrix anyway) */ 7177d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7178d3d1a6afSToby Isaac PetscInt b = points[p]; 71794b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7180d3d1a6afSToby Isaac 71819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7182ad540459SPierre Jolivet if (!bSecDof) continue; 718348a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7184d3d1a6afSToby Isaac if (bDof) { 7185d3d1a6afSToby Isaac /* this point is constrained */ 7186d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7187d3d1a6afSToby Isaac PetscInt bOff, q; 7188d3d1a6afSToby Isaac 7189d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 7190d3d1a6afSToby Isaac newNumPoints += bDof; 71919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7192d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7193d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7194d3d1a6afSToby Isaac PetscInt aDof; 7195d3d1a6afSToby Isaac 71969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7197d3d1a6afSToby Isaac newNumIndices += aDof; 7198d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7199d3d1a6afSToby Isaac PetscInt fDof; 7200d3d1a6afSToby Isaac 72019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7202d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7203d3d1a6afSToby Isaac } 7204d3d1a6afSToby Isaac } 72059371c9d4SSatish Balay } else { 7206d3d1a6afSToby Isaac /* this point is not constrained */ 7207d3d1a6afSToby Isaac newNumPoints++; 72084b2f2278SToby Isaac newNumIndices += bSecDof; 7209d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7210d3d1a6afSToby Isaac PetscInt fDof; 7211d3d1a6afSToby Isaac 72129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7213d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7214d3d1a6afSToby Isaac } 7215d3d1a6afSToby Isaac } 7216d3d1a6afSToby Isaac } 7217d3d1a6afSToby Isaac } 7218d3d1a6afSToby Isaac if (!anyConstrained) { 721972b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 722072b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 722172b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 722272b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 72239566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 72243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7225d3d1a6afSToby Isaac } 7226d3d1a6afSToby Isaac 72276ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 72286ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 72296ecaa68aSToby Isaac 7230f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7231d3d1a6afSToby Isaac 72326ecaa68aSToby Isaac if (!outPoints && !outValues) { 72336ecaa68aSToby Isaac if (offsets) { 7234ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 72356ecaa68aSToby Isaac } 72369566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 72373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 72386ecaa68aSToby Isaac } 72396ecaa68aSToby Isaac 72401dca8a05SBarry 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); 7241d3d1a6afSToby Isaac 72429566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7243d3d1a6afSToby Isaac 7244d3d1a6afSToby Isaac /* workspaces */ 7245d3d1a6afSToby Isaac if (numFields) { 7246d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 72479566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 72489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7249d3d1a6afSToby Isaac } 72509371c9d4SSatish Balay } else { 72519566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 72529566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0])); 7253d3d1a6afSToby Isaac } 7254d3d1a6afSToby Isaac 7255d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 7256d3d1a6afSToby Isaac if (numFields) { 72574b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 72584b2f2278SToby Isaac 7259d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7260d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 72614b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7262d3d1a6afSToby Isaac 72639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 72644b2f2278SToby Isaac if (!bSecDof) { 72654b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 72664b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 72674b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 72684b2f2278SToby Isaac } 72694b2f2278SToby Isaac continue; 72704b2f2278SToby Isaac } 727148a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7272d3d1a6afSToby Isaac if (bDof) { 7273d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7274d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 7275d3d1a6afSToby Isaac 72769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 72779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7278d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7279d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7280d3d1a6afSToby Isaac PetscInt aFDof; 7281d3d1a6afSToby Isaac 72829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 7283d3d1a6afSToby Isaac allFDof += aFDof; 7284d3d1a6afSToby Isaac } 7285d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = allFDof; 7286d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = fDof * allFDof; 7287d3d1a6afSToby Isaac } 72889371c9d4SSatish Balay } else { 7289d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7290d3d1a6afSToby Isaac PetscInt fDof; 7291d3d1a6afSToby Isaac 72929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7293d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = fDof; 7294d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = 0; 7295d3d1a6afSToby Isaac } 7296d3d1a6afSToby Isaac } 7297d3d1a6afSToby Isaac } 72984b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 72994b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 73004b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 7301d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7302d3d1a6afSToby Isaac newPointOffsets[f][p + 1] += newPointOffsets[f][p]; 7303d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] += pointMatOffsets[f][p]; 7304d3d1a6afSToby Isaac } 730519f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 730619f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 73079566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 7308d3d1a6afSToby Isaac } 73099371c9d4SSatish Balay } else { 7310d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7311d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 73124b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7313d3d1a6afSToby Isaac 73149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 73154b2f2278SToby Isaac if (!bSecDof) { 73164b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 73174b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 73184b2f2278SToby Isaac continue; 73194b2f2278SToby Isaac } 732048a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7321d3d1a6afSToby Isaac if (bDof) { 73224b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 7323d3d1a6afSToby Isaac 73249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7325d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7326d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 7327d3d1a6afSToby Isaac 73289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7329d3d1a6afSToby Isaac allDof += aDof; 7330d3d1a6afSToby Isaac } 7331d3d1a6afSToby Isaac newPointOffsets[0][p + 1] = allDof; 73324b2f2278SToby Isaac pointMatOffsets[0][p + 1] = bSecDof * allDof; 73339371c9d4SSatish Balay } else { 73344b2f2278SToby Isaac newPointOffsets[0][p + 1] = bSecDof; 7335d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] = 0; 7336d3d1a6afSToby Isaac } 7337d3d1a6afSToby Isaac } 7338d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 7339d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 7340d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7341d3d1a6afSToby Isaac newPointOffsets[0][p + 1] += newPointOffsets[0][p]; 7342d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] += pointMatOffsets[0][p]; 7343d3d1a6afSToby Isaac } 73449566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 7345d3d1a6afSToby Isaac } 7346d3d1a6afSToby Isaac 73476ecaa68aSToby Isaac /* output arrays */ 73489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 73496ecaa68aSToby Isaac 7350d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 73519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 73529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 73539566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices)); 73549566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 7355d3d1a6afSToby Isaac if (numFields) { 7356d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 7357d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7358d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 73594b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7360d3d1a6afSToby Isaac 73619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7362ad540459SPierre Jolivet if (!bSecDof) continue; 736348a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7364d3d1a6afSToby Isaac if (bDof) { 7365d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7366d3d1a6afSToby Isaac 7367d3d1a6afSToby Isaac fStart[0] = 0; 7368d3d1a6afSToby Isaac fEnd[0] = 0; 7369d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7370d3d1a6afSToby Isaac PetscInt fDof; 7371d3d1a6afSToby Isaac 73729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7373d3d1a6afSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7374d3d1a6afSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7375d3d1a6afSToby Isaac } 73769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 73779566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7378d3d1a6afSToby Isaac 7379d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7380d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7381d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7382d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7383d3d1a6afSToby Isaac 7384d3d1a6afSToby Isaac fAnchorStart[f + 1] = fAnchorStart[f] + fDof; 7385d3d1a6afSToby Isaac fAnchorEnd[f + 1] = fAnchorStart[f + 1]; 7386d3d1a6afSToby Isaac } 73879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7388d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7389d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7390d3d1a6afSToby Isaac 7391d3d1a6afSToby Isaac /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7392d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7393d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 73949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 73959566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7396d3d1a6afSToby Isaac } 7397d3d1a6afSToby Isaac newP += bDof; 7398d3d1a6afSToby Isaac 73996ecaa68aSToby Isaac if (outValues) { 7400d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 740148a46eb9SPierre Jolivet for (f = 0; f < numFields; f++) PetscCall(MatGetValues(cMat, fEnd[f] - fStart[f], indices + fStart[f], fAnchorEnd[f] - fAnchorStart[f], newIndices + fAnchorStart[f], pointMat[f] + pointMatOffsets[f][p])); 7402d3d1a6afSToby Isaac } 74039371c9d4SSatish Balay } else { 7404d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7405d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7406d3d1a6afSToby Isaac newP++; 7407d3d1a6afSToby Isaac } 7408d3d1a6afSToby Isaac } 7409d3d1a6afSToby Isaac } else { 7410d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7411d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7412d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 74134b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7414d3d1a6afSToby Isaac 74159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7416ad540459SPierre Jolivet if (!bSecDof) continue; 741748a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7418d3d1a6afSToby Isaac if (bDof) { 7419d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7420d3d1a6afSToby Isaac 74219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 74229566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7423d3d1a6afSToby Isaac 74249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7425d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7426d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7427d3d1a6afSToby Isaac 7428d3d1a6afSToby Isaac /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7429d3d1a6afSToby Isaac 7430d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7431d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 74329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 74339566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7434d3d1a6afSToby Isaac } 7435d3d1a6afSToby Isaac newP += bDof; 7436d3d1a6afSToby Isaac 7437d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 743848a46eb9SPierre Jolivet if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p])); 74399371c9d4SSatish Balay } else { 7440d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7441d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7442d3d1a6afSToby Isaac newP++; 7443d3d1a6afSToby Isaac } 7444d3d1a6afSToby Isaac } 7445d3d1a6afSToby Isaac } 7446d3d1a6afSToby Isaac 74476ecaa68aSToby Isaac if (outValues) { 74489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 74499566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices)); 7450d3d1a6afSToby Isaac /* multiply constraints on the right */ 7451d3d1a6afSToby Isaac if (numFields) { 7452d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7453d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7454d3d1a6afSToby Isaac 7455d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7456d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7457d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7458d3d1a6afSToby Isaac PetscInt c, r, k; 7459d3d1a6afSToby Isaac PetscInt dof; 7460d3d1a6afSToby Isaac 74619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7462ad540459SPierre Jolivet if (!dof) continue; 7463d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7464d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p + 1] - cStart; 7465d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7466d3d1a6afSToby Isaac 7467d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7468d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7469ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7470d3d1a6afSToby Isaac } 7471d3d1a6afSToby Isaac } 74729371c9d4SSatish Balay } else { 7473d3d1a6afSToby Isaac /* copy this column as is */ 7474d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7475ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7476d3d1a6afSToby Isaac } 7477d3d1a6afSToby Isaac } 7478d3d1a6afSToby Isaac oldOff += dof; 7479d3d1a6afSToby Isaac } 7480d3d1a6afSToby Isaac } 74819371c9d4SSatish Balay } else { 7482d3d1a6afSToby Isaac PetscInt oldOff = 0; 7483d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7484d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7485d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7486d3d1a6afSToby Isaac PetscInt c, r, k; 7487d3d1a6afSToby Isaac PetscInt dof; 7488d3d1a6afSToby Isaac 74899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7490ad540459SPierre Jolivet if (!dof) continue; 7491d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7492d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p + 1] - cStart; 7493d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7494d3d1a6afSToby Isaac 7495d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7496d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7497ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7498d3d1a6afSToby Isaac } 7499d3d1a6afSToby Isaac } 75009371c9d4SSatish Balay } else { 7501d3d1a6afSToby Isaac /* copy this column as is */ 7502d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7503ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7504d3d1a6afSToby Isaac } 7505d3d1a6afSToby Isaac } 7506d3d1a6afSToby Isaac oldOff += dof; 7507d3d1a6afSToby Isaac } 7508d3d1a6afSToby Isaac } 7509d3d1a6afSToby Isaac 75106ecaa68aSToby Isaac if (multiplyLeft) { 75119566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues)); 75129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices)); 7513d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7514d3d1a6afSToby Isaac if (numFields) { 7515d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7516d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7517d3d1a6afSToby Isaac 7518d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7519d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7520d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7521d3d1a6afSToby Isaac PetscInt c, r, k; 7522d3d1a6afSToby Isaac PetscInt dof; 7523d3d1a6afSToby Isaac 75249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7525d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7526d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p + 1] - rStart; 7527d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7528d3d1a6afSToby Isaac 7529d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7530d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7531ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7532d3d1a6afSToby Isaac } 7533d3d1a6afSToby Isaac } 75349371c9d4SSatish Balay } else { 7535d3d1a6afSToby Isaac /* copy this row as is */ 7536d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7537ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7538d3d1a6afSToby Isaac } 7539d3d1a6afSToby Isaac } 7540d3d1a6afSToby Isaac oldOff += dof; 7541d3d1a6afSToby Isaac } 7542d3d1a6afSToby Isaac } 75439371c9d4SSatish Balay } else { 7544d3d1a6afSToby Isaac PetscInt oldOff = 0; 7545d3d1a6afSToby Isaac 7546d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7547d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7548d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7549d3d1a6afSToby Isaac PetscInt c, r, k; 7550d3d1a6afSToby Isaac PetscInt dof; 7551d3d1a6afSToby Isaac 75529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7553d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7554d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p + 1] - rStart; 7555d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7556d3d1a6afSToby Isaac 7557d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7558d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7559ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7560d3d1a6afSToby Isaac } 7561d3d1a6afSToby Isaac } 75629371c9d4SSatish Balay } else { 7563d3d1a6afSToby Isaac /* copy this row as is */ 75649fc93327SToby Isaac for (r = 0; r < dof; r++) { 7565ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7566d3d1a6afSToby Isaac } 7567d3d1a6afSToby Isaac } 7568d3d1a6afSToby Isaac oldOff += dof; 7569d3d1a6afSToby Isaac } 7570d3d1a6afSToby Isaac } 7571d3d1a6afSToby Isaac 75729566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 75739371c9d4SSatish Balay } else { 75746ecaa68aSToby Isaac newValues = tmpValues; 75756ecaa68aSToby Isaac } 75766ecaa68aSToby Isaac } 75776ecaa68aSToby Isaac 7578d3d1a6afSToby Isaac /* clean up */ 75799566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices)); 75809566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 75816ecaa68aSToby Isaac 7582d3d1a6afSToby Isaac if (numFields) { 7583d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 75849566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 75859566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 75869566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7587d3d1a6afSToby Isaac } 75889371c9d4SSatish Balay } else { 75899566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 75909566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 75919566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0])); 7592d3d1a6afSToby Isaac } 75939566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7594d3d1a6afSToby Isaac 7595d3d1a6afSToby Isaac /* output */ 75966ecaa68aSToby Isaac if (outPoints) { 7597d3d1a6afSToby Isaac *outPoints = newPoints; 75989371c9d4SSatish Balay } else { 75999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 76006ecaa68aSToby Isaac } 7601ad540459SPierre Jolivet if (outValues) *outValues = newValues; 7602ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 76033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7604d3d1a6afSToby Isaac } 7605d3d1a6afSToby Isaac 76064a1e0b3eSMatthew G. Knepley /*@C 760771f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 76087cd05799SMatthew G. Knepley 76097cd05799SMatthew G. Knepley Not collective 76107cd05799SMatthew G. Knepley 76117cd05799SMatthew G. Knepley Input Parameters: 7612a1cb98faSBarry Smith + dm - The `DM` 7613a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7614a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 761571f0bbf9SMatthew G. Knepley . point - The point defining the closure 761671f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 76177cd05799SMatthew G. Knepley 761871f0bbf9SMatthew G. Knepley Output Parameters: 761971f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 762071f0bbf9SMatthew G. Knepley . indices - The dof indices 762120f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 762220f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 76237cd05799SMatthew G. Knepley 7624a1cb98faSBarry Smith Level: advanced 762536fa2b79SJed Brown 7626a1cb98faSBarry Smith Notes: 7627a1cb98faSBarry Smith Must call `DMPlexRestoreClosureIndices()` to free allocated memory 7628a1cb98faSBarry Smith 762920f4b53cSBarry Smith If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 763020f4b53cSBarry Smith of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 763136fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 763220f4b53cSBarry Smith indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 763336fa2b79SJed Brown indices (with the above semantics) are implied. 76347cd05799SMatthew G. Knepley 76351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 7636a1cb98faSBarry Smith `PetscSection`, `DMGetGlobalSection()` 76374a1e0b3eSMatthew G. Knepley @*/ 7638d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7639d71ae5a4SJacob Faibussowitsch { 764071f0bbf9SMatthew G. Knepley /* Closure ordering */ 76417773e69fSMatthew G. Knepley PetscSection clSection; 76427773e69fSMatthew G. Knepley IS clPoints; 764371f0bbf9SMatthew G. Knepley const PetscInt *clp; 764471f0bbf9SMatthew G. Knepley PetscInt *points; 764571f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 764671f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 76474acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 764871f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 764971f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 765071f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 765171f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 765271f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 765371f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 765471f0bbf9SMatthew G. Knepley 765571f0bbf9SMatthew G. Knepley PetscInt *idx; 765671f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 765771f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 76587773e69fSMatthew G. Knepley 765971f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 76607773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 76617773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 766236fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 76634f572ea9SToby Isaac if (numIndices) PetscAssertPointer(numIndices, 6); 76644f572ea9SToby Isaac if (indices) PetscAssertPointer(indices, 7); 76654f572ea9SToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 8); 76664f572ea9SToby Isaac if (values) PetscAssertPointer(values, 9); 76679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 766863a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 76699566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 767071f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 767107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7672c459fbc1SJed Brown if (useClPerm) { 7673c459fbc1SJed Brown PetscInt depth, clsize; 76749566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7675c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7676c459fbc1SJed Brown PetscInt dof; 76779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7678c459fbc1SJed Brown clsize += dof; 7679c459fbc1SJed Brown } 76809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7681c459fbc1SJed Brown } 768271f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 768371f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 76847773e69fSMatthew G. Knepley PetscInt dof, fdof; 76857773e69fSMatthew G. Knepley 76869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 76877773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 76889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 76897773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 76907773e69fSMatthew G. Knepley } 769171f0bbf9SMatthew G. Knepley Ni += dof; 76927773e69fSMatthew G. Knepley } 76937773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 76941dca8a05SBarry 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); 769571f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 769671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 76979566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 76989566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 769971f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 770071f0bbf9SMatthew G. Knepley if (values && flips[f]) { 770171f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 77026ecaa68aSToby Isaac 770371f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 770471f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 770571f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 770671f0bbf9SMatthew G. Knepley 77079566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 77089566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 770971f0bbf9SMatthew G. Knepley if (flip) { 771071f0bbf9SMatthew G. Knepley PetscInt i, j, k; 771171f0bbf9SMatthew G. Knepley 771271f0bbf9SMatthew G. Knepley if (!valCopy) { 77139566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 771471f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 771571f0bbf9SMatthew G. Knepley *values = valCopy; 771671f0bbf9SMatthew G. Knepley } 771771f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 771871f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 771971f0bbf9SMatthew G. Knepley 772071f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 772171f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 772271f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 77236ecaa68aSToby Isaac } 77246ecaa68aSToby Isaac } 772571f0bbf9SMatthew G. Knepley } 772671f0bbf9SMatthew G. Knepley foffset += fdof; 772771f0bbf9SMatthew G. Knepley } 772871f0bbf9SMatthew G. Knepley } 772971f0bbf9SMatthew G. Knepley } 773071f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 77319566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 773271f0bbf9SMatthew G. Knepley if (NclC) { 77339566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 773471f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 77359566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 77369566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 773771f0bbf9SMatthew G. Knepley } 773871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 77399566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 77409566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 774171f0bbf9SMatthew G. Knepley } 77429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 774371f0bbf9SMatthew G. Knepley Ncl = NclC; 774471f0bbf9SMatthew G. Knepley Ni = NiC; 774571f0bbf9SMatthew G. Knepley points = pointsC; 774671f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 774771f0bbf9SMatthew G. Knepley } 774871f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 77499566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 775071f0bbf9SMatthew G. Knepley if (Nf) { 775171f0bbf9SMatthew G. Knepley PetscInt idxOff; 775271f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 775371f0bbf9SMatthew G. Knepley 77549371c9d4SSatish Balay if (outOffsets) { 77559371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 77569371c9d4SSatish Balay } 77579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 775871f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 775971f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 776071f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 776171f0bbf9SMatthew G. Knepley 77629566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 77637773e69fSMatthew G. Knepley } 77647773e69fSMatthew G. Knepley } else { 776571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 776671f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 776771f0bbf9SMatthew G. Knepley 77689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 776971f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 777071f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 777171f0bbf9SMatthew G. Knepley * global section. */ 77729566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 777371f0bbf9SMatthew G. Knepley } 777471f0bbf9SMatthew G. Knepley } 777571f0bbf9SMatthew G. Knepley } else { 777671f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 777771f0bbf9SMatthew G. Knepley 777871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 777971f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 77804acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 77814acb8e1eSToby Isaac 77829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 778371f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 778471f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 77859566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 77867773e69fSMatthew G. Knepley } 77877773e69fSMatthew G. Knepley } 778871f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 778971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 77909566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 77919566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 77924acb8e1eSToby Isaac } 779371f0bbf9SMatthew G. Knepley if (NclC) { 77949566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 77957773e69fSMatthew G. Knepley } else { 77969566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 77977773e69fSMatthew G. Knepley } 779871f0bbf9SMatthew G. Knepley 779971f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 780071f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 78013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 78027773e69fSMatthew G. Knepley } 78037773e69fSMatthew G. Knepley 78047cd05799SMatthew G. Knepley /*@C 780571f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 78067cd05799SMatthew G. Knepley 78077cd05799SMatthew G. Knepley Not collective 78087cd05799SMatthew G. Knepley 78097cd05799SMatthew G. Knepley Input Parameters: 7810a1cb98faSBarry Smith + dm - The `DM` 7811a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7812a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 781371f0bbf9SMatthew G. Knepley . point - The point defining the closure 781471f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 781571f0bbf9SMatthew G. Knepley 781671f0bbf9SMatthew G. Knepley Output Parameters: 781771f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 781871f0bbf9SMatthew G. Knepley . indices - The dof indices 781920f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 782020f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 782171f0bbf9SMatthew G. Knepley 7822a1cb98faSBarry Smith Level: advanced 782371f0bbf9SMatthew G. Knepley 7824a1cb98faSBarry Smith Notes: 7825a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 7826a1cb98faSBarry Smith 7827a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 782871f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 782971f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 783071f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 783171f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 78327cd05799SMatthew G. Knepley 78331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 78347cd05799SMatthew G. Knepley @*/ 7835d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7836d71ae5a4SJacob Faibussowitsch { 78377773e69fSMatthew G. Knepley PetscFunctionBegin; 78387773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 78394f572ea9SToby Isaac PetscAssertPointer(indices, 7); 78409566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 78413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 78427773e69fSMatthew G. Knepley } 78437773e69fSMatthew G. Knepley 78447f5d1fdeSMatthew G. Knepley /*@C 78457f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 78467f5d1fdeSMatthew G. Knepley 78477f5d1fdeSMatthew G. Knepley Not collective 78487f5d1fdeSMatthew G. Knepley 78497f5d1fdeSMatthew G. Knepley Input Parameters: 7850a1cb98faSBarry Smith + dm - The `DM` 785120f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 785220f4b53cSBarry Smith . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 78537f5d1fdeSMatthew G. Knepley . A - The matrix 7854a1cb98faSBarry Smith . point - The point in the `DM` 78557f5d1fdeSMatthew G. Knepley . values - The array of values 7856a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 78577f5d1fdeSMatthew G. Knepley 78587f5d1fdeSMatthew G. Knepley Level: intermediate 78597f5d1fdeSMatthew G. Knepley 78601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 78617f5d1fdeSMatthew G. Knepley @*/ 7862d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7863d71ae5a4SJacob Faibussowitsch { 7864552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 7865552f7358SJed Brown PetscInt *indices; 786671f0bbf9SMatthew G. Knepley PetscInt numIndices; 786771f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 7868552f7358SJed Brown PetscErrorCode ierr; 7869552f7358SJed Brown 7870552f7358SJed Brown PetscFunctionBegin; 7871552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 78729566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 78733dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 78749566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 78753dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 78763dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7877552f7358SJed Brown 78789566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 78790d644c17SKarl Rupp 78809566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 7881d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 78824a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7883552f7358SJed Brown if (ierr) { 7884552f7358SJed Brown PetscMPIInt rank; 7885552f7358SJed Brown 78869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 78879566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 78889566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 78899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 78909566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 7891c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 7892552f7358SJed Brown } 78934a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 78944a1e0b3eSMatthew G. Knepley PetscInt i; 78959566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 789663a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 78979566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 78984a1e0b3eSMatthew G. Knepley } 789971f0bbf9SMatthew G. Knepley 79009566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 79019566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 79023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79034acb8e1eSToby Isaac } 790471f0bbf9SMatthew G. Knepley 79054a1e0b3eSMatthew G. Knepley /*@C 790660225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 79074a1e0b3eSMatthew G. Knepley 79084a1e0b3eSMatthew G. Knepley Not collective 79094a1e0b3eSMatthew G. Knepley 79104a1e0b3eSMatthew G. Knepley Input Parameters: 7911a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 791220f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 791320f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 7914a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 791520f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 791620f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 79174a1e0b3eSMatthew G. Knepley . A - The matrix 7918a1cb98faSBarry Smith . point - The point in the `DM` 79194a1e0b3eSMatthew G. Knepley . values - The array of values 7920a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 79214a1e0b3eSMatthew G. Knepley 79224a1e0b3eSMatthew G. Knepley Level: intermediate 79234a1e0b3eSMatthew G. Knepley 79241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 79254a1e0b3eSMatthew G. Knepley @*/ 7926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7927d71ae5a4SJacob Faibussowitsch { 792871f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 792971f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 793071f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 793171f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 793271f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 793371f0bbf9SMatthew G. Knepley 793471f0bbf9SMatthew G. Knepley PetscFunctionBegin; 793571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 79369566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 793771f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 79389566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 793971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 794071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 79419566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 794271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 79439566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 794471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 794571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 794671f0bbf9SMatthew G. Knepley 79479566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 79489566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 794971f0bbf9SMatthew G. Knepley 79509566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 7951d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 79524a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 795371f0bbf9SMatthew G. Knepley if (ierr) { 795471f0bbf9SMatthew G. Knepley PetscMPIInt rank; 795571f0bbf9SMatthew G. Knepley 79569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 79579566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 79589566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 79599566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 79609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values)); 79619566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7962d3d1a6afSToby Isaac } 796371f0bbf9SMatthew G. Knepley 79649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 79659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 79669566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 79673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7968552f7358SJed Brown } 7969552f7358SJed Brown 7970d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7971d71ae5a4SJacob Faibussowitsch { 7972de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 7973de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 7974de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 7975de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 797617c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7977de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 7978412e9a14SMatthew G. Knepley DMPolytopeType ct; 79794ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7980de41b84cSMatthew G. Knepley PetscErrorCode ierr; 7981de41b84cSMatthew G. Knepley 7982de41b84cSMatthew G. Knepley PetscFunctionBegin; 7983de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7984de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 79859566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 7986de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 79879566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 7988de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 79899566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 7990de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 79919566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 7992de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7993de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 79949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 799563a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 79969566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 79979566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 7998de41b84cSMatthew G. Knepley /* Column indices */ 79999566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 80004ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8001de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8002de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 80039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8004de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8005de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8006de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8007de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8008de41b84cSMatthew G. Knepley ++q; 8009de41b84cSMatthew G. Knepley } 8010de41b84cSMatthew G. Knepley } 8011de41b84cSMatthew G. Knepley numCPoints = q; 8012de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8013de41b84cSMatthew G. Knepley PetscInt fdof; 8014de41b84cSMatthew G. Knepley 80159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 80164ca5e9f5SMatthew G. Knepley if (!dof) continue; 8017de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 80189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8019de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8020de41b84cSMatthew G. Knepley } 8021de41b84cSMatthew G. Knepley numCIndices += dof; 8022de41b84cSMatthew G. Knepley } 8023de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8024de41b84cSMatthew G. Knepley /* Row indices */ 80259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8026412e9a14SMatthew G. Knepley { 8027012bc364SMatthew G. Knepley DMPlexTransform tr; 8028012bc364SMatthew G. Knepley DMPolytopeType *rct; 8029012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8030012bc364SMatthew G. Knepley 80319566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 80329566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 80339566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8034012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 80359566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8036412e9a14SMatthew G. Knepley } 80379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8038de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8039de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 80409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8041de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 80429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8043de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8044de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 80459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 80464ca5e9f5SMatthew G. Knepley if (!dof) continue; 80479371c9d4SSatish Balay for (s = 0; s < q; ++s) 80489371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 80494ca5e9f5SMatthew G. Knepley if (s < q) continue; 8050de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8051de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8052de41b84cSMatthew G. Knepley ++q; 8053de41b84cSMatthew G. Knepley } 8054de41b84cSMatthew G. Knepley } 80559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8056de41b84cSMatthew G. Knepley } 8057de41b84cSMatthew G. Knepley numFPoints = q; 8058de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8059de41b84cSMatthew G. Knepley PetscInt fdof; 8060de41b84cSMatthew G. Knepley 80619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 80624ca5e9f5SMatthew G. Knepley if (!dof) continue; 8063de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 80649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8065de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8066de41b84cSMatthew G. Knepley } 8067de41b84cSMatthew G. Knepley numFIndices += dof; 8068de41b84cSMatthew G. Knepley } 8069de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8070de41b84cSMatthew G. Knepley 80711dca8a05SBarry 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); 80721dca8a05SBarry 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); 80739566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 80749566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8075de41b84cSMatthew G. Knepley if (numFields) { 80764acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 80774acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 80784acb8e1eSToby Isaac 80794acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 80809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 80819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8082de41b84cSMatthew G. Knepley } 80834acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 80849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 80859566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 80864acb8e1eSToby Isaac } 80874acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 80889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 80899566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 80904acb8e1eSToby Isaac } 80914acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 80929566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 80939566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8094de41b84cSMatthew G. Knepley } 8095de41b84cSMatthew G. Knepley } else { 80964acb8e1eSToby Isaac const PetscInt **permsF = NULL; 80974acb8e1eSToby Isaac const PetscInt **permsC = NULL; 80984acb8e1eSToby Isaac 80999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 81009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 81014acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 81024acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 81034acb8e1eSToby Isaac 81049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 81059566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8106de41b84cSMatthew G. Knepley } 81074acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 81084acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 81094acb8e1eSToby Isaac 81109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 81119566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8112de41b84cSMatthew G. Knepley } 81139566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 81149566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8115de41b84cSMatthew G. Knepley } 81169566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 81174acb8e1eSToby Isaac /* TODO: flips */ 8118d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8119de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8120de41b84cSMatthew G. Knepley if (ierr) { 8121de41b84cSMatthew G. Knepley PetscMPIInt rank; 8122de41b84cSMatthew G. Knepley 81239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 81249566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 81259566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 81269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 81279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8128de41b84cSMatthew G. Knepley } 81299566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 81309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 81319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 81329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 81333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8134de41b84cSMatthew G. Knepley } 8135de41b84cSMatthew G. Knepley 8136d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8137d71ae5a4SJacob Faibussowitsch { 81387c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 81397c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 81407c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 814117c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8142412e9a14SMatthew G. Knepley DMPolytopeType ct; 81437c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 81447c927364SMatthew G. Knepley 81457c927364SMatthew G. Knepley PetscFunctionBegin; 81467c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 81477c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 81489566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 81497c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 81509566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 81517c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 81529566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 81537c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 81549566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 81557c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 81569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 815763a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 81589566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 81599566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 81607c927364SMatthew G. Knepley /* Column indices */ 81619566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 81627c927364SMatthew G. Knepley maxFPoints = numCPoints; 81637c927364SMatthew G. Knepley /* Compress out points not in the section */ 81647c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 81659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 81667c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 81677c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 81687c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 81697c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 81707c927364SMatthew G. Knepley ++q; 81717c927364SMatthew G. Knepley } 81727c927364SMatthew G. Knepley } 81737c927364SMatthew G. Knepley numCPoints = q; 81747c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 81757c927364SMatthew G. Knepley PetscInt fdof; 81767c927364SMatthew G. Knepley 81779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 81787c927364SMatthew G. Knepley if (!dof) continue; 81797c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 81809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 81817c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 81827c927364SMatthew G. Knepley } 81837c927364SMatthew G. Knepley numCIndices += dof; 81847c927364SMatthew G. Knepley } 81857c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 81867c927364SMatthew G. Knepley /* Row indices */ 81879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8188412e9a14SMatthew G. Knepley { 8189012bc364SMatthew G. Knepley DMPlexTransform tr; 8190012bc364SMatthew G. Knepley DMPolytopeType *rct; 8191012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8192012bc364SMatthew G. Knepley 81939566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 81949566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 81959566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8196012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 81979566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8198412e9a14SMatthew G. Knepley } 81999566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 82007c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 82017c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 82029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 82037c927364SMatthew G. Knepley /* Compress out points not in the section */ 82049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 82057c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 82067c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 82079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 82087c927364SMatthew G. Knepley if (!dof) continue; 82099371c9d4SSatish Balay for (s = 0; s < q; ++s) 82109371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 82117c927364SMatthew G. Knepley if (s < q) continue; 82127c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 82137c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 82147c927364SMatthew G. Knepley ++q; 82157c927364SMatthew G. Knepley } 82167c927364SMatthew G. Knepley } 82179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 82187c927364SMatthew G. Knepley } 82197c927364SMatthew G. Knepley numFPoints = q; 82207c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 82217c927364SMatthew G. Knepley PetscInt fdof; 82227c927364SMatthew G. Knepley 82239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 82247c927364SMatthew G. Knepley if (!dof) continue; 82257c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 82269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 82277c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 82287c927364SMatthew G. Knepley } 82297c927364SMatthew G. Knepley numFIndices += dof; 82307c927364SMatthew G. Knepley } 82317c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 82327c927364SMatthew G. Knepley 82331dca8a05SBarry 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); 82341dca8a05SBarry 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); 82357c927364SMatthew G. Knepley if (numFields) { 82364acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 82374acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 82384acb8e1eSToby Isaac 82394acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 82409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 82419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 82427c927364SMatthew G. Knepley } 82434acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 82449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 82459566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 82464acb8e1eSToby Isaac } 82474acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 82489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 82499566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 82504acb8e1eSToby Isaac } 82514acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 82529566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 82539566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 82547c927364SMatthew G. Knepley } 82557c927364SMatthew G. Knepley } else { 82564acb8e1eSToby Isaac const PetscInt **permsF = NULL; 82574acb8e1eSToby Isaac const PetscInt **permsC = NULL; 82584acb8e1eSToby Isaac 82599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 82609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 82614acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 82624acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 82634acb8e1eSToby Isaac 82649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 82659566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 82667c927364SMatthew G. Knepley } 82674acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 82684acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 82694acb8e1eSToby Isaac 82709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 82719566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 82727c927364SMatthew G. Knepley } 82739566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 82749566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 82757c927364SMatthew G. Knepley } 82769566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 82779566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 82783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 82797c927364SMatthew G. Knepley } 82807c927364SMatthew G. Knepley 82817cd05799SMatthew G. Knepley /*@C 82827cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 82837cd05799SMatthew G. Knepley 82847cd05799SMatthew G. Knepley Input Parameter: 8285a1cb98faSBarry Smith . dm - The `DMPLEX` object 82867cd05799SMatthew G. Knepley 82877cd05799SMatthew G. Knepley Output Parameter: 82887cd05799SMatthew G. Knepley . cellHeight - The height of a cell 82897cd05799SMatthew G. Knepley 82907cd05799SMatthew G. Knepley Level: developer 82917cd05799SMatthew G. Knepley 82921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 82937cd05799SMatthew G. Knepley @*/ 8294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8295d71ae5a4SJacob Faibussowitsch { 8296552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8297552f7358SJed Brown 8298552f7358SJed Brown PetscFunctionBegin; 8299552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 83004f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8301552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 83023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8303552f7358SJed Brown } 8304552f7358SJed Brown 83057cd05799SMatthew G. Knepley /*@C 83067cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 83077cd05799SMatthew G. Knepley 83087cd05799SMatthew G. Knepley Input Parameters: 8309a1cb98faSBarry Smith + dm - The `DMPLEX` object 83107cd05799SMatthew G. Knepley - cellHeight - The height of a cell 83117cd05799SMatthew G. Knepley 83127cd05799SMatthew G. Knepley Level: developer 83137cd05799SMatthew G. Knepley 83141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 83157cd05799SMatthew G. Knepley @*/ 8316d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8317d71ae5a4SJacob Faibussowitsch { 8318552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8319552f7358SJed Brown 8320552f7358SJed Brown PetscFunctionBegin; 8321552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8322552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 83233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8324552f7358SJed Brown } 8325552f7358SJed Brown 8326e6139122SMatthew G. Knepley /*@ 83272827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8328e6139122SMatthew G. Knepley 83292827ebadSStefano Zampini Input Parameters: 83302827ebadSStefano Zampini + dm - The `DMPLEX` object 83312827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8332e6139122SMatthew G. Knepley 8333e6139122SMatthew G. Knepley Output Parameters: 83342827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 83352827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8336e6139122SMatthew G. Knepley 83372a9f31c0SMatthew G. Knepley Level: advanced 8338e6139122SMatthew G. Knepley 83392827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8340e6139122SMatthew G. Knepley @*/ 83412827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8342d71ae5a4SJacob Faibussowitsch { 83432827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 83442827ebadSStefano Zampini DMLabel label; 83452827ebadSStefano Zampini PetscInt pStart, pEnd; 8346e6139122SMatthew G. Knepley 8347e6139122SMatthew G. Knepley PetscFunctionBegin; 8348e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 83492827ebadSStefano Zampini if (start) { 83504f572ea9SToby Isaac PetscAssertPointer(start, 3); 83512827ebadSStefano Zampini *start = 0; 83522827ebadSStefano Zampini } 83532827ebadSStefano Zampini if (end) { 83544f572ea9SToby Isaac PetscAssertPointer(end, 4); 83552827ebadSStefano Zampini *end = 0; 83562827ebadSStefano Zampini } 83572827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 83582827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 83592827ebadSStefano Zampini if (mesh->tr) { 83602827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 83612827ebadSStefano Zampini } else { 83622827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 83632827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 83642827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 83652827ebadSStefano Zampini } 83663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8367e6139122SMatthew G. Knepley } 8368e6139122SMatthew G. Knepley 8369d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8370d71ae5a4SJacob Faibussowitsch { 8371552f7358SJed Brown PetscSection section, globalSection; 8372552f7358SJed Brown PetscInt *numbers, p; 8373552f7358SJed Brown 8374552f7358SJed Brown PetscFunctionBegin; 8375d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 83769566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 83779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 837848a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 83799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 83809566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 83819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8382552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 83839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8384ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8385ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8386552f7358SJed Brown } 83879566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8388ef48cebcSMatthew G. Knepley if (globalSize) { 8389ef48cebcSMatthew G. Knepley PetscLayout layout; 83909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 83919566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 83929566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8393ef48cebcSMatthew G. Knepley } 83949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 83959566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 83963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8397552f7358SJed Brown } 8398552f7358SJed Brown 8399d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8400d71ae5a4SJacob Faibussowitsch { 8401412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8402552f7358SJed Brown 8403552f7358SJed Brown PetscFunctionBegin; 84049566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 84059566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 84069566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 84079566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 84083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8409552f7358SJed Brown } 841081ed3555SMatthew G. Knepley 84118dab3259SMatthew G. Knepley /*@ 84127cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 84137cd05799SMatthew G. Knepley 84147cd05799SMatthew G. Knepley Input Parameter: 8415a1cb98faSBarry Smith . dm - The `DMPLEX` object 84167cd05799SMatthew G. Knepley 84177cd05799SMatthew G. Knepley Output Parameter: 84187cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 84197cd05799SMatthew G. Knepley 84207cd05799SMatthew G. Knepley Level: developer 84217cd05799SMatthew G. Knepley 84221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 84237cd05799SMatthew G. Knepley @*/ 8424d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8425d71ae5a4SJacob Faibussowitsch { 842681ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 842781ed3555SMatthew G. Knepley 842881ed3555SMatthew G. Knepley PetscFunctionBegin; 842981ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84309566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8431552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 84323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8433552f7358SJed Brown } 8434552f7358SJed Brown 8435d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8436d71ae5a4SJacob Faibussowitsch { 8437412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 843881ed3555SMatthew G. Knepley 843981ed3555SMatthew G. Knepley PetscFunctionBegin; 844081ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 84429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 84433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 844481ed3555SMatthew G. Knepley } 844581ed3555SMatthew G. Knepley 84468dab3259SMatthew G. Knepley /*@ 84476aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 84487cd05799SMatthew G. Knepley 84497cd05799SMatthew G. Knepley Input Parameter: 8450a1cb98faSBarry Smith . dm - The `DMPLEX` object 84517cd05799SMatthew G. Knepley 84527cd05799SMatthew G. Knepley Output Parameter: 84537cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 84547cd05799SMatthew G. Knepley 84557cd05799SMatthew G. Knepley Level: developer 84567cd05799SMatthew G. Knepley 84571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 84587cd05799SMatthew G. Knepley @*/ 8459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8460d71ae5a4SJacob Faibussowitsch { 8461552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8462552f7358SJed Brown 8463552f7358SJed Brown PetscFunctionBegin; 8464552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84659566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8466552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 84673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8468552f7358SJed Brown } 8469552f7358SJed Brown 84708dab3259SMatthew G. Knepley /*@ 8471966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8472966484cfSJed Brown 847320f4b53cSBarry Smith Collective 84747cd05799SMatthew G. Knepley 84757cd05799SMatthew G. Knepley Input Parameter: 8476a1cb98faSBarry Smith . dm - The `DMPLEX` object 84777cd05799SMatthew G. Knepley 84787cd05799SMatthew G. Knepley Output Parameter: 84797cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 84807cd05799SMatthew G. Knepley 8481a1cb98faSBarry Smith Level: developer 8482966484cfSJed Brown 8483a1cb98faSBarry Smith Notes: 8484a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8485966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8486966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8487966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8488966484cfSJed Brown 8489966484cfSJed Brown The partitioned mesh is 8490966484cfSJed Brown ``` 8491966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8492966484cfSJed Brown ``` 8493966484cfSJed Brown and its global numbering is 8494966484cfSJed Brown ``` 8495966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8496966484cfSJed Brown ``` 8497966484cfSJed Brown Then the global numbering is provided as 8498966484cfSJed Brown ``` 8499966484cfSJed Brown [0] Number of indices in set 5 8500966484cfSJed Brown [0] 0 0 8501966484cfSJed Brown [0] 1 1 8502966484cfSJed Brown [0] 2 3 8503966484cfSJed Brown [0] 3 4 8504966484cfSJed Brown [0] 4 -6 8505966484cfSJed Brown [1] Number of indices in set 3 8506966484cfSJed Brown [1] 0 2 8507966484cfSJed Brown [1] 1 5 8508966484cfSJed Brown [1] 2 6 8509966484cfSJed Brown ``` 8510966484cfSJed Brown 85111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 85127cd05799SMatthew G. Knepley @*/ 8513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8514d71ae5a4SJacob Faibussowitsch { 8515ef48cebcSMatthew G. Knepley IS nums[4]; 8516862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8517ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 85180c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8519ef48cebcSMatthew G. Knepley 8520ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8521ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 85230c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 85249566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 85250c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8526862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8527862913ffSStefano Zampini PetscInt end; 8528862913ffSStefano Zampini 8529862913ffSStefano Zampini depths[d] = depth - d; 85309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 85310c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8532862913ffSStefano Zampini } 85330c15888dSMatthew G. Knepley if (empty) 85340c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 85350c15888dSMatthew G. Knepley depths[d] = -1; 85360c15888dSMatthew G. Knepley starts[d] = -1; 85370c15888dSMatthew G. Knepley } 85380c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 85391c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8540ad540459SPierre 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]); 85410c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8542ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8543ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8544ef48cebcSMatthew G. Knepley 85459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 85469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8547ef48cebcSMatthew G. Knepley shift += gsize; 8548ef48cebcSMatthew G. Knepley } 8549d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 85509566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 85513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8552ef48cebcSMatthew G. Knepley } 8553ef48cebcSMatthew G. Knepley 855408a22f4bSMatthew G. Knepley /*@ 855508a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 855608a22f4bSMatthew G. Knepley 855708a22f4bSMatthew G. Knepley Input Parameter: 8558a1cb98faSBarry Smith . dm - The `DMPLEX` object 855908a22f4bSMatthew G. Knepley 856008a22f4bSMatthew G. Knepley Output Parameter: 856108a22f4bSMatthew G. Knepley . ranks - The rank field 856208a22f4bSMatthew G. Knepley 8563a1cb98faSBarry Smith Options Database Key: 856420f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 856508a22f4bSMatthew G. Knepley 856608a22f4bSMatthew G. Knepley Level: intermediate 856708a22f4bSMatthew G. Knepley 85681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 856908a22f4bSMatthew G. Knepley @*/ 8570d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8571d71ae5a4SJacob Faibussowitsch { 857208a22f4bSMatthew G. Knepley DM rdm; 857308a22f4bSMatthew G. Knepley PetscFE fe; 857408a22f4bSMatthew G. Knepley PetscScalar *r; 857508a22f4bSMatthew G. Knepley PetscMPIInt rank; 8576a55f9a55SMatthew G. Knepley DMPolytopeType ct; 857708a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8578a55f9a55SMatthew G. Knepley PetscBool simplex; 857908a22f4bSMatthew G. Knepley 858008a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8581f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85824f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 85839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 85849566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 85859566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 85869566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 85879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8588a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 85899566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 85909566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 85919566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 85929566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 85939566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 85949566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 85959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 85969566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 859708a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 859808a22f4bSMatthew G. Knepley PetscScalar *lr; 859908a22f4bSMatthew G. Knepley 86009566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 860171f09efeSPierre Jolivet if (lr) *lr = rank; 860208a22f4bSMatthew G. Knepley } 86039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 86049566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 86053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 860608a22f4bSMatthew G. Knepley } 860708a22f4bSMatthew G. Knepley 8608ca8062c8SMatthew G. Knepley /*@ 860918e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 861018e14f0cSMatthew G. Knepley 861118e14f0cSMatthew G. Knepley Input Parameters: 861220f4b53cSBarry Smith + dm - The `DMPLEX` 861320f4b53cSBarry Smith - label - The `DMLabel` 861418e14f0cSMatthew G. Knepley 861518e14f0cSMatthew G. Knepley Output Parameter: 861618e14f0cSMatthew G. Knepley . val - The label value field 861718e14f0cSMatthew G. Knepley 861820f4b53cSBarry Smith Options Database Key: 861920f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 862018e14f0cSMatthew G. Knepley 862118e14f0cSMatthew G. Knepley Level: intermediate 862218e14f0cSMatthew G. Knepley 86231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 862418e14f0cSMatthew G. Knepley @*/ 8625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8626d71ae5a4SJacob Faibussowitsch { 862718e14f0cSMatthew G. Knepley DM rdm; 862818e14f0cSMatthew G. Knepley PetscFE fe; 862918e14f0cSMatthew G. Knepley PetscScalar *v; 863018e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 863118e14f0cSMatthew G. Knepley 863218e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 863318e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86344f572ea9SToby Isaac PetscAssertPointer(label, 2); 86354f572ea9SToby Isaac PetscAssertPointer(val, 3); 86369566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 86379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 86389566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 86399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "label_value")); 86409566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 86419566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 86429566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 86439566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 86449566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 86459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*val, "label_value")); 86469566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 864718e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 864818e14f0cSMatthew G. Knepley PetscScalar *lv; 864918e14f0cSMatthew G. Knepley PetscInt cval; 865018e14f0cSMatthew G. Knepley 86519566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 86529566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 865318e14f0cSMatthew G. Knepley *lv = cval; 865418e14f0cSMatthew G. Knepley } 86559566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 86569566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 86573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 865818e14f0cSMatthew G. Knepley } 865918e14f0cSMatthew G. Knepley 866018e14f0cSMatthew G. Knepley /*@ 8661ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8662ca8062c8SMatthew G. Knepley 866369916449SMatthew G. Knepley Input Parameter: 8664a1cb98faSBarry Smith . dm - The `DMPLEX` object 8665a1cb98faSBarry Smith 8666a1cb98faSBarry Smith Level: developer 8667ca8062c8SMatthew G. Knepley 866895eb5ee5SVaclav Hapla Notes: 866995eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 867095eb5ee5SVaclav Hapla 867120f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 8672ca8062c8SMatthew G. Knepley 86731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8674ca8062c8SMatthew G. Knepley @*/ 8675d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 8676d71ae5a4SJacob Faibussowitsch { 8677ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8678ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8679ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 868057beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 868157beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8682ca8062c8SMatthew G. Knepley 8683ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8684ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86859566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 86869566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 86879566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8688ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 86899566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8690ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 86919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 86929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8693ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 869442e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 869542e66dfaSMatthew G. Knepley PetscInt d; 869642e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 86979371c9d4SSatish Balay if (cone[c] == cone[d]) { 86989371c9d4SSatish Balay dup = PETSC_TRUE; 86999371c9d4SSatish Balay break; 87009371c9d4SSatish Balay } 870142e66dfaSMatthew G. Knepley } 87029566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 87039566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8704ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8705ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8706ca8062c8SMatthew G. Knepley } 870742e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 870863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 870948a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 87109566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 871163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 871248a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 87139566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 871463a3b9bcSJacob 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]); 8715f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8716ca8062c8SMatthew G. Knepley } 871742e66dfaSMatthew G. Knepley } 87189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 87199371c9d4SSatish Balay if (p != pp) { 87209371c9d4SSatish Balay storagecheck = PETSC_FALSE; 87219371c9d4SSatish Balay continue; 87229371c9d4SSatish Balay } 87239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 87249566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8725ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 87269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 87279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8728ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 87299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 87309371c9d4SSatish Balay if (cone[c] != pp) { 87319371c9d4SSatish Balay c = 0; 87329371c9d4SSatish Balay break; 87339371c9d4SSatish Balay } 8734ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8735ca8062c8SMatthew G. Knepley } 8736ca8062c8SMatthew G. Knepley if (c >= coneSize) { 873763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 873848a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 87399566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 874063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 874148a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 87429566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 874363a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8744ca8062c8SMatthew G. Knepley } 8745ca8062c8SMatthew G. Knepley } 8746ca8062c8SMatthew G. Knepley } 874757beb4faSStefano Zampini if (storagecheck) { 87489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 87499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 875063a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 875157beb4faSStefano Zampini } 87523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8753ca8062c8SMatthew G. Knepley } 8754ca8062c8SMatthew G. Knepley 8755412e9a14SMatthew G. Knepley /* 8756412e9a14SMatthew 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. 8757412e9a14SMatthew G. Knepley */ 8758d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8759d71ae5a4SJacob Faibussowitsch { 8760412e9a14SMatthew G. Knepley DMPolytopeType cct; 8761412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8762412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8763412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8764412e9a14SMatthew G. Knepley 8765412e9a14SMatthew G. Knepley PetscFunctionBegin; 8766412e9a14SMatthew G. Knepley *unsplit = 0; 8767412e9a14SMatthew G. Knepley switch (ct) { 8768d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 8769d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 8770d71ae5a4SJacob Faibussowitsch break; 8771412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 87729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 87739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8774412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 87759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 8776412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8777412e9a14SMatthew G. Knepley } 8778412e9a14SMatthew G. Knepley break; 8779412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8780412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 87819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 87829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8783412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 87849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 87859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8786412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 87879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8788412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8789412e9a14SMatthew G. Knepley PetscInt p; 87909371c9d4SSatish Balay for (p = 0; p < npt; ++p) 87919371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 8792412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8793412e9a14SMatthew G. Knepley } 8794412e9a14SMatthew G. Knepley } 8795412e9a14SMatthew G. Knepley } 8796412e9a14SMatthew G. Knepley break; 8797d71ae5a4SJacob Faibussowitsch default: 8798d71ae5a4SJacob Faibussowitsch break; 8799412e9a14SMatthew G. Knepley } 8800412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 88019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8802412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8803412e9a14SMatthew G. Knepley } 88043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8805412e9a14SMatthew G. Knepley } 8806412e9a14SMatthew G. Knepley 8807ca8062c8SMatthew G. Knepley /*@ 8808ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8809ca8062c8SMatthew G. Knepley 8810ca8062c8SMatthew G. Knepley Input Parameters: 8811a1cb98faSBarry Smith + dm - The `DMPLEX` object 881258723a97SMatthew G. Knepley - cellHeight - Normally 0 8813ca8062c8SMatthew G. Knepley 8814a1cb98faSBarry Smith Level: developer 8815a1cb98faSBarry Smith 881695eb5ee5SVaclav Hapla Notes: 881795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 881825c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 8819ca8062c8SMatthew G. Knepley 882020f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 882195eb5ee5SVaclav Hapla 88221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8823ca8062c8SMatthew G. Knepley @*/ 8824d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8825d71ae5a4SJacob Faibussowitsch { 8826412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 8827412e9a14SMatthew G. Knepley DMPolytopeType ct; 8828412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 8829ca8062c8SMatthew G. Knepley 8830ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8831ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88329566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 88339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 88349566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8835412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8836412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 8837412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 883858723a97SMatthew G. Knepley 88399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 884063a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 8841412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 8842412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 88439566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 884463a3b9bcSJacob 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)); 8845412e9a14SMatthew G. Knepley } 88469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 884758723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 884858723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 8849412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 885058723a97SMatthew G. Knepley } 88519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8852412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 8853412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8854412e9a14SMatthew G. Knepley PetscInt unsplit; 885542363296SMatthew G. Knepley 88569566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8857412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 885842363296SMatthew G. Knepley } 885963a3b9bcSJacob 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)); 886042363296SMatthew G. Knepley } 88613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8862ca8062c8SMatthew G. Knepley } 88639bf0dad6SMatthew G. Knepley 88649bf0dad6SMatthew G. Knepley /*@ 88659bf0dad6SMatthew 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 88669bf0dad6SMatthew G. Knepley 886720f4b53cSBarry Smith Collective 8868899ea2b8SJacob Faibussowitsch 88699bf0dad6SMatthew G. Knepley Input Parameters: 8870a1cb98faSBarry Smith + dm - The `DMPLEX` object 88719bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 88729bf0dad6SMatthew G. Knepley 8873a1cb98faSBarry Smith Level: developer 8874a1cb98faSBarry Smith 887545da879fSVaclav Hapla Notes: 887645da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 887745da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 887845da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 887945da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 88809bf0dad6SMatthew G. Knepley 8881a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 888295eb5ee5SVaclav Hapla 88831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 88849bf0dad6SMatthew G. Knepley @*/ 8885d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8886d71ae5a4SJacob Faibussowitsch { 8887ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8888899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 88899bf0dad6SMatthew G. Knepley 88909bf0dad6SMatthew G. Knepley PetscFunctionBegin; 88919bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88928f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 88933ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 88948f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 88953ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 88963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8897899ea2b8SJacob Faibussowitsch } 8898899ea2b8SJacob Faibussowitsch 88999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 89009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 89019566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8902ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 89039566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 89043554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8905412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 8906412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 8907ba2698f1SMatthew G. Knepley DMPolytopeType ct; 8908412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 8909412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 89109bf0dad6SMatthew G. Knepley 89119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 89129566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8913412e9a14SMatthew G. Knepley if (unsplit) continue; 89149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 89159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 89169566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 89179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 89189bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 89199bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 89209bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 89219bf0dad6SMatthew G. Knepley } 89229566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 892363a3b9bcSJacob 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); 89249bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 8925d4961f80SStefano Zampini DMPolytopeType fct; 89269bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 89279bf0dad6SMatthew G. Knepley 89289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 89299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 89309bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 89319bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 89329bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 89339bf0dad6SMatthew G. Knepley } 893463a3b9bcSJacob 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]); 89359bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 8936b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 8937b5a892a1SMatthew G. Knepley PetscInt v1; 8938b5a892a1SMatthew G. Knepley 89399566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 894063a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 89419566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 894263a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 89439566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 894463a3b9bcSJacob 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]); 8945b5a892a1SMatthew G. Knepley } 89469bf0dad6SMatthew G. Knepley } 89479566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 8948412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 89499bf0dad6SMatthew G. Knepley } 89509566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 89519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 89529bf0dad6SMatthew G. Knepley } 89533554e41dSMatthew G. Knepley } 89543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8955552f7358SJed Brown } 89563913d7c8SMatthew G. Knepley 8957bb6a34a8SMatthew G. Knepley /*@ 8958bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 8959bb6a34a8SMatthew G. Knepley 8960bb6a34a8SMatthew G. Knepley Input Parameter: 8961a1cb98faSBarry Smith . dm - The `DMPLEX` object 8962a1cb98faSBarry Smith 8963a1cb98faSBarry Smith Level: developer 8964bb6a34a8SMatthew G. Knepley 896595eb5ee5SVaclav Hapla Notes: 896695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 896795eb5ee5SVaclav Hapla 896820f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 8969bb6a34a8SMatthew G. Knepley 89701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8971bb6a34a8SMatthew G. Knepley @*/ 8972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 8973d71ae5a4SJacob Faibussowitsch { 8974a2a9e04cSMatthew G. Knepley Vec coordinates; 8975bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 8976bb6a34a8SMatthew G. Knepley PetscReal vol; 897751a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 8978bb6a34a8SMatthew G. Knepley 8979bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 89809566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 89819566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 89823ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 89839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8984bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 89859566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8986a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 89879566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 89883ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 8989412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8990412e9a14SMatthew G. Knepley DMPolytopeType ct; 8991412e9a14SMatthew G. Knepley PetscInt unsplit; 8992412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 8993412e9a14SMatthew G. Knepley 89949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 8995412e9a14SMatthew G. Knepley switch (ct) { 8996412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 8997412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8998d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8999d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9000d71ae5a4SJacob Faibussowitsch break; 9001d71ae5a4SJacob Faibussowitsch default: 9002d71ae5a4SJacob Faibussowitsch break; 9003412e9a14SMatthew G. Knepley } 9004412e9a14SMatthew G. Knepley switch (ct) { 9005412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9006412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9007412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9008d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9009d71ae5a4SJacob Faibussowitsch continue; 9010d71ae5a4SJacob Faibussowitsch default: 9011d71ae5a4SJacob Faibussowitsch break; 9012412e9a14SMatthew G. Knepley } 90139566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9014412e9a14SMatthew G. Knepley if (unsplit) continue; 90159566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 90161dca8a05SBarry 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); 901763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 90186858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 90196858538eSMatthew G. Knepley if (depth > 1) { 90209566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 90211dca8a05SBarry 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); 902263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9023bb6a34a8SMatthew G. Knepley } 9024bb6a34a8SMatthew G. Knepley } 90253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9026bb6a34a8SMatthew G. Knepley } 9027bb6a34a8SMatthew G. Knepley 902803da9461SVaclav Hapla /*@ 902920f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 90307726db96SVaclav Hapla 903120f4b53cSBarry Smith Collective 903203da9461SVaclav Hapla 903303da9461SVaclav Hapla Input Parameters: 9034a1cb98faSBarry Smith + dm - The `DMPLEX` object 903520f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9036a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9037a1cb98faSBarry Smith 9038a1cb98faSBarry Smith Level: developer 903903da9461SVaclav Hapla 9040e83a0d2dSVaclav Hapla Notes: 9041e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 904203da9461SVaclav Hapla 9043a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 904495eb5ee5SVaclav Hapla 9045d7d32a9aSMatthew G. Knepley Extra roots can come from priodic cuts, where additional points appear on the boundary 9046d7d32a9aSMatthew G. Knepley 90471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 904803da9461SVaclav Hapla @*/ 9049d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9050d71ae5a4SJacob Faibussowitsch { 90517726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 90527726db96SVaclav Hapla const PetscInt *locals; 90537726db96SVaclav Hapla const PetscSFNode *remotes; 9054f0cfc026SVaclav Hapla PetscBool distributed; 90557726db96SVaclav Hapla MPI_Comm comm; 90567726db96SVaclav Hapla PetscMPIInt rank; 905703da9461SVaclav Hapla 905803da9461SVaclav Hapla PetscFunctionBegin; 905903da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90607726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 90617726db96SVaclav Hapla else pointSF = dm->sf; 90627726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 90637726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 90647726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 90657726db96SVaclav Hapla { 90667726db96SVaclav Hapla PetscMPIInt mpiFlag; 90677726db96SVaclav Hapla 90687726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 90697726db96SVaclav 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); 90707726db96SVaclav Hapla } 90717726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 90729566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 90737726db96SVaclav Hapla if (!distributed) { 90747726db96SVaclav 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); 90753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 90768918e3e2SVaclav Hapla } 90777726db96SVaclav 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); 90787726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 907903da9461SVaclav Hapla 90807726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 90817726db96SVaclav Hapla { 90827726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 90837726db96SVaclav Hapla 90847726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 90857726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9086d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 90877726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 90887726db96SVaclav Hapla } 90897726db96SVaclav Hapla 90907726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 90917726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 90927726db96SVaclav Hapla PetscAssert(remotes[l].rank != (PetscInt)rank, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains local point %" PetscInt_FMT " <- (%" PetscInt_FMT ",%" PetscInt_FMT ")", locals ? locals[l] : l, remotes[l].rank, remotes[l].index); 90937726db96SVaclav Hapla } 90947726db96SVaclav Hapla 90957726db96SVaclav Hapla /* Check there are no cells in interface */ 90967726db96SVaclav Hapla if (!overlap) { 90977726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 90987726db96SVaclav Hapla 90999566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 91009566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9101f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 91027726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9103f5869d18SMatthew G. Knepley 91047726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 91057726db96SVaclav Hapla } 910603da9461SVaclav Hapla } 9107ece87651SVaclav Hapla 91087726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 91097726db96SVaclav Hapla { 91107726db96SVaclav Hapla const PetscInt *rootdegree; 91117726db96SVaclav Hapla 91127726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 91137726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9114f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 91157726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9116f5869d18SMatthew G. Knepley const PetscInt *cone; 9117f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9118f5869d18SMatthew G. Knepley 91199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 91209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9121f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9122f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 91237726db96SVaclav Hapla if (locals) { 91249566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 91257726db96SVaclav Hapla } else { 91267726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 91277726db96SVaclav Hapla } 912863a3b9bcSJacob 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]); 9129f5869d18SMatthew G. Knepley } 9130f5869d18SMatthew G. Knepley } 9131ece87651SVaclav Hapla } 91327726db96SVaclav Hapla } 91333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 913403da9461SVaclav Hapla } 913503da9461SVaclav Hapla 91367f9d8d6cSVaclav Hapla /*@ 913720f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 91387f9d8d6cSVaclav Hapla 91397f9d8d6cSVaclav Hapla Input Parameter: 9140a1cb98faSBarry Smith . dm - The `DMPLEX` object 9141a1cb98faSBarry Smith 9142a1cb98faSBarry Smith Level: developer 91437f9d8d6cSVaclav Hapla 91447f9d8d6cSVaclav Hapla Notes: 91457f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 91467f9d8d6cSVaclav Hapla 914720f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 91487f9d8d6cSVaclav Hapla 914920f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 91507f9d8d6cSVaclav Hapla 91511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 91527f9d8d6cSVaclav Hapla @*/ 9153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9154d71ae5a4SJacob Faibussowitsch { 91557f9d8d6cSVaclav Hapla PetscInt cellHeight; 91567f9d8d6cSVaclav Hapla 9157b5a892a1SMatthew G. Knepley PetscFunctionBegin; 91587f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 91599566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 91609566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 91619566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 91629566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9163d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 91649566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 91653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9166b5a892a1SMatthew G. Knepley } 9167b5a892a1SMatthew G. Knepley 91689371c9d4SSatish Balay typedef struct cell_stats { 9169068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9170068a5610SStefano Zampini PetscInt count; 9171068a5610SStefano Zampini } cell_stats_t; 9172068a5610SStefano Zampini 9173d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9174d71ae5a4SJacob Faibussowitsch { 9175068a5610SStefano Zampini PetscInt i, N = *len; 9176068a5610SStefano Zampini 9177068a5610SStefano Zampini for (i = 0; i < N; i++) { 9178068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9179068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9180068a5610SStefano Zampini 9181068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9182068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9183068a5610SStefano Zampini B->sum += A->sum; 9184068a5610SStefano Zampini B->squaresum += A->squaresum; 9185068a5610SStefano Zampini B->count += A->count; 9186068a5610SStefano Zampini } 9187068a5610SStefano Zampini } 9188068a5610SStefano Zampini 9189068a5610SStefano Zampini /*@ 919043fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9191068a5610SStefano Zampini 919220f4b53cSBarry Smith Collective 91938261a58bSMatthew G. Knepley 9194068a5610SStefano Zampini Input Parameters: 9195a1cb98faSBarry Smith + dm - The `DMPLEX` object 919620f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9197a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9198a1cb98faSBarry Smith 9199a1cb98faSBarry Smith Level: developer 9200068a5610SStefano Zampini 920195eb5ee5SVaclav Hapla Notes: 920295eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 920395eb5ee5SVaclav Hapla 9204a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9205068a5610SStefano Zampini 92061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9207068a5610SStefano Zampini @*/ 9208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9209d71ae5a4SJacob Faibussowitsch { 9210068a5610SStefano Zampini DM dmCoarse; 921143fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 921243fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 921343fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 921443fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9215412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 921643fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9217068a5610SStefano Zampini 9218068a5610SStefano Zampini PetscFunctionBegin; 9219068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9220068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9221068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9222068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9223068a5610SStefano Zampini stats.count = 0; 9224068a5610SStefano Zampini 92259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 92269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 92279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 92289566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 92299566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 92309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9231412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9232068a5610SStefano Zampini PetscInt i; 9233068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9234068a5610SStefano Zampini 92359566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 923663a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 923743fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9238068a5610SStefano Zampini frobJ += J[i] * J[i]; 9239068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9240068a5610SStefano Zampini } 9241068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9242068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9243068a5610SStefano Zampini 9244068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9245068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9246068a5610SStefano Zampini stats.sum += cond; 9247068a5610SStefano Zampini stats.squaresum += cond2; 9248068a5610SStefano Zampini stats.count++; 92498261a58bSMatthew G. Knepley if (output && cond > limit) { 925043fa8764SMatthew G. Knepley PetscSection coordSection; 925143fa8764SMatthew G. Knepley Vec coordsLocal; 925243fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 925343fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 925443fa8764SMatthew G. Knepley 92559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 92569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 92579566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 925863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 925943fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 926063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 926143fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 92629566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 92639566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 926443fa8764SMatthew G. Knepley } 92659566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 926643fa8764SMatthew G. Knepley } 92679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 926843fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 926943fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 927043fa8764SMatthew G. Knepley 927143fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 927243fa8764SMatthew G. Knepley PetscReal len; 927343fa8764SMatthew G. Knepley 92749566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 927563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 927643fa8764SMatthew G. Knepley } 927743fa8764SMatthew G. Knepley } 92789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 92799566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 928043fa8764SMatthew G. Knepley } 9281068a5610SStefano Zampini } 92829566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9283068a5610SStefano Zampini 9284068a5610SStefano Zampini if (size > 1) { 9285068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9286068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9287068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9288068a5610SStefano Zampini MPI_Op statReduce; 9289068a5610SStefano Zampini 92909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 92919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 92929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 92939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 92949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 92959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9296068a5610SStefano Zampini } else { 92979566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9298068a5610SStefano Zampini } 9299dd400576SPatrick Sanan if (rank == 0) { 9300068a5610SStefano Zampini count = globalStats.count; 9301068a5610SStefano Zampini min = globalStats.min; 9302068a5610SStefano Zampini max = globalStats.max; 9303068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9304068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9305068a5610SStefano Zampini } 9306068a5610SStefano Zampini 930748a46eb9SPierre 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)); 93089566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9309068a5610SStefano Zampini 93109566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9311068a5610SStefano Zampini if (dmCoarse) { 9312068a5610SStefano Zampini PetscBool isplex; 9313068a5610SStefano Zampini 93149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 93151baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9316068a5610SStefano Zampini } 93173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9318068a5610SStefano Zampini } 9319068a5610SStefano Zampini 9320f108dbd7SJacob Faibussowitsch /*@ 9321f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9322f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9323f108dbd7SJacob Faibussowitsch 932420f4b53cSBarry Smith Collective 9325f108dbd7SJacob Faibussowitsch 9326f108dbd7SJacob Faibussowitsch Input Parameters: 9327a1cb98faSBarry Smith + dm - The `DMPLEX` object 9328a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9329f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9330f108dbd7SJacob Faibussowitsch 9331f108dbd7SJacob Faibussowitsch Output Parameters: 933220f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9333a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9334f108dbd7SJacob Faibussowitsch 9335f108dbd7SJacob Faibussowitsch Options Database Keys: 9336a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9337f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9338f108dbd7SJacob Faibussowitsch 9339a1cb98faSBarry Smith Level: intermediate 9340a1cb98faSBarry Smith 9341f108dbd7SJacob Faibussowitsch Notes: 9342a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9343f108dbd7SJacob Faibussowitsch 9344a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9345f108dbd7SJacob Faibussowitsch 9346f108dbd7SJacob 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 9347f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9348f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9349f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9350f108dbd7SJacob Faibussowitsch 9351f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9352f108dbd7SJacob Faibussowitsch 9353a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9354f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9355f108dbd7SJacob Faibussowitsch 9356f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9357f108dbd7SJacob Faibussowitsch 93581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9359f108dbd7SJacob Faibussowitsch @*/ 9360d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9361d71ae5a4SJacob Faibussowitsch { 93626ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 93636ed19f2fSJacob Faibussowitsch PetscInt *idx; 93646ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9365f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 93666ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9367f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9368f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9369f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9370f108dbd7SJacob Faibussowitsch IS glob; 9371f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9372f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9373f108dbd7SJacob Faibussowitsch 9374f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9375f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9376ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 93774f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 93786bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 93799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 93809566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 938163a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 93826ed19f2fSJacob Faibussowitsch { 93836ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 93846ed19f2fSJacob Faibussowitsch 93859566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9386f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9387f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9388f108dbd7SJacob Faibussowitsch 93899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 939098921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9391f108dbd7SJacob Faibussowitsch } 93926ed19f2fSJacob Faibussowitsch } 9393f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 93944f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 93959566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 93969566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 93979371c9d4SSatish Balay } else { 93989371c9d4SSatish Balay *OrthQualLabel = NULL; 93999371c9d4SSatish Balay } 94009566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94019566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 94029566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 94039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 94049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 94059566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 94069566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 94079566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 94089566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 94099566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 94109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 94119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 94129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 94139566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 94149566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 94159566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 94169566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 94179566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 94186ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 94196ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9420f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9421f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9422898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9423f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9424f108dbd7SJacob Faibussowitsch 94256ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9426f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9427f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 94289566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 94299566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9430f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 94319566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 94326ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 94336ed19f2fSJacob Faibussowitsch PetscInt i; 94346ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9435f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9436f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9437f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9438f108dbd7SJacob Faibussowitsch 9439f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9440f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 94419566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9442f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 94436ed19f2fSJacob Faibussowitsch { 94446ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 94456ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 94466ed19f2fSJacob Faibussowitsch 94479566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 94489566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 94499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 94506ed19f2fSJacob Faibussowitsch } 9451f108dbd7SJacob Faibussowitsch 9452f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9453f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9454f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9455f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9456f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9457addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9458addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9459addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9460f108dbd7SJacob Faibussowitsch } 9461addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9462addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9463addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9464f108dbd7SJacob Faibussowitsch 9465f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9466f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9467f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9468f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9469f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9470f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9471f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9472f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9473f108dbd7SJacob Faibussowitsch } 9474ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9475ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9476f108dbd7SJacob Faibussowitsch } 94779566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 94789566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9479f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 94806ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9481f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 94829566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9483f108dbd7SJacob Faibussowitsch } 9484f108dbd7SJacob Faibussowitsch } 94859566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 94869566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 94879566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 94889566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 94899566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 94909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9491f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 94929566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9493f108dbd7SJacob Faibussowitsch } 94949566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 94959566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vwr)); 94969566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 94973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9498f108dbd7SJacob Faibussowitsch } 9499f108dbd7SJacob Faibussowitsch 9500d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 95011eb70e55SToby Isaac * interpolator construction */ 9502d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9503d71ae5a4SJacob Faibussowitsch { 95041eb70e55SToby Isaac PetscSection section, newSection, gsection; 95051eb70e55SToby Isaac PetscSF sf; 95061eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 95071eb70e55SToby Isaac 95081eb70e55SToby Isaac PetscFunctionBegin; 95091eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95104f572ea9SToby Isaac PetscAssertPointer(odm, 2); 95119566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 95129566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9513712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 95141eb70e55SToby Isaac if (!ghasConstraints) { 95159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 95161eb70e55SToby Isaac *odm = dm; 95173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 95181eb70e55SToby Isaac } 95199566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 95209566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 95219566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 95229566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 95239566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 95249566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 95259566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 95263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 95271eb70e55SToby Isaac } 95281eb70e55SToby Isaac 9529d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9530d71ae5a4SJacob Faibussowitsch { 95311eb70e55SToby Isaac DM dmco, dmfo; 95321eb70e55SToby Isaac Mat interpo; 95331eb70e55SToby Isaac Vec rscale; 95341eb70e55SToby Isaac Vec cglobalo, clocal; 95351eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 95361eb70e55SToby Isaac PetscBool regular; 95371eb70e55SToby Isaac 95381eb70e55SToby Isaac PetscFunctionBegin; 95399566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 95409566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 95419566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 95429566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 95439566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 95449566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 95459566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 95469566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 95479566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 95489566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 95499566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 95509566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 95519566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 95529566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 95539566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 95549566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 95559566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 95569566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 95579566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 95589566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 95599566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 95609566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 95619566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 95629566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 95631eb70e55SToby Isaac *shift = fglobal; 95649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 95659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 95669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 95679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 95689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 95699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 95709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 95719566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 95723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 95731eb70e55SToby Isaac } 95741eb70e55SToby Isaac 9575d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9576d71ae5a4SJacob Faibussowitsch { 95771eb70e55SToby Isaac PetscObject shifto; 95781eb70e55SToby Isaac Vec shift; 95791eb70e55SToby Isaac 95801eb70e55SToby Isaac PetscFunctionBegin; 95811eb70e55SToby Isaac if (!interp) { 95821eb70e55SToby Isaac Vec rscale; 95831eb70e55SToby Isaac 95849566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 95859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 95861eb70e55SToby Isaac } else { 95879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 95881eb70e55SToby Isaac } 95899566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 95901eb70e55SToby Isaac if (!shifto) { 95919566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 95929566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 95931eb70e55SToby Isaac shifto = (PetscObject)shift; 95949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 95951eb70e55SToby Isaac } 95961eb70e55SToby Isaac shift = (Vec)shifto; 95979566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 95989566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 95999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 96003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 96011eb70e55SToby Isaac } 96021eb70e55SToby Isaac 9603bceba477SMatthew G. Knepley /* Pointwise interpolation 9604bceba477SMatthew G. Knepley Just code FEM for now 9605bceba477SMatthew G. Knepley u^f = I u^c 96064ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 96074ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 96084ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9609bceba477SMatthew G. Knepley */ 9610d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9611d71ae5a4SJacob Faibussowitsch { 9612bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9613bceba477SMatthew G. Knepley PetscInt m, n; 9614a063dac3SMatthew G. Knepley void *ctx; 961568132eb9SMatthew G. Knepley DM cdm; 9616cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9617bceba477SMatthew G. Knepley 9618bceba477SMatthew G. Knepley PetscFunctionBegin; 96199566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 96209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 96219566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 96229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 962368132eb9SMatthew G. Knepley 96249566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 96259566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 96269566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 96279566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 96289566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 962968132eb9SMatthew G. Knepley 96309566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 96319566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 96329566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 96339566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 96349566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 96354db47ee9SStefano Zampini if (scaling) { 96365d1c2e58SMatthew G. Knepley /* Use naive scaling */ 96379566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 96384db47ee9SStefano Zampini } 96393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9640a063dac3SMatthew G. Knepley } 9641bceba477SMatthew G. Knepley 9642d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9643d71ae5a4SJacob Faibussowitsch { 96446dbf9973SLawrence Mitchell VecScatter ctx; 964590748bafSMatthew G. Knepley 9646a063dac3SMatthew G. Knepley PetscFunctionBegin; 96479566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 96489566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 96499566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 96503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9651bceba477SMatthew G. Knepley } 9652bceba477SMatthew G. Knepley 9653d71ae5a4SJacob 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[]) 9654d71ae5a4SJacob Faibussowitsch { 965500635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 965600635df3SMatthew G. Knepley PetscInt c; 965700635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 96583e9753d6SMatthew G. Knepley } 96593e9753d6SMatthew G. Knepley 9660d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9661d71ae5a4SJacob Faibussowitsch { 9662b4937a87SMatthew G. Knepley DM dmc; 9663b4937a87SMatthew G. Knepley PetscDS ds; 9664b4937a87SMatthew G. Knepley Vec ones, locmass; 9665b4937a87SMatthew G. Knepley IS cellIS; 9666b4937a87SMatthew G. Knepley PetscFormKey key; 9667b4937a87SMatthew G. Knepley PetscInt depth; 9668b4937a87SMatthew G. Knepley 9669b4937a87SMatthew G. Knepley PetscFunctionBegin; 96709566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 96719566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 96729566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 96739566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 96749566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 96759566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 96769566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 96779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 96789566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 96799566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 96809566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9681b4937a87SMatthew G. Knepley key.label = NULL; 9682b4937a87SMatthew G. Knepley key.value = 0; 9683b4937a87SMatthew G. Knepley key.field = 0; 9684b4937a87SMatthew G. Knepley key.part = 0; 96859566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 96869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 96879566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 96889566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 96899566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 96909566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 96919566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 96929566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 96933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9694b4937a87SMatthew G. Knepley } 9695b4937a87SMatthew G. Knepley 9696d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9697d71ae5a4SJacob Faibussowitsch { 9698bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9699bd041c0cSMatthew G. Knepley PetscInt m, n; 9700bd041c0cSMatthew G. Knepley void *ctx; 9701bd041c0cSMatthew G. Knepley DM cdm; 9702bd041c0cSMatthew G. Knepley PetscBool regular; 9703bd041c0cSMatthew G. Knepley 9704bd041c0cSMatthew G. Knepley PetscFunctionBegin; 97053e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 97063e9753d6SMatthew G. Knepley DM dmc; 97073e9753d6SMatthew G. Knepley PetscDS ds; 9708b4937a87SMatthew G. Knepley PetscWeakForm wf; 97093e9753d6SMatthew G. Knepley Vec u; 97103e9753d6SMatthew G. Knepley IS cellIS; 971106ad1575SMatthew G. Knepley PetscFormKey key; 97123e9753d6SMatthew G. Knepley PetscInt depth; 97133e9753d6SMatthew G. Knepley 97149566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 97159566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 97169566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 97179566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 97189566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 97199566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 97209566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 97218d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 97229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 97239566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 97249566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 97256528b96dSMatthew G. Knepley key.label = NULL; 97266528b96dSMatthew G. Knepley key.value = 0; 97276528b96dSMatthew G. Knepley key.field = 0; 972806ad1575SMatthew G. Knepley key.part = 0; 97299566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 97309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 97318d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 97329566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 97333e9753d6SMatthew G. Knepley } else { 97349566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 97359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 97369566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 97379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9738bd041c0cSMatthew G. Knepley 97399566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 97409566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 97419566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 97429566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9743bd041c0cSMatthew G. Knepley 97449566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 97459566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 97469566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 97479566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 97483e9753d6SMatthew G. Knepley } 97499566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 97503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9751bd041c0cSMatthew G. Knepley } 9752bd041c0cSMatthew G. Knepley 97530aef6b92SMatthew G. Knepley /*@ 97540aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 97550aef6b92SMatthew G. Knepley 97560aef6b92SMatthew G. Knepley Input Parameter: 9757a1cb98faSBarry Smith . dm - The `DMPLEX` object 97580aef6b92SMatthew G. Knepley 97590aef6b92SMatthew G. Knepley Output Parameter: 97600aef6b92SMatthew G. Knepley . regular - The flag 97610aef6b92SMatthew G. Knepley 97620aef6b92SMatthew G. Knepley Level: intermediate 97630aef6b92SMatthew G. Knepley 97641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 97650aef6b92SMatthew G. Knepley @*/ 9766d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9767d71ae5a4SJacob Faibussowitsch { 97680aef6b92SMatthew G. Knepley PetscFunctionBegin; 97690aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97704f572ea9SToby Isaac PetscAssertPointer(regular, 2); 97710aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 97723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97730aef6b92SMatthew G. Knepley } 97740aef6b92SMatthew G. Knepley 97750aef6b92SMatthew G. Knepley /*@ 97760aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 97770aef6b92SMatthew G. Knepley 97780aef6b92SMatthew G. Knepley Input Parameters: 9779a1cb98faSBarry Smith + dm - The `DMPLEX` object 97800aef6b92SMatthew G. Knepley - regular - The flag 97810aef6b92SMatthew G. Knepley 97820aef6b92SMatthew G. Knepley Level: intermediate 97830aef6b92SMatthew G. Knepley 97841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 97850aef6b92SMatthew G. Knepley @*/ 9786d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9787d71ae5a4SJacob Faibussowitsch { 97880aef6b92SMatthew G. Knepley PetscFunctionBegin; 97890aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97900aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 97913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97920aef6b92SMatthew G. Knepley } 97930aef6b92SMatthew G. Knepley 9794a68b90caSToby Isaac /*@ 9795f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9796a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 9797a68b90caSToby Isaac 9798a1cb98faSBarry Smith Not Collective 9799a68b90caSToby Isaac 9800f899ff85SJose E. Roman Input Parameter: 9801a1cb98faSBarry Smith . dm - The `DMPLEX` object 9802a68b90caSToby Isaac 9803a68b90caSToby Isaac Output Parameters: 980420f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 980520f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 9806a68b90caSToby Isaac 9807a68b90caSToby Isaac Level: intermediate 9808a68b90caSToby Isaac 98091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 9810a68b90caSToby Isaac @*/ 9811d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9812d71ae5a4SJacob Faibussowitsch { 9813a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9814a68b90caSToby Isaac 9815a68b90caSToby Isaac PetscFunctionBegin; 9816a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 98179566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 9818a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 9819a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 98203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9821a68b90caSToby Isaac } 9822a68b90caSToby Isaac 9823a68b90caSToby Isaac /*@ 9824a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 9825a68b90caSToby Isaac 982620f4b53cSBarry Smith Collective 9827a68b90caSToby Isaac 9828a68b90caSToby Isaac Input Parameters: 9829a1cb98faSBarry Smith + dm - The `DMPLEX` object 9830a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 9831a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 9832a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 9833a68b90caSToby Isaac 9834a68b90caSToby Isaac Level: intermediate 9835a68b90caSToby Isaac 9836a1cb98faSBarry Smith Notes: 9837a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 9838a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 9839a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 9840a4e35b19SJacob Faibussowitsch 9841a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 9842a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 9843a1cb98faSBarry Smith 984420f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 9845a1cb98faSBarry Smith 98461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9847a68b90caSToby Isaac @*/ 9848d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9849d71ae5a4SJacob Faibussowitsch { 9850a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9851e228b242SToby Isaac PetscMPIInt result; 9852a68b90caSToby Isaac 9853a68b90caSToby Isaac PetscFunctionBegin; 9854a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9855e228b242SToby Isaac if (anchorSection) { 9856e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 98579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 98581dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 9859e228b242SToby Isaac } 9860e228b242SToby Isaac if (anchorIS) { 9861e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 98629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 98631dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 9864e228b242SToby Isaac } 9865a68b90caSToby Isaac 98669566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 98679566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 9868a68b90caSToby Isaac plex->anchorSection = anchorSection; 9869a68b90caSToby Isaac 98709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 98719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 9872a68b90caSToby Isaac plex->anchorIS = anchorIS; 9873a68b90caSToby Isaac 9874cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9875a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 9876a68b90caSToby Isaac const PetscInt *anchors; 9877a68b90caSToby Isaac 98789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 98799566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 98809566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 9881a68b90caSToby Isaac for (a = 0; a < size; a++) { 9882a68b90caSToby Isaac PetscInt p; 9883a68b90caSToby Isaac 9884a68b90caSToby Isaac p = anchors[a]; 9885a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 9886a68b90caSToby Isaac PetscInt dof; 9887a68b90caSToby Isaac 98889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 9889a68b90caSToby Isaac if (dof) { 98909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 989163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 9892a68b90caSToby Isaac } 9893a68b90caSToby Isaac } 9894a68b90caSToby Isaac } 98959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 9896a68b90caSToby Isaac } 9897f7c74593SToby Isaac /* reset the generic constraints */ 98989566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 98993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9900a68b90caSToby Isaac } 9901a68b90caSToby Isaac 9902d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9903d71ae5a4SJacob Faibussowitsch { 9904f7c74593SToby Isaac PetscSection anchorSection; 99056995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9906a68b90caSToby Isaac 9907a68b90caSToby Isaac PetscFunctionBegin; 9908a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 99099566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 99109566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 99119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 99126995de1eSToby Isaac if (numFields) { 9913719ab38cSToby Isaac PetscInt f; 99149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 9915719ab38cSToby Isaac 9916719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 9917719ab38cSToby Isaac PetscInt numComp; 9918719ab38cSToby Isaac 99199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 99209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 9921719ab38cSToby Isaac } 99226995de1eSToby Isaac } 99239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 99249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 99256995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 99266995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 99276995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 99289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 9929a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 99309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 9931a68b90caSToby Isaac if (dof) { 99329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 99339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 9934a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 99359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 99369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 9937a68b90caSToby Isaac } 9938a68b90caSToby Isaac } 9939a68b90caSToby Isaac } 99409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 99419566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 99423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9943a68b90caSToby Isaac } 9944a68b90caSToby Isaac 9945d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9946d71ae5a4SJacob Faibussowitsch { 9947f7c74593SToby Isaac PetscSection aSec; 9948ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 99490ac89760SToby Isaac const PetscInt *anchors; 99500ac89760SToby Isaac PetscInt numFields, f; 995166ad2231SToby Isaac IS aIS; 9952e19f7ee6SMark Adams MatType mtype; 9953e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 99540ac89760SToby Isaac 99550ac89760SToby Isaac PetscFunctionBegin; 99560ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 99579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 99589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 99599566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 99609566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 99619566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 99629566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 99639566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 99649566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 9965e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 9966e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9967e19f7ee6SMark Adams else mtype = MATSEQAIJ; 99689566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 99699566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 99709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 99716995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 99729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 99739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 99749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 99750ac89760SToby Isaac i[0] = 0; 99769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 99770ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 9978f19733c5SToby Isaac PetscInt rDof, rOff, r; 9979f19733c5SToby Isaac 99809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 9981f19733c5SToby Isaac if (!rDof) continue; 99829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 99830ac89760SToby Isaac if (numFields) { 99840ac89760SToby Isaac for (f = 0; f < numFields; f++) { 99850ac89760SToby Isaac annz = 0; 9986f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 9987f19733c5SToby Isaac a = anchors[rOff + r]; 9988ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 99899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 99900ac89760SToby Isaac annz += aDof; 99910ac89760SToby Isaac } 99929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 99939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 9994ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 99950ac89760SToby Isaac } 99962f7452b8SBarry Smith } else { 99970ac89760SToby Isaac annz = 0; 99989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 99990ac89760SToby Isaac for (q = 0; q < dof; q++) { 10000ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10001ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 100029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 100030ac89760SToby Isaac annz += aDof; 100040ac89760SToby Isaac } 100059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 100069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10007ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 100080ac89760SToby Isaac } 100090ac89760SToby Isaac } 100100ac89760SToby Isaac nnz = i[m]; 100119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 100120ac89760SToby Isaac offset = 0; 100130ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 100140ac89760SToby Isaac if (numFields) { 100150ac89760SToby Isaac for (f = 0; f < numFields; f++) { 100169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 100170ac89760SToby Isaac for (q = 0; q < dof; q++) { 100180ac89760SToby Isaac PetscInt rDof, rOff, r; 100199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 100209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 100210ac89760SToby Isaac for (r = 0; r < rDof; r++) { 100220ac89760SToby Isaac PetscInt s; 100230ac89760SToby Isaac 100240ac89760SToby Isaac a = anchors[rOff + r]; 10025ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 100269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 100279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10028ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 100290ac89760SToby Isaac } 100300ac89760SToby Isaac } 100310ac89760SToby Isaac } 100322f7452b8SBarry Smith } else { 100339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 100340ac89760SToby Isaac for (q = 0; q < dof; q++) { 100350ac89760SToby Isaac PetscInt rDof, rOff, r; 100369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 100379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 100380ac89760SToby Isaac for (r = 0; r < rDof; r++) { 100390ac89760SToby Isaac PetscInt s; 100400ac89760SToby Isaac 100410ac89760SToby Isaac a = anchors[rOff + r]; 10042ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 100439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 100449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10045ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 100460ac89760SToby Isaac } 100470ac89760SToby Isaac } 100480ac89760SToby Isaac } 100490ac89760SToby Isaac } 100509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 100519566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 100529566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 100539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 100543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100550ac89760SToby Isaac } 100560ac89760SToby Isaac 10057d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10058d71ae5a4SJacob Faibussowitsch { 10059f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10060f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1006166ad2231SToby Isaac Mat cMat; 1006266ad2231SToby Isaac 1006366ad2231SToby Isaac PetscFunctionBegin; 1006466ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100659566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1006666ad2231SToby Isaac if (anchorSection) { 1006744a7f3ddSMatthew G. Knepley PetscInt Nf; 10068e228b242SToby Isaac 100699566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 100709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 100719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 100729566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 100739566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 100749566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 100759566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 100769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1007766ad2231SToby Isaac } 100783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1007966ad2231SToby Isaac } 10080a93c429eSMatthew G. Knepley 10081d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10082d71ae5a4SJacob Faibussowitsch { 10083a93c429eSMatthew G. Knepley IS subis; 10084a93c429eSMatthew G. Knepley PetscSection section, subsection; 10085a93c429eSMatthew G. Knepley 10086a93c429eSMatthew G. Knepley PetscFunctionBegin; 100879566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1008828b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1008928b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10090a93c429eSMatthew G. Knepley /* Create subdomain */ 100919566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 10092a93c429eSMatthew G. Knepley /* Create submodel */ 100939566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 100949566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 100959566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 100969566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 100979566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10098a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10099a93c429eSMatthew G. Knepley if (is) { 10100a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10101a93c429eSMatthew G. Knepley IS spIS; 10102a93c429eSMatthew G. Knepley const PetscInt *spmap; 10103a93c429eSMatthew G. Knepley PetscInt *subIndices; 10104a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10105a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10106a93c429eSMatthew G. Knepley 101079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 101089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 101099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 101109566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 101119566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 101129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10113a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10114a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10115a93c429eSMatthew G. Knepley 101169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10117a93c429eSMatthew G. Knepley if (gdof > 0) { 10118a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10119a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10120a93c429eSMatthew G. Knepley 101219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 101229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10123a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10124a93c429eSMatthew G. Knepley } 10125a93c429eSMatthew G. Knepley subSize += pSubSize; 10126a93c429eSMatthew G. Knepley if (pSubSize) { 10127a93c429eSMatthew G. Knepley if (bs < 0) { 10128a93c429eSMatthew G. Knepley bs = pSubSize; 10129a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10130a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10131a93c429eSMatthew G. Knepley bs = 1; 10132a93c429eSMatthew G. Knepley } 10133a93c429eSMatthew G. Knepley } 10134a93c429eSMatthew G. Knepley } 10135a93c429eSMatthew G. Knepley } 10136a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 101379371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 101389371c9d4SSatish Balay bsLocal[1] = bs; 101399566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 101409371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 101419371c9d4SSatish Balay bs = 1; 101429371c9d4SSatish Balay } else { 101439371c9d4SSatish Balay bs = bsMinMax[0]; 101449371c9d4SSatish Balay } 101459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10146a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10147a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10148a93c429eSMatthew G. Knepley 101499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10150a93c429eSMatthew G. Knepley if (gdof > 0) { 10151a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10152a93c429eSMatthew G. Knepley 101539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10154a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10155a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10156a93c429eSMatthew G. Knepley 10157a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10158a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 101599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 101609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10161a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10162a93c429eSMatthew G. Knepley } 101639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 101649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10165ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10166a93c429eSMatthew G. Knepley } 10167a93c429eSMatthew G. Knepley } 10168a93c429eSMatthew G. Knepley } 101699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 101709566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10171a93c429eSMatthew G. Knepley if (bs > 1) { 10172a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10173a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10174a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10175a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 101769371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 101779371c9d4SSatish Balay set = 0; 101789371c9d4SSatish Balay break; 101799371c9d4SSatish Balay } 10180a93c429eSMatthew G. Knepley } 10181a93c429eSMatthew G. Knepley } 101829566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10183a93c429eSMatthew G. Knepley } 10184a93c429eSMatthew G. Knepley /* Attach nullspace */ 10185a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10186a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10187a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10188a93c429eSMatthew G. Knepley } 10189a93c429eSMatthew G. Knepley if (f < Nf) { 10190a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 101919566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 101926823f3c5SBlaise Bourdin 101939566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 101949566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10195a93c429eSMatthew G. Knepley } 10196a93c429eSMatthew G. Knepley } 101973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10198a93c429eSMatthew G. Knepley } 10199c0f0dcc3SMatthew G. Knepley 10200c0f0dcc3SMatthew G. Knepley /*@ 10201c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10202c0f0dcc3SMatthew G. Knepley 10203a1cb98faSBarry Smith Input Parameters: 10204a1cb98faSBarry Smith + dm - The `DM` 10205a1cb98faSBarry Smith - dummy - unused argument 10206a1cb98faSBarry Smith 10207a1cb98faSBarry Smith Options Database Key: 10208a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10209c0f0dcc3SMatthew G. Knepley 10210c0f0dcc3SMatthew G. Knepley Level: developer 10211c0f0dcc3SMatthew G. Knepley 102121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10213c0f0dcc3SMatthew G. Knepley @*/ 10214d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10215d71ae5a4SJacob Faibussowitsch { 10216b665b14eSToby Isaac PetscLogHandler default_handler; 10217b665b14eSToby Isaac 102182611ad71SToby Isaac PetscFunctionBegin; 102192611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10220b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10221b665b14eSToby Isaac if (default_handler) { 10222c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10223c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10224c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10225c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10226c0f0dcc3SMatthew G. Knepley const char *name; 10227c0f0dcc3SMatthew G. Knepley 102289566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 102299566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 102309566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 102319566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10232b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10233c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10234c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10235c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1023663a3b9bcSJacob 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))); 102372611ad71SToby Isaac } else { 10238b665b14eSToby 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."); 102392611ad71SToby Isaac } 102403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10241c0f0dcc3SMatthew G. Knepley } 10242