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; 14*46139095SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate; 15552f7358SJed Brown 165a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 17552f7358SJed Brown 18e5337592SStefano Zampini /*@ 199318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 209318fe57SMatthew G. Knepley 219318fe57SMatthew G. Knepley Input Parameter: 22a1cb98faSBarry Smith . dm - The `DMPLEX` object 239318fe57SMatthew G. Knepley 249318fe57SMatthew G. Knepley Output Parameter: 259318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 269318fe57SMatthew G. Knepley 279318fe57SMatthew G. Knepley Level: intermediate 289318fe57SMatthew G. Knepley 29a1cb98faSBarry Smith Note: 30a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 31a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 32a1cb98faSBarry Smith 33a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 349318fe57SMatthew G. Knepley @*/ 35d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 36d71ae5a4SJacob Faibussowitsch { 379318fe57SMatthew G. Knepley DMPolytopeType ct; 389318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 399318fe57SMatthew G. Knepley 409318fe57SMatthew G. Knepley PetscFunctionBegin; 419566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 429371c9d4SSatish Balay if (cEnd <= cStart) { 439371c9d4SSatish Balay *simplex = PETSC_FALSE; 449371c9d4SSatish Balay PetscFunctionReturn(0); 459371c9d4SSatish Balay } 469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 479318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 489318fe57SMatthew G. Knepley PetscFunctionReturn(0); 499318fe57SMatthew G. Knepley } 509318fe57SMatthew G. Knepley 519318fe57SMatthew G. Knepley /*@ 52412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 53e5337592SStefano Zampini 54d8d19677SJose E. Roman Input Parameters: 55a1cb98faSBarry Smith + dm - The `DMPLEX` object 56412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 57e5337592SStefano Zampini 58e5337592SStefano Zampini Output Parameters: 59412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 60412e9a14SMatthew G. Knepley - cEnd - The upper bound on "normal"" cells 61e5337592SStefano Zampini 62412e9a14SMatthew G. Knepley Level: developer 63e5337592SStefano Zampini 64a1cb98faSBarry Smith Note: 65a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 66a1cb98faSBarry Smith 67a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 68e5337592SStefano Zampini @*/ 69d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 70d71ae5a4SJacob Faibussowitsch { 71412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 72412e9a14SMatthew G. Knepley PetscInt cS, cE, c; 73e5337592SStefano Zampini 74e5337592SStefano Zampini PetscFunctionBegin; 759566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE)); 76412e9a14SMatthew G. Knepley for (c = cS; c < cE; ++c) { 77412e9a14SMatthew G. Knepley DMPolytopeType cct; 78412e9a14SMatthew G. Knepley 799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &cct)); 80412e9a14SMatthew G. Knepley if ((PetscInt)cct < 0) break; 81412e9a14SMatthew G. Knepley switch (cct) { 82ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 83ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 84ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 85ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 86ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 87d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 88d71ae5a4SJacob Faibussowitsch ct = cct; 89d71ae5a4SJacob Faibussowitsch break; 90d71ae5a4SJacob Faibussowitsch default: 91d71ae5a4SJacob Faibussowitsch break; 92e5337592SStefano Zampini } 93412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) break; 94e5337592SStefano Zampini } 95412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) { 96412e9a14SMatthew G. Knepley DMLabel ctLabel; 97412e9a14SMatthew G. Knepley 989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 999566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE)); 100695799ffSMatthew G. Knepley // Reset label for fast lookup 101695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 102e5337592SStefano Zampini } 103412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 104412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 105e5337592SStefano Zampini PetscFunctionReturn(0); 106e5337592SStefano Zampini } 107e5337592SStefano Zampini 108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 109d71ae5a4SJacob Faibussowitsch { 110412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 111a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 1127e42fee7SMatthew G. Knepley 1137e42fee7SMatthew G. Knepley PetscFunctionBegin; 114e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 1159566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1179566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 1189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1197e42fee7SMatthew G. Knepley if (field >= 0) { 1209566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 1219566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 1227e42fee7SMatthew G. Knepley } else { 1239566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 1249566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 1257e42fee7SMatthew G. Knepley } 1269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 127a99a26bcSAdrian Croucher if (globalvcdof[0]) { 1287e42fee7SMatthew G. Knepley *sStart = vStart; 1297e42fee7SMatthew G. Knepley *sEnd = vEnd; 130f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 1317e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 132a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 1337e42fee7SMatthew G. Knepley *sStart = cStart; 1347e42fee7SMatthew G. Knepley *sEnd = cEnd; 135f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 1367e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 137e630c359SToby Isaac } else { 138e630c359SToby Isaac if (field >= 0) { 139e630c359SToby Isaac const char *fieldname; 140e630c359SToby Isaac 1419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 14263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 143e630c359SToby Isaac } else { 14463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 145e630c359SToby Isaac } 146e630c359SToby Isaac } 1477e42fee7SMatthew G. Knepley PetscFunctionReturn(0); 1487e42fee7SMatthew G. Knepley } 1497e42fee7SMatthew G. Knepley 1506913077dSMatthew G. Knepley /*@ 1516913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 1526913077dSMatthew G. Knepley 1536913077dSMatthew G. Knepley Collective on dm 1546913077dSMatthew G. Knepley 1556913077dSMatthew G. Knepley Input Parameters: 156a1cb98faSBarry Smith + dm - The `DMPLEX` object 1576913077dSMatthew G. Knepley . n - The number of vectors 1586913077dSMatthew G. Knepley . u - The array of local vectors 159a1cb98faSBarry Smith - viewer - The `PetscViewer` 1606913077dSMatthew G. Knepley 1616913077dSMatthew G. Knepley Level: advanced 1626913077dSMatthew G. Knepley 163a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 1646913077dSMatthew G. Knepley @*/ 165d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 166d71ae5a4SJacob Faibussowitsch { 1676913077dSMatthew G. Knepley PetscDS ds; 1686913077dSMatthew G. Knepley PetscDraw draw = NULL; 1696913077dSMatthew G. Knepley PetscDrawLG lg; 1706913077dSMatthew G. Knepley Vec coordinates; 1716913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 1726913077dSMatthew G. Knepley PetscReal *vals; 1736913077dSMatthew G. Knepley PetscInt *Nc; 1746913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 1756913077dSMatthew G. Knepley char **names; 1766913077dSMatthew G. Knepley 1776913077dSMatthew G. Knepley PetscFunctionBegin; 1789566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 1799566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 1809566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 1819566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 1826913077dSMatthew G. Knepley 1839566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 1846913077dSMatthew G. Knepley if (!draw) PetscFunctionReturn(0); 1859566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 1866913077dSMatthew G. Knepley 1879566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 1886913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 1896913077dSMatthew G. Knepley const char *vname; 1906913077dSMatthew G. Knepley 1919566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 1926913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1936913077dSMatthew G. Knepley PetscObject disc; 1946913077dSMatthew G. Knepley const char *fname; 1956913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 1966913077dSMatthew G. Knepley 1979566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 1986913077dSMatthew G. Knepley /* TODO Create names for components */ 1996913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 2009566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 2019566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(tmpname, vname)); 2029566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN)); 2039566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN)); 2049566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 2056913077dSMatthew G. Knepley } 2066913077dSMatthew G. Knepley } 2076913077dSMatthew G. Knepley } 2089566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 2096913077dSMatthew G. Knepley /* Just add P_1 support for now */ 2109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2129566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 2139566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 2146913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 2156913077dSMatthew G. Knepley PetscScalar *x, *svals; 2166913077dSMatthew G. Knepley 2179566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 2186913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 2199566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 2206913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 2216913077dSMatthew G. Knepley } 2229566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 2236913077dSMatthew G. Knepley } 2249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 2259566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 2269566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 2279566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 2286913077dSMatthew G. Knepley 2299566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 2309566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 2316913077dSMatthew G. Knepley PetscFunctionReturn(0); 2326913077dSMatthew G. Knepley } 2336913077dSMatthew G. Knepley 234d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 235d71ae5a4SJacob Faibussowitsch { 2366913077dSMatthew G. Knepley DM dm; 2376913077dSMatthew G. Knepley 2386913077dSMatthew G. Knepley PetscFunctionBegin; 2399566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 2409566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 2416913077dSMatthew G. Knepley PetscFunctionReturn(0); 2426913077dSMatthew G. Knepley } 2436913077dSMatthew G. Knepley 244d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 245d71ae5a4SJacob Faibussowitsch { 246e412dcbdSMatthew G. Knepley DM dm; 247d1df6f1dSMatthew G. Knepley PetscSection s; 248e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 249e412dcbdSMatthew G. Knepley DM cdm; 250e412dcbdSMatthew G. Knepley PetscSection coordSection; 251e412dcbdSMatthew G. Knepley Vec coordinates; 252e412dcbdSMatthew G. Knepley const PetscScalar *coords, *array; 253e412dcbdSMatthew G. Knepley PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 254339e3443SMatthew G. Knepley PetscReal vbound[2], time; 2556913077dSMatthew G. Knepley PetscBool flg; 256d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 257e412dcbdSMatthew G. Knepley const char *name; 258339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 259e412dcbdSMatthew G. Knepley 260e412dcbdSMatthew G. Knepley PetscFunctionBegin; 2619566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2629566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 2639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 2649566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 2659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 2669566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 2679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 2689566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 2699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2719566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 272e412dcbdSMatthew G. Knepley 2739566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 2749566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 275e412dcbdSMatthew G. Knepley 2769566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 2779566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 278e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 2799371c9d4SSatish Balay bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); 2809371c9d4SSatish Balay bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 2819371c9d4SSatish Balay bound[1] = PetscMin(bound[1], PetscRealPart(coords[c + 1])); 2829371c9d4SSatish Balay bound[3] = PetscMax(bound[3], PetscRealPart(coords[c + 1])); 283e412dcbdSMatthew G. Knepley } 2849566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 2859566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 286e412dcbdSMatthew G. Knepley 287d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 288d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 289d1df6f1dSMatthew G. Knepley DM fdm = dm; 290d1df6f1dSMatthew G. Knepley Vec fv = v; 291d1df6f1dSMatthew G. Knepley IS fis; 292d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 293d1df6f1dSMatthew G. Knepley const char *fname; 294d1df6f1dSMatthew G. Knepley 2959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 2969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 297d1df6f1dSMatthew G. Knepley 2989566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 299ad540459SPierre Jolivet else prefix[0] = '\0'; 300d1df6f1dSMatthew G. Knepley if (Nf > 1) { 3019566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 3029566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 3039566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 3049566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 305d1df6f1dSMatthew G. Knepley } 306d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 307d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 308d1df6f1dSMatthew G. Knepley 3099566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 31063a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 31163a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 3129566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 313d1df6f1dSMatthew G. Knepley 314d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 3159566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 316339e3443SMatthew G. Knepley if (!flg) { 3179566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 3189566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 319d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 320339e3443SMatthew G. Knepley } 3219566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 3229566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 3239566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3])); 324e412dcbdSMatthew G. Knepley 3259566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 326e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 32799a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 328e56f9228SJed Brown PetscInt numCoords, color[4] = {-1, -1, -1, -1}; 329e412dcbdSMatthew G. Knepley 3309566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 331339e3443SMatthew G. Knepley if (a) { 332d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 333339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 334339e3443SMatthew G. Knepley } else { 335339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 336339e3443SMatthew G. Knepley PetscInt numVals, va; 337339e3443SMatthew G. Knepley 3389566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 33963a3b9bcSJacob 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); 340d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 341d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 342d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 343d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 344339e3443SMatthew G. Knepley break; 345d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 346d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 347d1df6f1dSMatthew 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]); 348d1df6f1dSMatthew G. Knepley break; 349d71ae5a4SJacob Faibussowitsch default: 350d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 351339e3443SMatthew G. Knepley } 3529566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 353339e3443SMatthew G. Knepley } 3549566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 355e412dcbdSMatthew G. Knepley switch (numCoords) { 356e412dcbdSMatthew G. Knepley case 6: 3579edc3542SMatthew Knepley case 12: /* Localized triangle */ 3589566063dSJacob 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])); 359e412dcbdSMatthew G. Knepley break; 360e412dcbdSMatthew G. Knepley case 8: 3619edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 3629566063dSJacob 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])); 3639566063dSJacob 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])); 364e412dcbdSMatthew G. Knepley break; 365d71ae5a4SJacob Faibussowitsch default: 366d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 367e412dcbdSMatthew G. Knepley } 3689566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 369e412dcbdSMatthew G. Knepley } 3709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 3719566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 3729566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 3739566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 374d1df6f1dSMatthew G. Knepley } 375d1df6f1dSMatthew G. Knepley if (Nf > 1) { 3769566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 3779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 3789566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 379d1df6f1dSMatthew G. Knepley } 380d1df6f1dSMatthew G. Knepley } 381e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 382e412dcbdSMatthew G. Knepley } 383e412dcbdSMatthew G. Knepley 384d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 385d71ae5a4SJacob Faibussowitsch { 3866913077dSMatthew G. Knepley DM dm; 3876913077dSMatthew G. Knepley PetscDraw draw; 3886913077dSMatthew G. Knepley PetscInt dim; 3896913077dSMatthew G. Knepley PetscBool isnull; 3906913077dSMatthew G. Knepley 3916913077dSMatthew G. Knepley PetscFunctionBegin; 3929566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3939566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 3946913077dSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 3956913077dSMatthew G. Knepley 3969566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3986913077dSMatthew G. Knepley switch (dim) { 399d71ae5a4SJacob Faibussowitsch case 1: 400d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 401d71ae5a4SJacob Faibussowitsch break; 402d71ae5a4SJacob Faibussowitsch case 2: 403d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 404d71ae5a4SJacob Faibussowitsch break; 405d71ae5a4SJacob Faibussowitsch default: 406d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 4076913077dSMatthew G. Knepley } 4086913077dSMatthew G. Knepley PetscFunctionReturn(0); 4096913077dSMatthew G. Knepley } 4106913077dSMatthew G. Knepley 411d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 412d71ae5a4SJacob Faibussowitsch { 413684b87d9SLisandro Dalcin DM dm; 414684b87d9SLisandro Dalcin Vec locv; 415684b87d9SLisandro Dalcin const char *name; 416684b87d9SLisandro Dalcin PetscSection section; 417684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 418e630c359SToby Isaac PetscInt numFields; 419684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 420684b87d9SLisandro Dalcin 421684b87d9SLisandro Dalcin PetscFunctionBegin; 4229566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4239566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 4249566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 4259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 4269566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4279566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 4289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 429e630c359SToby Isaac if (!numFields) { 4309566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 4319566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 432e630c359SToby Isaac } else { 433e630c359SToby Isaac PetscInt f; 434e630c359SToby Isaac 435e630c359SToby Isaac for (f = 0; f < numFields; f++) { 4369566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 437e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 4389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 4399566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 440e630c359SToby Isaac } 4419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 442e630c359SToby Isaac } 443684b87d9SLisandro Dalcin PetscFunctionReturn(0); 444684b87d9SLisandro Dalcin } 445684b87d9SLisandro Dalcin 446d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 447d71ae5a4SJacob Faibussowitsch { 448552f7358SJed Brown DM dm; 4495f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 450552f7358SJed Brown 451552f7358SJed Brown PetscFunctionBegin; 4529566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 45328b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 4549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 4559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 4569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 4579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 4585f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 4595f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 460684b87d9SLisandro Dalcin PetscInt i, numFields; 461684b87d9SLisandro Dalcin PetscObject fe; 462ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 463684b87d9SLisandro Dalcin Vec locv = v; 464684b87d9SLisandro Dalcin const char *name; 465684b87d9SLisandro Dalcin PetscInt step; 466684b87d9SLisandro Dalcin PetscReal time; 467ef31f671SMatthew G. Knepley 4689566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 469684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 4709566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 4719371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 4729371c9d4SSatish Balay fem = PETSC_TRUE; 4739371c9d4SSatish Balay break; 4749371c9d4SSatish Balay } 475ef31f671SMatthew G. Knepley } 476684b87d9SLisandro Dalcin if (fem) { 477798534f6SMatthew G. Knepley PetscObject isZero; 478798534f6SMatthew G. Knepley 4799566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 4809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 4819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 4829566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 4839566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 4849566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4859566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 4869566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 487ef31f671SMatthew G. Knepley } 488552f7358SJed Brown if (isvtk) { 4899566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 490b136c2c9SMatthew G. Knepley } else if (ishdf5) { 491b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 4929566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 493b136c2c9SMatthew G. Knepley #else 494b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 495b136c2c9SMatthew G. Knepley #endif 496f13a32a3SMatthew G. Knepley } else if (isdraw) { 4979566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 498684b87d9SLisandro Dalcin } else if (isglvis) { 4999566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 5009566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 5019566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 5025f34f2dcSJed Brown } else if (iscgns) { 5035f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 5045f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 5055f34f2dcSJed Brown #else 5065f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 5075f34f2dcSJed Brown #endif 508684b87d9SLisandro Dalcin } 509798534f6SMatthew G. Knepley if (fem) { 5109566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 5119566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 512798534f6SMatthew G. Knepley } 513552f7358SJed Brown } else { 514684b87d9SLisandro Dalcin PetscBool isseq; 515684b87d9SLisandro Dalcin 5169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 5179566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5189566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 519552f7358SJed Brown } 520552f7358SJed Brown PetscFunctionReturn(0); 521552f7358SJed Brown } 522552f7358SJed Brown 523d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 524d71ae5a4SJacob Faibussowitsch { 525552f7358SJed Brown DM dm; 5265f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 527552f7358SJed Brown 528552f7358SJed Brown PetscFunctionBegin; 5299566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 53028b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5355f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 5375f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 538552f7358SJed Brown Vec locv; 539798534f6SMatthew G. Knepley PetscObject isZero; 540552f7358SJed Brown const char *name; 541552f7358SJed Brown 5429566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5449566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5459566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 5469566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 5479566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 5489566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 5499566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 5509566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 5519566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 552b136c2c9SMatthew G. Knepley } else if (ishdf5) { 553b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5549566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 555b136c2c9SMatthew G. Knepley #else 556b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 557b136c2c9SMatthew G. Knepley #endif 5586823f3c5SBlaise Bourdin } else if (isexodusii) { 5596823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 5609566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 5616823f3c5SBlaise Bourdin #else 5626823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 5636823f3c5SBlaise Bourdin #endif 564552f7358SJed Brown } else { 565684b87d9SLisandro Dalcin PetscBool isseq; 566684b87d9SLisandro Dalcin 5679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 5689566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5699566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 570552f7358SJed Brown } 571552f7358SJed Brown PetscFunctionReturn(0); 572552f7358SJed Brown } 573552f7358SJed Brown 574d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 575d71ae5a4SJacob Faibussowitsch { 576d930f514SMatthew G. Knepley DM dm; 577d930f514SMatthew G. Knepley MPI_Comm comm; 578d930f514SMatthew G. Knepley PetscViewerFormat format; 579d930f514SMatthew G. Knepley Vec v; 580d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 581d930f514SMatthew G. Knepley 582d930f514SMatthew G. Knepley PetscFunctionBegin; 5839566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 5849566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 58528b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5869566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 5879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 589d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 590a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 591a8ad634aSStefano Zampini /* this need a better fix */ 592a8ad634aSStefano Zampini if (dm->useNatural) { 593a8ad634aSStefano Zampini if (dm->sfNatural) { 594d930f514SMatthew G. Knepley const char *vecname; 595d930f514SMatthew G. Knepley PetscInt n, nroots; 596d930f514SMatthew G. Knepley 5979566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 5989566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 599d930f514SMatthew G. Knepley if (n == nroots) { 6009566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 6019566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 6029566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 6039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 6049566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 605d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 606d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 607a8ad634aSStefano Zampini } else v = originalv; 608a8ad634aSStefano Zampini } else v = originalv; 609a8ad634aSStefano Zampini 610d930f514SMatthew G. Knepley if (ishdf5) { 611d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6129566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 613d930f514SMatthew G. Knepley #else 614d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 615d930f514SMatthew G. Knepley #endif 616d930f514SMatthew G. Knepley } else if (isvtk) { 617d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 618d930f514SMatthew G. Knepley } else { 619d930f514SMatthew G. Knepley PetscBool isseq; 620d930f514SMatthew G. Knepley 6219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6229566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6239566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 624d930f514SMatthew G. Knepley } 6259566063dSJacob Faibussowitsch if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v)); 626d930f514SMatthew G. Knepley PetscFunctionReturn(0); 627d930f514SMatthew G. Knepley } 628d930f514SMatthew G. Knepley 629d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 630d71ae5a4SJacob Faibussowitsch { 6312c40f234SMatthew G. Knepley DM dm; 6322c40f234SMatthew G. Knepley PetscBool ishdf5; 6332c40f234SMatthew G. Knepley 6342c40f234SMatthew G. Knepley PetscFunctionBegin; 6359566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63628b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6382c40f234SMatthew G. Knepley if (ishdf5) { 6392c40f234SMatthew G. Knepley DM dmBC; 6402c40f234SMatthew G. Knepley Vec gv; 6412c40f234SMatthew G. Knepley const char *name; 6422c40f234SMatthew G. Knepley 6439566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 6449566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 6459566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 6479566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 6489566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 6499566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 6509566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 6511baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 6522c40f234SMatthew G. Knepley PetscFunctionReturn(0); 6532c40f234SMatthew G. Knepley } 6542c40f234SMatthew G. Knepley 655d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 656d71ae5a4SJacob Faibussowitsch { 6572c40f234SMatthew G. Knepley DM dm; 6586823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 6592c40f234SMatthew G. Knepley 6602c40f234SMatthew G. Knepley PetscFunctionBegin; 6619566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 66228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6652c40f234SMatthew G. Knepley if (ishdf5) { 666878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6679566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 668b136c2c9SMatthew G. Knepley #else 669b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 670878b459fSMatthew G. Knepley #endif 6716823f3c5SBlaise Bourdin } else if (isexodusii) { 6726823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6739566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 6746823f3c5SBlaise Bourdin #else 6756823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6766823f3c5SBlaise Bourdin #endif 6771baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 678552f7358SJed Brown PetscFunctionReturn(0); 679552f7358SJed Brown } 680552f7358SJed Brown 681d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 682d71ae5a4SJacob Faibussowitsch { 683d930f514SMatthew G. Knepley DM dm; 684d930f514SMatthew G. Knepley PetscViewerFormat format; 685d930f514SMatthew G. Knepley PetscBool ishdf5; 686d930f514SMatthew G. Knepley 687d930f514SMatthew G. Knepley PetscFunctionBegin; 6889566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 68928b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6909566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 692d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 693a8ad634aSStefano Zampini if (dm->useNatural) { 694d930f514SMatthew G. Knepley if (dm->sfNatural) { 695d930f514SMatthew G. Knepley if (ishdf5) { 696d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 697d930f514SMatthew G. Knepley Vec v; 698d930f514SMatthew G. Knepley const char *vecname; 699d930f514SMatthew G. Knepley 7009566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 7019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7029566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 7039566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 7049566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 7059566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 7069566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dm, &v)); 707d930f514SMatthew G. Knepley #else 708d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 709d930f514SMatthew G. Knepley #endif 710d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 711d930f514SMatthew G. Knepley } 7121baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 713d930f514SMatthew G. Knepley } 714d930f514SMatthew G. Knepley PetscFunctionReturn(0); 715d930f514SMatthew G. Knepley } 716d930f514SMatthew G. Knepley 717d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 718d71ae5a4SJacob Faibussowitsch { 719731e8ddeSMatthew G. Knepley PetscSection coordSection; 720731e8ddeSMatthew G. Knepley Vec coordinates; 721ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 722731e8ddeSMatthew G. Knepley const char *name[4]; 723731e8ddeSMatthew G. Knepley const PetscScalar *a; 724731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 725731e8ddeSMatthew G. Knepley 726731e8ddeSMatthew G. Knepley PetscFunctionBegin; 7279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 7289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 7299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 7319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 7329566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 7339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 7349566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 735731e8ddeSMatthew G. Knepley name[0] = "vertex"; 736731e8ddeSMatthew G. Knepley name[1] = "edge"; 737731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 738731e8ddeSMatthew G. Knepley name[dim] = "cell"; 739731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 740731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 741ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 742731e8ddeSMatthew G. Knepley 7439566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 74463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 7459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 747731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 748731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 749731e8ddeSMatthew G. Knepley 750731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 7519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 752731e8ddeSMatthew G. Knepley if (!dof) continue; 7539566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 7549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 75563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 756731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 7579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 758731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 7599566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 7609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 761731e8ddeSMatthew G. Knepley } 7629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 763731e8ddeSMatthew G. Knepley } 7649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 765731e8ddeSMatthew G. Knepley } 7669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 768731e8ddeSMatthew G. Knepley } 7699566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 770731e8ddeSMatthew G. Knepley PetscFunctionReturn(0); 771731e8ddeSMatthew G. Knepley } 772731e8ddeSMatthew G. Knepley 7739371c9d4SSatish Balay typedef enum { 7749371c9d4SSatish Balay CS_CARTESIAN, 7759371c9d4SSatish Balay CS_POLAR, 7769371c9d4SSatish Balay CS_CYLINDRICAL, 7779371c9d4SSatish Balay CS_SPHERICAL 7789371c9d4SSatish Balay } CoordSystem; 77919ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 78019ad8254SMatthew G. Knepley 781d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 782d71ae5a4SJacob Faibussowitsch { 78319ad8254SMatthew G. Knepley PetscInt i; 78419ad8254SMatthew G. Knepley 78519ad8254SMatthew G. Knepley PetscFunctionBegin; 78619ad8254SMatthew G. Knepley if (dim > 3) { 7879566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 78819ad8254SMatthew G. Knepley } else { 789bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 79019ad8254SMatthew G. Knepley 79119ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 79219ad8254SMatthew G. Knepley switch (cs) { 7939371c9d4SSatish Balay case CS_CARTESIAN: 7949371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 7959371c9d4SSatish Balay break; 79619ad8254SMatthew G. Knepley case CS_POLAR: 79763a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 79819ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 79919ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 80019ad8254SMatthew G. Knepley break; 80119ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 80263a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 80319ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 80419ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 80519ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 80619ad8254SMatthew G. Knepley break; 80719ad8254SMatthew G. Knepley case CS_SPHERICAL: 80863a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 80919ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 81019ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 81119ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 81219ad8254SMatthew G. Knepley break; 81319ad8254SMatthew G. Knepley } 8149566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 81519ad8254SMatthew G. Knepley } 81619ad8254SMatthew G. Knepley PetscFunctionReturn(0); 81719ad8254SMatthew G. Knepley } 81819ad8254SMatthew G. Knepley 819d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 820d71ae5a4SJacob Faibussowitsch { 821552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8226858538eSMatthew G. Knepley DM cdm, cdmCell; 8236858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 8246858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 825552f7358SJed Brown PetscViewerFormat format; 826552f7358SJed Brown 827552f7358SJed Brown PetscFunctionBegin; 8289566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 829552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 830552f7358SJed Brown const char *name; 831f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 8329318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 833552f7358SJed Brown PetscMPIInt rank, size; 834552f7358SJed Brown 8359f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 8369f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8379f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8389f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 8399f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 8409f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 8419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 8439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 8449566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8459566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 8469566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8479566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 84863a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 84963a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 85063a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 85163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 8529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 85363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 854552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 855552f7358SJed Brown PetscInt dof, off, s; 856552f7358SJed Brown 8579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 85948a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 860552f7358SJed Brown } 8619566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 86263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 86363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 864552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 865552f7358SJed Brown PetscInt dof, off, c; 866552f7358SJed Brown 8679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 8689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 86948a46eb9SPierre 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])); 870552f7358SJed Brown } 8719566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8733d2e540fSStefano Zampini if (coordSection && coordinates) { 87419ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 8756858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 8766858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 87719ad8254SMatthew G. Knepley PetscMPIInt rank; 87819ad8254SMatthew G. Knepley const char *name; 87919ad8254SMatthew G. Knepley 8809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 8819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 8829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 88363a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 8849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 8856858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 8866858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 8876858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 8886858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 8899566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 89063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 89163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 8929566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 89319ad8254SMatthew G. Knepley 8949566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 8956858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 8969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 8979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 89819ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 89919ad8254SMatthew G. Knepley PetscInt dof, off; 90019ad8254SMatthew G. Knepley 9016858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 9029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 9039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 9046858538eSMatthew G. Knepley if (dof) { 90563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 9069566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 9079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 90819ad8254SMatthew G. Knepley } 9096858538eSMatthew G. Knepley } 9106858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 9116858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 9126858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 9136858538eSMatthew G. Knepley if (dof) { 9146858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 9156858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 9166858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 9176858538eSMatthew G. Knepley } 9186858538eSMatthew G. Knepley } 9196858538eSMatthew G. Knepley } 9209566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 9229566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 9236858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 9243d2e540fSStefano Zampini } 9259566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 9269566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 9279318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 9289318fe57SMatthew G. Knepley DMLabel label; 9299318fe57SMatthew G. Knepley PetscBool isdepth; 9309318fe57SMatthew G. Knepley const char *name; 9319318fe57SMatthew G. Knepley 9329566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 9339566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 9349318fe57SMatthew G. Knepley if (isdepth) continue; 9359566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 9369566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 9379318fe57SMatthew G. Knepley } 938552f7358SJed Brown if (size > 1) { 939552f7358SJed Brown PetscSF sf; 940552f7358SJed Brown 9419566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9429566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 943552f7358SJed Brown } 9444e2e9504SJed Brown if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer)); 9459566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 946552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 9470588280cSMatthew G. Knepley const char *name, *color; 9480588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 9490588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 950fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 951552f7358SJed Brown PetscReal scale = 2.0; 95278081901SStefano Zampini PetscReal tikzscale = 1.0; 953b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 9540588280cSMatthew G. Knepley double tcoords[3]; 955552f7358SJed Brown PetscScalar *coords; 956b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 957552f7358SJed Brown PetscMPIInt rank, size; 9580588280cSMatthew G. Knepley char **names, **colors, **lcolors; 959b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 960fe1cc32dSStefano Zampini PetscBT wp = NULL; 961fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 962552f7358SJed Brown 9639f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 9649f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9659f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9669f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 9679f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 9689f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 9699566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9719566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 9720588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 9730588280cSMatthew G. Knepley numColors = 10; 9740588280cSMatthew G. Knepley numLColors = 10; 9759566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 9769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 9779566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 9789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 979b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 980b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 981b7f6ffafSMatthew G. Knepley n = 4; 9829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 9831dca8a05SBarry 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); 9849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 9851dca8a05SBarry 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); 9869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 9870588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 9889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 9890588280cSMatthew G. Knepley if (!useColors) { 9900588280cSMatthew G. Knepley numColors = 3; 9919566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 9920588280cSMatthew G. Knepley } 9939566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 9940588280cSMatthew G. Knepley if (!useColors) { 9950588280cSMatthew G. Knepley numLColors = 4; 9969566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 9970588280cSMatthew G. Knepley } 9989566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 999b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 10009566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 10011dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1002202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 10039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1004fe1cc32dSStefano Zampini 1005fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 10069566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 10079566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 10089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 10099566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1010fe1cc32dSStefano Zampini if (lflg) { 1011fe1cc32dSStefano Zampini DMLabel lbl; 1012fe1cc32dSStefano Zampini 10139566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1014fe1cc32dSStefano Zampini if (lbl) { 1015fe1cc32dSStefano Zampini PetscInt val, defval; 1016fe1cc32dSStefano Zampini 10179566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 10189566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1019fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1020fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1021fe1cc32dSStefano Zampini PetscInt closureSize; 1022fe1cc32dSStefano Zampini 10239566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1024fe1cc32dSStefano Zampini if (val == defval) continue; 1025fe1cc32dSStefano Zampini 10269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 102748a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 10289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1029fe1cc32dSStefano Zampini } 1030fe1cc32dSStefano Zampini } 1031fe1cc32dSStefano Zampini } 1032fe1cc32dSStefano Zampini 10339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 10349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 10359566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 10369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 10370588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1038552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1039552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1040552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 10415f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 10420588280cSMatthew G. Knepley if (size > 1) { 10439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1044770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 104563a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 104663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1047770b213bSMatthew G Knepley } 10489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 10490588280cSMatthew G. Knepley } 1050b7f6ffafSMatthew G. Knepley if (drawHasse) { 1051b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1052b7f6ffafSMatthew G. Knepley 105363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 105463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 105563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 10569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 105763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 105863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 10599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 106063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 106163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 106263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 106363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 10649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1065b7f6ffafSMatthew G. Knepley } 10669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1067fe1cc32dSStefano Zampini 1068552f7358SJed Brown /* Plot vertices */ 10699566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1071552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1072552f7358SJed Brown PetscInt off, dof, d; 10730588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1074552f7358SJed Brown 1075fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 10769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 10779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 10789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 107963a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 10800588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10810588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1082c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 10830588280cSMatthew G. Knepley } 10840588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 10859371c9d4SSatish Balay if (dim == 3) { 10869371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 10879371c9d4SSatish Balay tcoords[1] = tcoords[2]; 10889371c9d4SSatish Balay tcoords[2] = -tmp; 10899371c9d4SSatish Balay } 1090552f7358SJed Brown for (d = 0; d < dof; ++d) { 10919566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1093552f7358SJed Brown } 1094b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1095b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 10960588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10970588280cSMatthew G. Knepley PetscInt val; 10989566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 10999371c9d4SSatish Balay if (val >= 0) { 11009371c9d4SSatish Balay color = lcolors[l % numLColors]; 11019371c9d4SSatish Balay isLabeled = PETSC_TRUE; 11029371c9d4SSatish Balay break; 11039371c9d4SSatish Balay } 11040588280cSMatthew G. Knepley } 1105b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 110663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1107b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 110863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 11091baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1110552f7358SJed Brown } 11119566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 11129566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1113b7f6ffafSMatthew G. Knepley /* Plot edges */ 1114b7f6ffafSMatthew G. Knepley if (plotEdges) { 11159566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 11169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1117b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1118b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1119b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1120b7f6ffafSMatthew G. Knepley 1121b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 11229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 112363a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 11249566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 11259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 11269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 11279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 11289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1129b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1130b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1131b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1132b7f6ffafSMatthew G. Knepley } 1133b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 11349371c9d4SSatish Balay if (dim == 3) { 11359371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11369371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11379371c9d4SSatish Balay tcoords[2] = -tmp; 11389371c9d4SSatish Balay } 1139b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11409566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1142b7f6ffafSMatthew G. Knepley } 1143b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1144b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1145b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1146b7f6ffafSMatthew G. Knepley PetscInt val; 11479566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 11489371c9d4SSatish Balay if (val >= 0) { 11499371c9d4SSatish Balay color = lcolors[l % numLColors]; 11509371c9d4SSatish Balay break; 11519371c9d4SSatish Balay } 1152b7f6ffafSMatthew G. Knepley } 115363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1154b7f6ffafSMatthew G. Knepley } 11559566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 11569566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 11579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1158b7f6ffafSMatthew G. Knepley } 1159846a3e8bSMatthew G. Knepley /* Plot cells */ 1160b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1161846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1162846a3e8bSMatthew G. Knepley const PetscInt *cone; 1163846a3e8bSMatthew G. Knepley 1164fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1165846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1166846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1167846a3e8bSMatthew G. Knepley PetscInt val; 11689566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 11699371c9d4SSatish Balay if (val >= 0) { 11709371c9d4SSatish Balay color = lcolors[l % numLColors]; 11719371c9d4SSatish Balay break; 11729371c9d4SSatish Balay } 1173846a3e8bSMatthew G. Knepley } 11749566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 117563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1176846a3e8bSMatthew G. Knepley } 1177846a3e8bSMatthew G. Knepley } else { 1178b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1179846a3e8bSMatthew G. Knepley 1180b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1181b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1182fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 11839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 11849371c9d4SSatish Balay if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1185b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1186b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1187b7f6ffafSMatthew G. Knepley 11889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 11899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1190b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1191b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1192b7f6ffafSMatthew G. Knepley 11939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 119463a3b9bcSJacob 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)); 1195b7f6ffafSMatthew G. Knepley } 1196b7f6ffafSMatthew G. Knepley } else { 1197b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1198b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1199b7f6ffafSMatthew G. Knepley 12009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1201846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1202846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1203846a3e8bSMatthew G. Knepley 1204b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1205846a3e8bSMatthew G. Knepley } 12069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1207b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1208b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1209b7f6ffafSMatthew G. Knepley 1210b7f6ffafSMatthew G. Knepley if (v > 0) { 1211b7f6ffafSMatthew G. Knepley if (plotEdges) { 1212b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1213b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1214b7f6ffafSMatthew G. Knepley 12159371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 12169371c9d4SSatish Balay endpoints[1] = vertex; 12179566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 121863a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 121963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 12209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 12211baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1222b7f6ffafSMatthew G. Knepley } 122363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1224b7f6ffafSMatthew G. Knepley } 12259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 12269566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1227846a3e8bSMatthew G. Knepley } 1228846a3e8bSMatthew G. Knepley } 1229b7f6ffafSMatthew G. Knepley } 1230846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1231846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1232846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1233c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1234c713ec31SMatthew G. Knepley const PetscScalar *array; 1235c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1236c713ec31SMatthew G. Knepley PetscBool isDG; 1237846a3e8bSMatthew G. Knepley 1238fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1239c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1240c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1241c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 12429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1243c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1244c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1245c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1246846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1247846a3e8bSMatthew G. Knepley } 1248846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12499371c9d4SSatish Balay if (cdim == 3) { 12509371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12519371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12529371c9d4SSatish Balay tcoords[2] = -tmp; 12539371c9d4SSatish Balay } 1254ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1255846a3e8bSMatthew G. Knepley } 1256ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1257c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1258c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 12599566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1261846a3e8bSMatthew G. Knepley } 1262b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1263b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1264846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1265846a3e8bSMatthew G. Knepley PetscInt val; 12669566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 12679371c9d4SSatish Balay if (val >= 0) { 12689371c9d4SSatish Balay color = lcolors[l % numLColors]; 12699371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12709371c9d4SSatish Balay break; 12719371c9d4SSatish Balay } 1272846a3e8bSMatthew G. Knepley } 1273b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 127463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1275b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 127663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 12771baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1278846a3e8bSMatthew G. Knepley } 1279b7f6ffafSMatthew G. Knepley if (drawHasse) { 1280b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 12819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 12829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 12839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 12859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1286552f7358SJed Brown 1287b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 12889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 12899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 12909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 12929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1293b7f6ffafSMatthew G. Knepley 1294b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 12959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 12969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 12979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 12999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1300b7f6ffafSMatthew G. Knepley 1301b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1302b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1303b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1304b7f6ffafSMatthew G. Knepley 13059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 13069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 130748a46eb9SPierre 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)); 13080588280cSMatthew G. Knepley } 13090588280cSMatthew G. Knepley } 13109566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 13119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 13129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 131363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 13149566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 13159566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 13169566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 13179566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 13189566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 13190f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 13200f7d6e4aSStefano Zampini Vec cown, acown; 13210f7d6e4aSStefano Zampini VecScatter sct; 13220f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 13230f7d6e4aSStefano Zampini IS gid, acis; 13240f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 13250f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 13260f7d6e4aSStefano Zampini PetscScalar *array, nid; 13270f7d6e4aSStefano Zampini const PetscInt *idxs; 13280f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 13290f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 13300f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 13310f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 13320f7d6e4aSStefano Zampini 13339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 13349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1335b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 13369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 13370f7d6e4aSStefano Zampini #endif 13380f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 13399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 13409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 13410f7d6e4aSStefano Zampini d1 = 0; 13429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 13430f7d6e4aSStefano Zampini nid = d2; 13449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 13459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 13469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 13470f7d6e4aSStefano Zampini } else nid = 0.0; 13480f7d6e4aSStefano Zampini 13490f7d6e4aSStefano Zampini /* Get connectivity */ 13509566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 13519566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 13520f7d6e4aSStefano Zampini 13530f7d6e4aSStefano Zampini /* filter overlapped local cells */ 13549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 13559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 13569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 13579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 13580f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 13590f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 13600f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 13610f7d6e4aSStefano Zampini } 13629566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 136363a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 13649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 13660f7d6e4aSStefano Zampini 13670f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 13689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 13699566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 13709566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 13719566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 13720f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 13739566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 13749566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 13759566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 13769566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 13779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 13789566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 13799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 13800f7d6e4aSStefano Zampini 13810f7d6e4aSStefano Zampini /* compute edgeCut */ 13820f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 13839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 13849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 13859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 13869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13879566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 13880f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 13890f7d6e4aSStefano Zampini PetscInt totl; 13900f7d6e4aSStefano Zampini 13910f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 13929566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 13930f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 13940f7d6e4aSStefano Zampini if (work[i] < 0) { 13950f7d6e4aSStefano Zampini ect += 1; 13960f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 13970f7d6e4aSStefano Zampini } 13980f7d6e4aSStefano Zampini } 13990f7d6e4aSStefano Zampini } 14009566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 14019566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 14020f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 14030f7d6e4aSStefano Zampini lm[1] = -numVertices; 14041c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 140563a3b9bcSJacob 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])); 14060f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 14070f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 14080f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 14091c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 141063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1411b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 141263a3b9bcSJacob 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.)); 14130f7d6e4aSStefano Zampini #else 141463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 14150f7d6e4aSStefano Zampini #endif 14169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 14179566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 14189566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 14199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1420552f7358SJed Brown } else { 1421412e9a14SMatthew G. Knepley const char *name; 1422d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1423412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1424d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1425ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 14269318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1427412e9a14SMatthew G. Knepley MPI_Comm comm; 1428412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1429552f7358SJed Brown 14309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 14329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 14339566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 14349566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14359566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 143663a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 143763a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 143863a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 14399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 14401c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 14419566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd)); 1442d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 14439566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 14449566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1445412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1446412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1447412e9a14SMatthew G. Knepley 14489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 14499566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1450412e9a14SMatthew G. Knepley ict = ct0; 14519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1452412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1453412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1454412e9a14SMatthew G. Knepley DMPolytopeType ct; 1455412e9a14SMatthew G. Knepley 14569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1457412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1458412e9a14SMatthew G. Knepley else ++Nc[1]; 1459412e9a14SMatthew G. Knepley } 1460ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 14619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 14629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 14639566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 146463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1465834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1466dd400576SPatrick Sanan if (rank == 0) { 146763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 146863a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 146963a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1470834065abSMatthew G. Knepley } 1471cbb7f117SMark Adams } 1472ca7bf7eeSMatthew G. Knepley } else { 1473ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1474ca7bf7eeSMatthew G. Knepley 14759371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 14769371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 14779566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 14789371c9d4SSatish Balay locMinMax[0] = Nc[1]; 14799371c9d4SSatish Balay locMinMax[1] = Nc[1]; 14809566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1481ca7bf7eeSMatthew G. Knepley if (d == depth) { 14829371c9d4SSatish Balay locMinMax[0] = gcNum; 14839371c9d4SSatish Balay locMinMax[1] = gcNum; 14849566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1485ca7bf7eeSMatthew G. Knepley } 148663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 14879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 14889566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 14899566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1490ca7bf7eeSMatthew G. Knepley } 14919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1492552f7358SJed Brown } 14939566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 14949318fe57SMatthew G. Knepley { 14959318fe57SMatthew G. Knepley const PetscReal *maxCell; 14969318fe57SMatthew G. Knepley const PetscReal *L; 14976858538eSMatthew G. Knepley PetscBool localized; 14989318fe57SMatthew G. Knepley 14994fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 15009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 15016858538eSMatthew G. Knepley if (L || localized) { 15026858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 15039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 15046858538eSMatthew G. Knepley if (L) { 15056858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 15069318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 15076858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 15086858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 15099318fe57SMatthew G. Knepley } 15106858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 15116858538eSMatthew G. Knepley } 15126858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 15139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 15149318fe57SMatthew G. Knepley } 15159318fe57SMatthew G. Knepley } 15169566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 15179566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1518a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1519a57dd577SMatthew G Knepley DMLabel label; 1520a57dd577SMatthew G Knepley const char *name; 1521a57dd577SMatthew G Knepley IS valueIS; 1522a57dd577SMatthew G Knepley const PetscInt *values; 1523a57dd577SMatthew G Knepley PetscInt numValues, v; 1524a57dd577SMatthew G Knepley 15259566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 15269566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 15279566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 152863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 15299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 15309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 15319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1532a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1533a57dd577SMatthew G Knepley PetscInt size; 1534a57dd577SMatthew G Knepley 15359566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 15369566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 153763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1538a57dd577SMatthew G Knepley } 15399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 15409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 15419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 15429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1543a57dd577SMatthew G Knepley } 1544c1cad2e7SMatthew G. Knepley { 1545c1cad2e7SMatthew G. Knepley char **labelNames; 1546c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1547c1cad2e7SMatthew G. Knepley PetscBool flg; 1548c1cad2e7SMatthew G. Knepley 15499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 15509566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1551c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1552c1cad2e7SMatthew G. Knepley DMLabel label; 1553c1cad2e7SMatthew G. Knepley 15549566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1555c1cad2e7SMatthew G. Knepley if (flg) { 15569566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 15579566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1558c1cad2e7SMatthew G. Knepley } 15599566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1560c1cad2e7SMatthew G. Knepley } 15619566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1562c1cad2e7SMatthew G. Knepley } 156334aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 156434aa8a36SMatthew G. Knepley if (dm->Nf) { 156534aa8a36SMatthew G. Knepley PetscInt f; 156634aa8a36SMatthew G. Knepley 156734aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 156834aa8a36SMatthew G. Knepley const char *name; 156934aa8a36SMatthew G. Knepley 15709566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 15719566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 15729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15739566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 157434aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 15759566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 15769566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 157734aa8a36SMatthew G. Knepley } else { 15789566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 15799566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 158034aa8a36SMatthew G. Knepley } 15819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 158234aa8a36SMatthew G. Knepley } 158334aa8a36SMatthew G. Knepley } 15849566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 15858e7ff633SMatthew G. Knepley if (cdm) { 15869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15879f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 15889566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 15899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 15908e7ff633SMatthew G. Knepley } 1591552f7358SJed Brown } 1592552f7358SJed Brown PetscFunctionReturn(0); 1593552f7358SJed Brown } 1594552f7358SJed Brown 1595d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1596d71ae5a4SJacob Faibussowitsch { 1597e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1598e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1599a12d352dSMatthew G. Knepley PetscInt cdim; 1600e5c487bfSMatthew G. Knepley 1601e5c487bfSMatthew G. Knepley PetscFunctionBegin; 16029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 16039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 16049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1605e5c487bfSMatthew G. Knepley switch (ct) { 1606a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1607a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1608a12d352dSMatthew G. Knepley switch (cdim) { 16099371c9d4SSatish Balay case 1: { 1610a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1611a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1612a12d352dSMatthew G. Knepley 16139566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 16149566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 16159566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 16169371c9d4SSatish Balay } break; 16179371c9d4SSatish Balay case 2: { 1618a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1619a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1620a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1621a12d352dSMatthew G. Knepley 16229566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16239566063dSJacob 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)); 16249566063dSJacob 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)); 16259371c9d4SSatish Balay } break; 1626d71ae5a4SJacob Faibussowitsch default: 1627d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1628a12d352dSMatthew G. Knepley } 1629a12d352dSMatthew G. Knepley break; 1630e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 16319371c9d4SSatish 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)); 16329566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16339566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 16349566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1635e5c487bfSMatthew G. Knepley break; 1636e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 16379371c9d4SSatish 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)); 16389371c9d4SSatish 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)); 16399566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16409566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 16419566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 16429566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1643e5c487bfSMatthew G. Knepley break; 16449f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 16459f4ada15SMatthew 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)); 16469f4ada15SMatthew 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)); 16479f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16489f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 16499f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 16509f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 16519f4ada15SMatthew G. Knepley break; 1652d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1653d71ae5a4SJacob Faibussowitsch break; 1654d71ae5a4SJacob Faibussowitsch default: 1655d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1656e5c487bfSMatthew G. Knepley } 1657e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1658e5c487bfSMatthew G. Knepley } 1659e5c487bfSMatthew G. Knepley 1660d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1661d71ae5a4SJacob Faibussowitsch { 1662e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1663e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1664e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1665e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1666e5c487bfSMatthew G. Knepley 1667e5c487bfSMatthew G. Knepley PetscFunctionBegin; 16689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 16699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1670e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1671e5c487bfSMatthew G. Knepley switch (ct) { 16729371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 1673e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1674e5c487bfSMatthew G. Knepley 16759371c9d4SSatish Balay for (v = 0; v < 3; ++v) { 16769371c9d4SSatish Balay centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.; 16779371c9d4SSatish Balay centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.; 16789371c9d4SSatish Balay } 1679e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1680e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1681e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1682e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1683e5c487bfSMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv; 1684e5c487bfSMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv; 1685e5c487bfSMatthew G. Knepley } 16869566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1687e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 16889566063dSJacob 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)); 16899566063dSJacob 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)); 1690e5c487bfSMatthew G. Knepley } 1691e5c487bfSMatthew G. Knepley } 16929371c9d4SSatish Balay } break; 1693d71ae5a4SJacob Faibussowitsch default: 1694d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1695e5c487bfSMatthew G. Knepley } 1696e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1697e5c487bfSMatthew G. Knepley } 1698e5c487bfSMatthew G. Knepley 1699d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1700d71ae5a4SJacob Faibussowitsch { 1701e412dcbdSMatthew G. Knepley PetscDraw draw; 1702e412dcbdSMatthew G. Knepley DM cdm; 1703e412dcbdSMatthew G. Knepley PetscSection coordSection; 1704e412dcbdSMatthew G. Knepley Vec coordinates; 1705e412dcbdSMatthew G. Knepley const PetscScalar *coords; 170629494db1SLisandro Dalcin PetscReal xyl[2], xyr[2], bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1707e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1708e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1709e5c487bfSMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1710e412dcbdSMatthew G. Knepley 1711e412dcbdSMatthew G. Knepley PetscFunctionBegin; 17129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 171363a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 17149566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 17159566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 17169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 17179566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 17189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 17199566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 17209566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1721e412dcbdSMatthew G. Knepley 17229566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 17239566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 1724e412dcbdSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 17259566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1726e412dcbdSMatthew G. Knepley 17279566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 17289566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 1729e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 17309371c9d4SSatish Balay bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); 17319371c9d4SSatish Balay bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 17329371c9d4SSatish Balay bound[1] = PetscMin(bound[1], PetscRealPart(coords[c + 1])); 17339371c9d4SSatish Balay bound[3] = PetscMax(bound[3], PetscRealPart(coords[c + 1])); 1734e412dcbdSMatthew G. Knepley } 17359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 17361c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[0], xyl, 2, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)dm))); 17371c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[2], xyr, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 17389566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 17399566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1740e412dcbdSMatthew G. Knepley 1741cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1742cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1743ba2698f1SMatthew G. Knepley PetscInt numCoords; 1744cf3064d3SMatthew G. Knepley 17459566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords)); 17461baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 17471baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 17489566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 1749cf3064d3SMatthew G. Knepley } 17509566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 17519566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 17529566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 17539566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 1754e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 1755e412dcbdSMatthew G. Knepley } 1756e412dcbdSMatthew G. Knepley 17571e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17581e50132fSMatthew G. Knepley #include <exodusII.h> 17596823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 17601e50132fSMatthew G. Knepley #endif 17611e50132fSMatthew G. Knepley 1762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1763d71ae5a4SJacob Faibussowitsch { 17645f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1765002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1766552f7358SJed Brown 1767552f7358SJed Brown PetscFunctionBegin; 1768552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1769552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 17719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 17729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 17739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 17749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 17759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 17765f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1777552f7358SJed Brown if (iascii) { 17788135c375SStefano Zampini PetscViewerFormat format; 17799566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 17801baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 17811baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1782c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1783c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 17849566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1785c6ccd67eSMatthew G. Knepley #else 1786c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1787552f7358SJed Brown #endif 1788e412dcbdSMatthew G. Knepley } else if (isvtk) { 17899566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1790e412dcbdSMatthew G. Knepley } else if (isdraw) { 17919566063dSJacob Faibussowitsch PetscCall(DMPlexView_Draw(dm, viewer)); 17928135c375SStefano Zampini } else if (isglvis) { 17939566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 17941e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17951e50132fSMatthew G. Knepley } else if (isexodus) { 17966823f3c5SBlaise Bourdin /* 17976823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 17986823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 17996823f3c5SBlaise Bourdin with ID 1, containig all cells. 18006823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 18016823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 18026823f3c5SBlaise Bourdin */ 18036823f3c5SBlaise Bourdin PetscInt numCS; 18049566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 18056823f3c5SBlaise Bourdin if (!numCS) { 18061e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 18079566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 18089566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 18099566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 18106823f3c5SBlaise Bourdin } 18119566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 18121e50132fSMatthew G. Knepley #endif 18135f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 18145f34f2dcSJed Brown } else if (iscgns) { 18155f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 18165f34f2dcSJed Brown #endif 18171baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1818cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 18199566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1820cb3ba0daSMatthew G. Knepley if (flg) { 1821cb3ba0daSMatthew G. Knepley Vec ranks; 18229566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 18239566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 18249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1825cb3ba0daSMatthew G. Knepley } 1826002a2709SMatthew G. Knepley /* Optionally view a label */ 18279566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1828002a2709SMatthew G. Knepley if (flg) { 1829002a2709SMatthew G. Knepley DMLabel label; 1830002a2709SMatthew G. Knepley Vec val; 1831002a2709SMatthew G. Knepley 18329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 183328b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 18349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 18359566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 18369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1837002a2709SMatthew G. Knepley } 1838552f7358SJed Brown PetscFunctionReturn(0); 1839552f7358SJed Brown } 1840552f7358SJed Brown 18417f96f51bSksagiyam /*@ 1842a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 18437f96f51bSksagiyam 1844a1cb98faSBarry Smith Collective on dm 18457f96f51bSksagiyam 18467f96f51bSksagiyam Input Parameters: 1847a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 1848a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 18497f96f51bSksagiyam 18507f96f51bSksagiyam Level: advanced 18517f96f51bSksagiyam 1852a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 18537f96f51bSksagiyam @*/ 1854d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1855d71ae5a4SJacob Faibussowitsch { 18567f96f51bSksagiyam PetscBool ishdf5; 18577f96f51bSksagiyam 18587f96f51bSksagiyam PetscFunctionBegin; 18597f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 18607f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 18629566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 18637f96f51bSksagiyam if (ishdf5) { 18647f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 18657f96f51bSksagiyam PetscViewerFormat format; 18669566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 18677f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18687f96f51bSksagiyam IS globalPointNumbering; 18697f96f51bSksagiyam 18709566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18719566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 187398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 18747f96f51bSksagiyam #else 18757f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 18767f96f51bSksagiyam #endif 18777f96f51bSksagiyam } 18789566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 18797f96f51bSksagiyam PetscFunctionReturn(0); 18807f96f51bSksagiyam } 18817f96f51bSksagiyam 188277b8e257Sksagiyam /*@ 1883a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 188477b8e257Sksagiyam 1885a1cb98faSBarry Smith Collective on dm 188677b8e257Sksagiyam 188777b8e257Sksagiyam Input Parameters: 1888a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 1889a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 189077b8e257Sksagiyam 189177b8e257Sksagiyam Level: advanced 189277b8e257Sksagiyam 1893a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 189477b8e257Sksagiyam @*/ 1895d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1896d71ae5a4SJacob Faibussowitsch { 189777b8e257Sksagiyam PetscBool ishdf5; 189877b8e257Sksagiyam 189977b8e257Sksagiyam PetscFunctionBegin; 190077b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 190177b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 190477b8e257Sksagiyam if (ishdf5) { 190577b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 190677b8e257Sksagiyam PetscViewerFormat format; 19079566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 190877b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 19099566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 1910fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 191177b8e257Sksagiyam #else 191277b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 191377b8e257Sksagiyam #endif 191477b8e257Sksagiyam } 19159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 191677b8e257Sksagiyam PetscFunctionReturn(0); 191777b8e257Sksagiyam } 191877b8e257Sksagiyam 1919bd6565f1Sksagiyam /*@ 1920a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 1921bd6565f1Sksagiyam 1922a1cb98faSBarry Smith Collective on dm 1923bd6565f1Sksagiyam 1924bd6565f1Sksagiyam Input Parameters: 1925a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 1926a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 1927bd6565f1Sksagiyam 1928bd6565f1Sksagiyam Level: advanced 1929bd6565f1Sksagiyam 1930a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 1931bd6565f1Sksagiyam @*/ 1932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1933d71ae5a4SJacob Faibussowitsch { 1934bd6565f1Sksagiyam PetscBool ishdf5; 1935bd6565f1Sksagiyam 1936bd6565f1Sksagiyam PetscFunctionBegin; 1937bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1938bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 1941bd6565f1Sksagiyam if (ishdf5) { 1942bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 1943bd6565f1Sksagiyam IS globalPointNumbering; 1944bd6565f1Sksagiyam PetscViewerFormat format; 1945bd6565f1Sksagiyam 19469566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 1947bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 19489566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 19499566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 19509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 195198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1952bd6565f1Sksagiyam #else 1953bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1954bd6565f1Sksagiyam #endif 1955bd6565f1Sksagiyam } 19569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 1957bd6565f1Sksagiyam PetscFunctionReturn(0); 1958bd6565f1Sksagiyam } 1959bd6565f1Sksagiyam 1960021affd3Sksagiyam /*@ 1961a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 1962021affd3Sksagiyam 1963a1cb98faSBarry Smith Collective on dm 1964021affd3Sksagiyam 1965021affd3Sksagiyam Input Parameters: 1966a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 1967a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 1968a1cb98faSBarry Smith - sectiondm - The `DM` that contains the section to be saved 1969021affd3Sksagiyam 1970021affd3Sksagiyam Level: advanced 1971021affd3Sksagiyam 1972021affd3Sksagiyam Notes: 1973a1cb98faSBarry 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. 1974021affd3Sksagiyam 1975a1cb98faSBarry 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. 1976021affd3Sksagiyam 1977a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 1978021affd3Sksagiyam @*/ 1979d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1980d71ae5a4SJacob Faibussowitsch { 1981021affd3Sksagiyam PetscBool ishdf5; 1982021affd3Sksagiyam 1983021affd3Sksagiyam PetscFunctionBegin; 1984021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1985021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1986021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19889566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 1989021affd3Sksagiyam if (ishdf5) { 1990021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 19919566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 1992021affd3Sksagiyam #else 1993021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1994021affd3Sksagiyam #endif 1995021affd3Sksagiyam } 19969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 1997021affd3Sksagiyam PetscFunctionReturn(0); 1998021affd3Sksagiyam } 1999021affd3Sksagiyam 20003e97647fSksagiyam /*@ 20013e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 20023e97647fSksagiyam 2003a1cb98faSBarry Smith Collective on dm 20043e97647fSksagiyam 20053e97647fSksagiyam Input Parameters: 2006a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2007a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 2008a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 20093e97647fSksagiyam - vec - The global vector to be saved 20103e97647fSksagiyam 20113e97647fSksagiyam Level: advanced 20123e97647fSksagiyam 20133e97647fSksagiyam Notes: 2014a1cb98faSBarry 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. 20153e97647fSksagiyam 2016a1cb98faSBarry Smith Typical calling sequence: 2017a1cb98faSBarry Smith .vb 2018a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2019a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2020a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2021a1cb98faSBarry Smith DMClone(dm, §iondm); 2022a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2023a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2024a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2025a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2026a1cb98faSBarry Smith PetscSectionSetUp(section); 2027a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2028a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2029a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2030a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2031a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2032a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2033a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2034a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2035a1cb98faSBarry Smith DMDestroy(§iondm); 2036a1cb98faSBarry Smith DMDestroy(&dm); 2037a1cb98faSBarry Smith .ve 20383e97647fSksagiyam 2039a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 20403e97647fSksagiyam @*/ 2041d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2042d71ae5a4SJacob Faibussowitsch { 20433e97647fSksagiyam PetscBool ishdf5; 20443e97647fSksagiyam 20453e97647fSksagiyam PetscFunctionBegin; 20463e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20473e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20483e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 20493e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 20503e97647fSksagiyam /* Check consistency */ 20513e97647fSksagiyam { 20523e97647fSksagiyam PetscSection section; 20533e97647fSksagiyam PetscBool includesConstraints; 20543e97647fSksagiyam PetscInt m, m1; 20553e97647fSksagiyam 20569566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 20579566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 20589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 20599566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 20609566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 206163a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 20623e97647fSksagiyam } 20639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20649566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 20653e97647fSksagiyam if (ishdf5) { 20663e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 20679566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20683e97647fSksagiyam #else 20693e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20703e97647fSksagiyam #endif 20713e97647fSksagiyam } 20729566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 20733e97647fSksagiyam PetscFunctionReturn(0); 20743e97647fSksagiyam } 20753e97647fSksagiyam 20763e97647fSksagiyam /*@ 20773e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 20783e97647fSksagiyam 2079a1cb98faSBarry Smith Collective on dm 20803e97647fSksagiyam 20813e97647fSksagiyam Input Parameters: 2082a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2083a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 2084a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined; may be the same as dm 20853e97647fSksagiyam - vec - The local vector to be saved 20863e97647fSksagiyam 20873e97647fSksagiyam Level: advanced 20883e97647fSksagiyam 2089a1cb98faSBarry Smith Note: 2090a1cb98faSBarry 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. 20913e97647fSksagiyam 2092a1cb98faSBarry Smith Typical calling sequence: 2093a1cb98faSBarry Smith .vb 2094a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2095a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2096a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2097a1cb98faSBarry Smith DMClone(dm, §iondm); 2098a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2099a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2100a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2101a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2102a1cb98faSBarry Smith PetscSectionSetUp(section); 2103a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2104a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2105a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2106a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2107a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2108a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2109a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2110a1cb98faSBarry Smith DMDestroy(§iondm); 2111a1cb98faSBarry Smith DMDestroy(&dm); 2112a1cb98faSBarry Smith .ve 21133e97647fSksagiyam 2114a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 21153e97647fSksagiyam @*/ 2116d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2117d71ae5a4SJacob Faibussowitsch { 21183e97647fSksagiyam PetscBool ishdf5; 21193e97647fSksagiyam 21203e97647fSksagiyam PetscFunctionBegin; 21213e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21223e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21233e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21243e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 21253e97647fSksagiyam /* Check consistency */ 21263e97647fSksagiyam { 21273e97647fSksagiyam PetscSection section; 21283e97647fSksagiyam PetscBool includesConstraints; 21293e97647fSksagiyam PetscInt m, m1; 21303e97647fSksagiyam 21319566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 21329566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 21339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 21349566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 21359566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 213663a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 21373e97647fSksagiyam } 21389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21399566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 21403e97647fSksagiyam if (ishdf5) { 21413e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 21429566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 21433e97647fSksagiyam #else 21443e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21453e97647fSksagiyam #endif 21463e97647fSksagiyam } 21479566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 21483e97647fSksagiyam PetscFunctionReturn(0); 21493e97647fSksagiyam } 21503e97647fSksagiyam 2151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2152d71ae5a4SJacob Faibussowitsch { 2153d4f5a9a0SVaclav Hapla PetscBool ishdf5; 21542c40f234SMatthew G. Knepley 21552c40f234SMatthew G. Knepley PetscFunctionBegin; 21562c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21572c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2159d4f5a9a0SVaclav Hapla if (ishdf5) { 21602c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 21619c48423bSVaclav Hapla PetscViewerFormat format; 21629566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 21639c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 21649566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2165509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21669566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 216798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2168b458e8f1SJose E. Roman PetscFunctionReturn(0); 21692c40f234SMatthew G. Knepley #else 21702c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2171552f7358SJed Brown #endif 217298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2173552f7358SJed Brown } 2174552f7358SJed Brown 2175ea8e1828Sksagiyam /*@ 2176a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2177ea8e1828Sksagiyam 2178a1cb98faSBarry Smith Collective on dm 2179ea8e1828Sksagiyam 2180ea8e1828Sksagiyam Input Parameters: 2181a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2182a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2183ea8e1828Sksagiyam 2184dec9e869Sksagiyam Output Parameters: 2185a1cb98faSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded plex, where N is the global number of points; NULL if unneeded 2186dec9e869Sksagiyam 2187ea8e1828Sksagiyam Level: advanced 2188ea8e1828Sksagiyam 2189a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2190a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2191ea8e1828Sksagiyam @*/ 2192d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2193d71ae5a4SJacob Faibussowitsch { 2194ea8e1828Sksagiyam PetscBool ishdf5; 2195ea8e1828Sksagiyam 2196ea8e1828Sksagiyam PetscFunctionBegin; 2197ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2198ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2199f84dd6b4Sksagiyam if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 22009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22019566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2202ea8e1828Sksagiyam if (ishdf5) { 2203ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2204ea8e1828Sksagiyam PetscViewerFormat format; 22059566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2206ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22079566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 220898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2209ea8e1828Sksagiyam #else 2210ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2211ea8e1828Sksagiyam #endif 2212ea8e1828Sksagiyam } 22139566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2214ea8e1828Sksagiyam PetscFunctionReturn(0); 2215ea8e1828Sksagiyam } 2216ea8e1828Sksagiyam 22173e701f1cSksagiyam /*@ 2218a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 22193e701f1cSksagiyam 2220a1cb98faSBarry Smith Collective on dm 22213e701f1cSksagiyam 22223e701f1cSksagiyam Input Parameters: 2223a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2224a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2225a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 22263e701f1cSksagiyam 22273e701f1cSksagiyam Level: advanced 22283e701f1cSksagiyam 2229a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2230a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 22313e701f1cSksagiyam @*/ 2232d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2233d71ae5a4SJacob Faibussowitsch { 22343e701f1cSksagiyam PetscBool ishdf5; 22353e701f1cSksagiyam 22363e701f1cSksagiyam PetscFunctionBegin; 22373e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22383e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2239c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22419566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 22423e701f1cSksagiyam if (ishdf5) { 22433e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 22443e701f1cSksagiyam PetscViewerFormat format; 22459566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 22463e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22479566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 224898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 22493e701f1cSksagiyam #else 22503e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22513e701f1cSksagiyam #endif 22523e701f1cSksagiyam } 22539566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 22543e701f1cSksagiyam PetscFunctionReturn(0); 22553e701f1cSksagiyam } 22563e701f1cSksagiyam 2257b08ad5deSksagiyam /*@ 2258a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2259b08ad5deSksagiyam 2260a1cb98faSBarry Smith Collective on dm 2261b08ad5deSksagiyam 2262b08ad5deSksagiyam Input Parameters: 2263a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2264a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 2265a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 2266b08ad5deSksagiyam 2267b08ad5deSksagiyam Level: advanced 2268b08ad5deSksagiyam 2269a1cb98faSBarry Smith Note: 2270a1cb98faSBarry Smith The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs. 2271e6368b79SVaclav Hapla 2272a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2273a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2274b08ad5deSksagiyam @*/ 2275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2276d71ae5a4SJacob Faibussowitsch { 2277b08ad5deSksagiyam PetscBool ishdf5; 2278b08ad5deSksagiyam 2279b08ad5deSksagiyam PetscFunctionBegin; 2280b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2281b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2282e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22839566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22849566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2285b08ad5deSksagiyam if (ishdf5) { 2286b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2287b08ad5deSksagiyam PetscViewerFormat format; 2288b08ad5deSksagiyam 22899566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2290b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22919566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 229298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2293b08ad5deSksagiyam #else 2294b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2295b08ad5deSksagiyam #endif 2296b08ad5deSksagiyam } 22979566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2298b08ad5deSksagiyam PetscFunctionReturn(0); 2299b08ad5deSksagiyam } 2300b08ad5deSksagiyam 2301f84dd6b4Sksagiyam /*@ 2302a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2303f84dd6b4Sksagiyam 2304a1cb98faSBarry Smith Collective on dm 2305f84dd6b4Sksagiyam 2306f84dd6b4Sksagiyam Input Parameters: 2307a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2308a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 2309a1cb98faSBarry Smith . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated 2310a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2311f84dd6b4Sksagiyam 2312f84dd6b4Sksagiyam Output Parameters 2313f84dd6b4Sksagiyam + globalDofSF - The SF 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) 2314f84dd6b4Sksagiyam - localDofSF - The SF 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) 2315f84dd6b4Sksagiyam 2316f84dd6b4Sksagiyam Level: advanced 2317f84dd6b4Sksagiyam 2318f84dd6b4Sksagiyam Notes: 2319a1cb98faSBarry 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. 2320f84dd6b4Sksagiyam 2321a1cb98faSBarry 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. 2322f84dd6b4Sksagiyam 2323a1cb98faSBarry 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. 2324f84dd6b4Sksagiyam 2325f84dd6b4Sksagiyam Example using 2 processes: 2326a1cb98faSBarry Smith .vb 2327a1cb98faSBarry Smith NX (number of points on dm): 4 2328a1cb98faSBarry Smith sectionA : the on-disk section 2329a1cb98faSBarry Smith vecA : a vector associated with sectionA 2330a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2331a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2332a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2333f84dd6b4Sksagiyam 2334a1cb98faSBarry Smith rank 0 rank 1 2335a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2336a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2337a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2338a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2339a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2340a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2341a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2342a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2343a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2344a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2345a1cb98faSBarry Smith .ve 2346a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2347a1cb98faSBarry Smith 2348a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2349f84dd6b4Sksagiyam @*/ 2350d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2351d71ae5a4SJacob Faibussowitsch { 2352f84dd6b4Sksagiyam PetscBool ishdf5; 2353f84dd6b4Sksagiyam 2354f84dd6b4Sksagiyam PetscFunctionBegin; 2355f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2356f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2357f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2358f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2359f84dd6b4Sksagiyam if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2360f84dd6b4Sksagiyam if (localDofSF) PetscValidPointer(localDofSF, 6); 23619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23629566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2363f84dd6b4Sksagiyam if (ishdf5) { 2364f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 23659566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2366f84dd6b4Sksagiyam #else 2367f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2368f84dd6b4Sksagiyam #endif 2369f84dd6b4Sksagiyam } 23709566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2371f84dd6b4Sksagiyam PetscFunctionReturn(0); 2372f84dd6b4Sksagiyam } 2373f84dd6b4Sksagiyam 23748be3dfe1Sksagiyam /*@ 23758be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 23768be3dfe1Sksagiyam 2377a1cb98faSBarry Smith Collective on dm 23788be3dfe1Sksagiyam 23798be3dfe1Sksagiyam Input Parameters: 2380a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2381a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2382a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 2383a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 23848be3dfe1Sksagiyam - vec - The global vector to set values of 23858be3dfe1Sksagiyam 23868be3dfe1Sksagiyam Level: advanced 23878be3dfe1Sksagiyam 23888be3dfe1Sksagiyam Notes: 2389a1cb98faSBarry 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. 23908be3dfe1Sksagiyam 2391a1cb98faSBarry Smith Typical calling sequence: 2392a1cb98faSBarry Smith .vb 2393a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2394a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2395a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2396a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2397a1cb98faSBarry Smith DMClone(dm, §iondm); 2398a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2399a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2400a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2401a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2402a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2403a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2404a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2405a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2406a1cb98faSBarry Smith DMDestroy(§iondm); 2407a1cb98faSBarry Smith DMDestroy(&dm); 2408a1cb98faSBarry Smith .ve 24098be3dfe1Sksagiyam 2410a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2411a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 24128be3dfe1Sksagiyam @*/ 2413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2414d71ae5a4SJacob Faibussowitsch { 24158be3dfe1Sksagiyam PetscBool ishdf5; 24168be3dfe1Sksagiyam 24178be3dfe1Sksagiyam PetscFunctionBegin; 24188be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24198be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24208be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24218be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24228be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24238be3dfe1Sksagiyam /* Check consistency */ 24248be3dfe1Sksagiyam { 24258be3dfe1Sksagiyam PetscSection section; 24268be3dfe1Sksagiyam PetscBool includesConstraints; 24278be3dfe1Sksagiyam PetscInt m, m1; 24288be3dfe1Sksagiyam 24299566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 24309566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 24319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24329566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 24339566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 243463a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 24358be3dfe1Sksagiyam } 24369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24379566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 24388be3dfe1Sksagiyam if (ishdf5) { 24398be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 24409566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 24418be3dfe1Sksagiyam #else 24428be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24438be3dfe1Sksagiyam #endif 24448be3dfe1Sksagiyam } 24459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 24468be3dfe1Sksagiyam PetscFunctionReturn(0); 24478be3dfe1Sksagiyam } 24488be3dfe1Sksagiyam 24498be3dfe1Sksagiyam /*@ 24508be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 24518be3dfe1Sksagiyam 2452a1cb98faSBarry Smith Collective on dm 24538be3dfe1Sksagiyam 24548be3dfe1Sksagiyam Input Parameters: 2455a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2456a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2457a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined 2458a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 24598be3dfe1Sksagiyam - vec - The local vector to set values of 24608be3dfe1Sksagiyam 24618be3dfe1Sksagiyam Level: advanced 24628be3dfe1Sksagiyam 24638be3dfe1Sksagiyam Notes: 2464a1cb98faSBarry 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. 24658be3dfe1Sksagiyam 2466a1cb98faSBarry Smith Typical calling sequence: 2467a1cb98faSBarry Smith .vb 2468a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2469a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2470a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2471a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2472a1cb98faSBarry Smith DMClone(dm, §iondm); 2473a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2474a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2475a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2476a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2477a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2478a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2479a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2480a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2481a1cb98faSBarry Smith DMDestroy(§iondm); 2482a1cb98faSBarry Smith DMDestroy(&dm); 2483a1cb98faSBarry Smith .ve 24848be3dfe1Sksagiyam 2485a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2486a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 24878be3dfe1Sksagiyam @*/ 2488d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2489d71ae5a4SJacob Faibussowitsch { 24908be3dfe1Sksagiyam PetscBool ishdf5; 24918be3dfe1Sksagiyam 24928be3dfe1Sksagiyam PetscFunctionBegin; 24938be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24948be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24958be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24968be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24978be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24988be3dfe1Sksagiyam /* Check consistency */ 24998be3dfe1Sksagiyam { 25008be3dfe1Sksagiyam PetscSection section; 25018be3dfe1Sksagiyam PetscBool includesConstraints; 25028be3dfe1Sksagiyam PetscInt m, m1; 25038be3dfe1Sksagiyam 25049566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 25059566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 25069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 25079566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 25089566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 250963a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 25108be3dfe1Sksagiyam } 25119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25129566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 25138be3dfe1Sksagiyam if (ishdf5) { 25148be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 25159566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 25168be3dfe1Sksagiyam #else 25178be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 25188be3dfe1Sksagiyam #endif 25198be3dfe1Sksagiyam } 25209566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 25218be3dfe1Sksagiyam PetscFunctionReturn(0); 25228be3dfe1Sksagiyam } 25238be3dfe1Sksagiyam 2524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2525d71ae5a4SJacob Faibussowitsch { 2526552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2527552f7358SJed Brown 2528552f7358SJed Brown PetscFunctionBegin; 25299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 25309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 25319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 25329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 25332e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", NULL)); 25342e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 25352e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 25362e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 25372e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 25386bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 25396bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2540c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2541c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 25425f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 25430d644c17SKarl Rupp if (--mesh->refct > 0) PetscFunctionReturn(0); 25449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 25459566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 25469566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 25479566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 25489566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 25499566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 25509f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 25519566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->facesTmp)); 25529566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 25539566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 25549566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 25551d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 25569566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 25579566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 25589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 25599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 25609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 25614e2e9504SJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.face_sf)); 25626725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 25636725e60dSJed Brown PetscCall(ISDestroy(&mesh->periodic.periodic_points)); 25649566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 25659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 25669566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 25679566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 25689566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 25699566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 25709566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 25719566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 25729566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 25739566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 25749566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2575552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 25769566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 2577552f7358SJed Brown PetscFunctionReturn(0); 2578552f7358SJed Brown } 2579552f7358SJed Brown 2580d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2581d71ae5a4SJacob Faibussowitsch { 25828d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2583acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 25849fca9976SJed Brown PetscInt localSize, localStart = 0; 2585837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2586b412c318SBarry Smith MatType mtype; 25871428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2588552f7358SJed Brown 2589552f7358SJed Brown PetscFunctionBegin; 25909566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2591b412c318SBarry Smith mtype = dm->mattype; 25929566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 25939566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 25949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 25959fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 25969566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 25979566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 25989566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 25999566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 26009566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2601acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 26029566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 26039566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 26049566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 26059566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 26069566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 26079566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 26089566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 26099566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2610552f7358SJed Brown if (!isShell) { 2611837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 26129fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2613fad22124SMatthew G Knepley PetscInt pStart, pEnd, p, dof, cdof; 2614552f7358SJed Brown 26159566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 26169fca9976SJed Brown 26179fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 26189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2619e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 26209fca9976SJed Brown PetscInt bdof, offset; 2621a9d99c84SMatthew G. Knepley 26229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 26239fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 26249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 26259371c9d4SSatish Balay for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof; 26261d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 26271d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 26281d17a0a3SMatthew G. Knepley if (dof) { 26299371c9d4SSatish Balay if (bs < 0) { 26309371c9d4SSatish Balay bs = bdof; 26319371c9d4SSatish Balay } else if (bs != bdof) { 26329371c9d4SSatish Balay bs = 1; 26339371c9d4SSatish Balay } 2634552f7358SJed Brown } 26352a28c762SMatthew G Knepley } 26362a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2637e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2638e432b41dSStefano Zampini bsLocal[1] = bs; 26399566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2640e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2641e432b41dSStefano Zampini else bs = bsMinMax[0]; 26426fd5c86aSStefano Zampini bs = PetscMax(1, bs); 26439566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 26440682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 26459566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 26469566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 26470682b8bbSJed Brown } else { 26489566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 26499566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 26509566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2651552f7358SJed Brown } 26529fca9976SJed Brown { // Consolidate blocks 26539fca9976SJed Brown PetscInt nblocks = 0; 26549fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 26559fca9976SJed Brown if (pblocks[i] == 0) continue; 26569fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2657ad540459SPierre 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]); 26589fca9976SJed Brown } 26599fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 26609fca9976SJed Brown } 26619fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2662aa0f6e3cSJed Brown } 26639566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 2664552f7358SJed Brown PetscFunctionReturn(0); 2665552f7358SJed Brown } 2666552f7358SJed Brown 26677cd05799SMatthew G. Knepley /*@ 2668a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2669be36d101SStefano Zampini 2670a1cb98faSBarry Smith Not Collective 2671be36d101SStefano Zampini 2672be36d101SStefano Zampini Input Parameter: 2673a1cb98faSBarry Smith . mesh - The `DMPLEX` 2674be36d101SStefano Zampini 2675be36d101SStefano Zampini Output Parameters: 2676be36d101SStefano Zampini . subsection - The subdomain section 2677be36d101SStefano Zampini 2678be36d101SStefano Zampini Level: developer 2679be36d101SStefano Zampini 2680a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSection` 26817cd05799SMatthew G. Knepley @*/ 2682d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2683d71ae5a4SJacob Faibussowitsch { 2684be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2685be36d101SStefano Zampini 2686be36d101SStefano Zampini PetscFunctionBegin; 2687be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2688be36d101SStefano Zampini if (!mesh->subdomainSection) { 2689be36d101SStefano Zampini PetscSection section; 2690be36d101SStefano Zampini PetscSF sf; 2691be36d101SStefano Zampini 26929566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 26939566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 26949566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 26959566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2696be36d101SStefano Zampini } 2697be36d101SStefano Zampini *subsection = mesh->subdomainSection; 2698be36d101SStefano Zampini PetscFunctionReturn(0); 2699be36d101SStefano Zampini } 2700be36d101SStefano Zampini 2701552f7358SJed Brown /*@ 2702552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2703552f7358SJed Brown 2704a1cb98faSBarry Smith Not Collective 2705552f7358SJed Brown 2706552f7358SJed Brown Input Parameter: 2707a1cb98faSBarry Smith . mesh - The `DMPLEX` 2708552f7358SJed Brown 2709552f7358SJed Brown Output Parameters: 2710552f7358SJed Brown + pStart - The first mesh point 2711552f7358SJed Brown - pEnd - The upper bound for mesh points 2712552f7358SJed Brown 2713552f7358SJed Brown Level: beginner 2714552f7358SJed Brown 2715a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2716552f7358SJed Brown @*/ 2717d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2718d71ae5a4SJacob Faibussowitsch { 2719552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2720552f7358SJed Brown 2721552f7358SJed Brown PetscFunctionBegin; 2722552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27239f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 27249f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 2725552f7358SJed Brown PetscFunctionReturn(0); 2726552f7358SJed Brown } 2727552f7358SJed Brown 2728552f7358SJed Brown /*@ 2729552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2730552f7358SJed Brown 2731a1cb98faSBarry Smith Not Collective 2732552f7358SJed Brown 2733552f7358SJed Brown Input Parameters: 2734a1cb98faSBarry Smith + mesh - The `DMPLEX` 2735552f7358SJed Brown . pStart - The first mesh point 2736552f7358SJed Brown - pEnd - The upper bound for mesh points 2737552f7358SJed Brown 2738552f7358SJed Brown Level: beginner 2739552f7358SJed Brown 2740a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2741552f7358SJed Brown @*/ 2742d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2743d71ae5a4SJacob Faibussowitsch { 2744552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2745552f7358SJed Brown 2746552f7358SJed Brown PetscFunctionBegin; 2747552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 27499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 2750552f7358SJed Brown PetscFunctionReturn(0); 2751552f7358SJed Brown } 2752552f7358SJed Brown 2753552f7358SJed Brown /*@ 2754eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2755552f7358SJed Brown 2756a1cb98faSBarry Smith Not Collective 2757552f7358SJed Brown 2758552f7358SJed Brown Input Parameters: 2759a1cb98faSBarry Smith + mesh - The `DMPLEX` 2760a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2761552f7358SJed Brown 2762552f7358SJed Brown Output Parameter: 2763552f7358SJed Brown . size - The cone size for point p 2764552f7358SJed Brown 2765552f7358SJed Brown Level: beginner 2766552f7358SJed Brown 2767a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2768552f7358SJed Brown @*/ 2769d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2770d71ae5a4SJacob Faibussowitsch { 2771552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2772552f7358SJed Brown 2773552f7358SJed Brown PetscFunctionBegin; 2774552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2775dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 27769f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 27779f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 2778552f7358SJed Brown PetscFunctionReturn(0); 2779552f7358SJed Brown } 2780552f7358SJed Brown 2781552f7358SJed Brown /*@ 2782eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2783552f7358SJed Brown 2784a1cb98faSBarry Smith Not Collective 2785552f7358SJed Brown 2786552f7358SJed Brown Input Parameters: 2787a1cb98faSBarry Smith + mesh - The `DMPLEX` 2788a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 2789552f7358SJed Brown - size - The cone size for point p 2790552f7358SJed Brown 2791552f7358SJed Brown Level: beginner 2792552f7358SJed Brown 2793a1cb98faSBarry Smith Note: 2794a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 2795a1cb98faSBarry Smith 2796a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2797552f7358SJed Brown @*/ 2798d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2799d71ae5a4SJacob Faibussowitsch { 2800552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2801552f7358SJed Brown 2802552f7358SJed Brown PetscFunctionBegin; 2803552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28049f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 28059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 2806552f7358SJed Brown PetscFunctionReturn(0); 2807552f7358SJed Brown } 2808552f7358SJed Brown 2809552f7358SJed Brown /*@C 2810eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2811552f7358SJed Brown 2812a1cb98faSBarry Smith Not Collective 2813552f7358SJed Brown 2814552f7358SJed Brown Input Parameters: 2815a1cb98faSBarry Smith + dm - The `DMPLEX` 2816a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2817552f7358SJed Brown 2818552f7358SJed Brown Output Parameter: 2819552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 2820552f7358SJed Brown 2821552f7358SJed Brown Level: beginner 2822552f7358SJed Brown 2823a1cb98faSBarry Smith Fortran Note: 2824a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 2825a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 28263813dfbdSMatthew G Knepley 2827a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 2828552f7358SJed Brown @*/ 2829d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2830d71ae5a4SJacob Faibussowitsch { 2831552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2832552f7358SJed Brown PetscInt off; 2833552f7358SJed Brown 2834552f7358SJed Brown PetscFunctionBegin; 2835552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2836552f7358SJed Brown PetscValidPointer(cone, 3); 28379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 2838552f7358SJed Brown *cone = &mesh->cones[off]; 2839552f7358SJed Brown PetscFunctionReturn(0); 2840552f7358SJed Brown } 2841552f7358SJed Brown 28420ce7577fSVaclav Hapla /*@C 28430ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 28440ce7577fSVaclav Hapla 2845a1cb98faSBarry Smith Not Collective 28460ce7577fSVaclav Hapla 28470ce7577fSVaclav Hapla Input Parameters: 2848a1cb98faSBarry Smith + dm - The `DMPLEX` 2849a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 28500ce7577fSVaclav Hapla 2851d8d19677SJose E. Roman Output Parameters: 2852a1cb98faSBarry Smith + pConesSection - `PetscSection` describing the layout of pCones 28530ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p 28540ce7577fSVaclav Hapla 28550ce7577fSVaclav Hapla Level: intermediate 28560ce7577fSVaclav Hapla 2857a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 28580ce7577fSVaclav Hapla @*/ 2859d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2860d71ae5a4SJacob Faibussowitsch { 28610ce7577fSVaclav Hapla PetscSection cs, newcs; 28620ce7577fSVaclav Hapla PetscInt *cones; 28630ce7577fSVaclav Hapla PetscInt *newarr = NULL; 28640ce7577fSVaclav Hapla PetscInt n; 28650ce7577fSVaclav Hapla 28660ce7577fSVaclav Hapla PetscFunctionBegin; 28679566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 28689566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 28699566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 28700ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 28710ce7577fSVaclav Hapla if (pCones) { 28729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 28739566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 28740ce7577fSVaclav Hapla } 28750ce7577fSVaclav Hapla PetscFunctionReturn(0); 28760ce7577fSVaclav Hapla } 28770ce7577fSVaclav Hapla 2878af9eab45SVaclav Hapla /*@ 2879af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2880d4636a37SVaclav Hapla 2881a1cb98faSBarry Smith Not Collective 2882d4636a37SVaclav Hapla 2883d4636a37SVaclav Hapla Input Parameters: 2884a1cb98faSBarry Smith + dm - The `DMPLEX` 2885a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 2886d4636a37SVaclav Hapla 2887d4636a37SVaclav Hapla Output Parameter: 2888af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 2889d4636a37SVaclav Hapla 2890d4636a37SVaclav Hapla Level: advanced 2891d4636a37SVaclav Hapla 2892af9eab45SVaclav Hapla Notes: 2893a1cb98faSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth IS (i.e. vertices only) and no sections. 2894af9eab45SVaclav Hapla 2895a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 2896a1cb98faSBarry Smith 2897a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 2898a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 2899d4636a37SVaclav Hapla @*/ 2900d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2901d71ae5a4SJacob Faibussowitsch { 2902af9eab45SVaclav Hapla IS *expandedPointsAll; 2903af9eab45SVaclav Hapla PetscInt depth; 2904d4636a37SVaclav Hapla 2905d4636a37SVaclav Hapla PetscFunctionBegin; 2906af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2907af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2908af9eab45SVaclav Hapla PetscValidPointer(expandedPoints, 3); 29099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2910af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 29119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 29129566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2913af9eab45SVaclav Hapla PetscFunctionReturn(0); 2914af9eab45SVaclav Hapla } 2915af9eab45SVaclav Hapla 2916af9eab45SVaclav Hapla /*@ 2917af9eab45SVaclav 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). 2918af9eab45SVaclav Hapla 2919a1cb98faSBarry Smith Not Collective 2920af9eab45SVaclav Hapla 2921af9eab45SVaclav Hapla Input Parameters: 2922a1cb98faSBarry Smith + dm - The `DMPLEX` 2923a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 2924af9eab45SVaclav Hapla 2925d8d19677SJose E. Roman Output Parameters: 2926a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 2927af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 2928af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2929af9eab45SVaclav Hapla 2930af9eab45SVaclav Hapla Level: advanced 2931af9eab45SVaclav Hapla 2932af9eab45SVaclav Hapla Notes: 2933a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 2934af9eab45SVaclav Hapla 2935af9eab45SVaclav Hapla 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. 2936af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2937af9eab45SVaclav Hapla 2938a1cb98faSBarry Smith 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: 2939af9eab45SVaclav Hapla (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2940af9eab45SVaclav Hapla (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2941af9eab45SVaclav Hapla 2942a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 2943a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 2944af9eab45SVaclav Hapla @*/ 2945d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2946d71ae5a4SJacob Faibussowitsch { 2947af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 2948af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 2949af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 2950af9eab45SVaclav Hapla IS *expandedPoints_; 2951af9eab45SVaclav Hapla PetscSection *sections_; 2952af9eab45SVaclav Hapla 2953af9eab45SVaclav Hapla PetscFunctionBegin; 2954af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2955af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2956af9eab45SVaclav Hapla if (depth) PetscValidIntPointer(depth, 3); 2957af9eab45SVaclav Hapla if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2958af9eab45SVaclav Hapla if (sections) PetscValidPointer(sections, 5); 29599566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 29609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 29619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29629566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 29639566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 2964af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 2965af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 29669566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 29679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 2968af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 29699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 2970af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 29719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 29729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 2973af9eab45SVaclav Hapla } else { 29749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 2975af9eab45SVaclav Hapla } 2976af9eab45SVaclav Hapla } 29779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 29789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 29799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 2980af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 29819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 29829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 2983af9eab45SVaclav Hapla if (cn > 1) { 29849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 29859566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 2986af9eab45SVaclav Hapla } else { 2987af9eab45SVaclav Hapla newarr[co] = arr[i]; 2988af9eab45SVaclav Hapla } 2989af9eab45SVaclav Hapla } 29909566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 2991af9eab45SVaclav Hapla arr = newarr; 2992af9eab45SVaclav Hapla n = newn; 2993af9eab45SVaclav Hapla } 29949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 2995af9eab45SVaclav Hapla *depth = depth_; 2996af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 2997af9eab45SVaclav Hapla else { 29989566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 29999566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3000af9eab45SVaclav Hapla } 3001af9eab45SVaclav Hapla if (sections) *sections = sections_; 3002af9eab45SVaclav Hapla else { 30039566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 30049566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3005af9eab45SVaclav Hapla } 3006af9eab45SVaclav Hapla PetscFunctionReturn(0); 3007af9eab45SVaclav Hapla } 3008af9eab45SVaclav Hapla 3009af9eab45SVaclav Hapla /*@ 3010a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3011af9eab45SVaclav Hapla 3012a1cb98faSBarry Smith Not Collective 3013af9eab45SVaclav Hapla 3014af9eab45SVaclav Hapla Input Parameters: 3015a1cb98faSBarry Smith + dm - The `DMPLEX` 3016a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3017af9eab45SVaclav Hapla 3018d8d19677SJose E. Roman Output Parameters: 3019a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3020af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3021af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3022af9eab45SVaclav Hapla 3023af9eab45SVaclav Hapla Level: advanced 3024af9eab45SVaclav Hapla 3025a1cb98faSBarry Smith Note: 3026a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3027af9eab45SVaclav Hapla 3028a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3029a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3030af9eab45SVaclav Hapla @*/ 3031d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3032d71ae5a4SJacob Faibussowitsch { 3033af9eab45SVaclav Hapla PetscInt d, depth_; 3034af9eab45SVaclav Hapla 3035af9eab45SVaclav Hapla PetscFunctionBegin; 30369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 30371dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3038af9eab45SVaclav Hapla if (depth) *depth = 0; 3039af9eab45SVaclav Hapla if (expandedPoints) { 30409566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 30419566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3042af9eab45SVaclav Hapla } 3043af9eab45SVaclav Hapla if (sections) { 30449566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 30459566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3046af9eab45SVaclav Hapla } 3047d4636a37SVaclav Hapla PetscFunctionReturn(0); 3048d4636a37SVaclav Hapla } 3049d4636a37SVaclav Hapla 3050552f7358SJed Brown /*@ 305192371b87SBarry 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 3052552f7358SJed Brown 3053a1cb98faSBarry Smith Not Collective 3054552f7358SJed Brown 3055552f7358SJed Brown Input Parameters: 3056a1cb98faSBarry Smith + mesh - The `DMPLEX` 3057a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3058552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 3059552f7358SJed Brown 3060552f7358SJed Brown Level: beginner 3061552f7358SJed Brown 3062a1cb98faSBarry Smith Note: 3063a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3064a1cb98faSBarry Smith 3065a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3066552f7358SJed Brown @*/ 3067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3068d71ae5a4SJacob Faibussowitsch { 3069552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3070552f7358SJed Brown PetscInt pStart, pEnd; 3071552f7358SJed Brown PetscInt dof, off, c; 3072552f7358SJed Brown 3073552f7358SJed Brown PetscFunctionBegin; 3074552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 30769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3077dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(cone, 3); 30789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 307963a3b9bcSJacob 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); 3080552f7358SJed Brown for (c = 0; c < dof; ++c) { 308163a3b9bcSJacob 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); 3082552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3083552f7358SJed Brown } 3084552f7358SJed Brown PetscFunctionReturn(0); 3085552f7358SJed Brown } 3086552f7358SJed Brown 3087552f7358SJed Brown /*@C 3088eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3089552f7358SJed Brown 3090a1cb98faSBarry Smith Not Collective 3091552f7358SJed Brown 3092552f7358SJed Brown Input Parameters: 3093a1cb98faSBarry Smith + mesh - The `DMPLEX` 3094a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3095552f7358SJed Brown 3096552f7358SJed Brown Output Parameter: 3097552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 3098b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3099552f7358SJed Brown 3100552f7358SJed Brown Level: beginner 3101552f7358SJed Brown 3102a1cb98faSBarry Smith Note: 3103b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3104b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3105a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3106b5a892a1SMatthew G. Knepley with the identity. 3107b5a892a1SMatthew G. Knepley 3108a1cb98faSBarry Smith Fortran Note: 3109a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3110a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 31113813dfbdSMatthew G Knepley 3112a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3113552f7358SJed Brown @*/ 3114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3115d71ae5a4SJacob Faibussowitsch { 3116552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3117552f7358SJed Brown PetscInt off; 3118552f7358SJed Brown 3119552f7358SJed Brown PetscFunctionBegin; 3120552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 312176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3122552f7358SJed Brown PetscInt dof; 31239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3124552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 3125552f7358SJed Brown } 31269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 31270d644c17SKarl Rupp 3128552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 3129552f7358SJed Brown PetscFunctionReturn(0); 3130552f7358SJed Brown } 3131552f7358SJed Brown 3132552f7358SJed Brown /*@ 3133eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3134552f7358SJed Brown 3135a1cb98faSBarry Smith Not Collective 3136552f7358SJed Brown 3137552f7358SJed Brown Input Parameters: 3138a1cb98faSBarry Smith + mesh - The `DMPLEX` 3139a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3140b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3141b5a892a1SMatthew G. Knepley 3142552f7358SJed Brown Level: beginner 3143552f7358SJed Brown 3144a1cb98faSBarry Smith Notes: 3145a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3146a1cb98faSBarry Smith 3147a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3148a1cb98faSBarry Smith 3149a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3150552f7358SJed Brown @*/ 3151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3152d71ae5a4SJacob Faibussowitsch { 3153552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3154552f7358SJed Brown PetscInt pStart, pEnd; 3155552f7358SJed Brown PetscInt dof, off, c; 3156552f7358SJed Brown 3157552f7358SJed Brown PetscFunctionBegin; 3158552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 31609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3161dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(coneOrientation, 3); 31629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 316363a3b9bcSJacob 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); 3164552f7358SJed Brown for (c = 0; c < dof; ++c) { 3165552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3166552f7358SJed Brown 31679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 31681dca8a05SBarry 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); 3169552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3170552f7358SJed Brown } 3171552f7358SJed Brown PetscFunctionReturn(0); 3172552f7358SJed Brown } 3173552f7358SJed Brown 31747cd05799SMatthew G. Knepley /*@ 3175eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 31767cd05799SMatthew G. Knepley 3177a1cb98faSBarry Smith Not Collective 31787cd05799SMatthew G. Knepley 31797cd05799SMatthew G. Knepley Input Parameters: 3180a1cb98faSBarry Smith + mesh - The `DMPLEX` 3181a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 31827cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31837cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 31847cd05799SMatthew G. Knepley 31857cd05799SMatthew G. Knepley Level: beginner 31867cd05799SMatthew G. Knepley 3187a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31887cd05799SMatthew G. Knepley @*/ 3189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3190d71ae5a4SJacob Faibussowitsch { 3191552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3192552f7358SJed Brown PetscInt pStart, pEnd; 3193552f7358SJed Brown PetscInt dof, off; 3194552f7358SJed Brown 3195552f7358SJed Brown PetscFunctionBegin; 3196552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 319863a3b9bcSJacob 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); 319963a3b9bcSJacob 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); 32009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 320263a3b9bcSJacob 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); 3203552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 3204552f7358SJed Brown PetscFunctionReturn(0); 3205552f7358SJed Brown } 3206552f7358SJed Brown 32077cd05799SMatthew G. Knepley /*@ 3208eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 32097cd05799SMatthew G. Knepley 3210a1cb98faSBarry Smith Not Collective 32117cd05799SMatthew G. Knepley 32127cd05799SMatthew G. Knepley Input Parameters: 3213a1cb98faSBarry Smith + mesh - The `DMPLEX` 3214a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 32157cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 32167cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 32177cd05799SMatthew G. Knepley 32187cd05799SMatthew G. Knepley Level: beginner 32197cd05799SMatthew G. Knepley 3220a1cb98faSBarry Smith Note: 3221a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3222b5a892a1SMatthew G. Knepley 3223a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 32247cd05799SMatthew G. Knepley @*/ 3225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3226d71ae5a4SJacob Faibussowitsch { 322777c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 322877c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 322977c88f5bSMatthew G Knepley PetscInt dof, off; 323077c88f5bSMatthew G Knepley 323177c88f5bSMatthew G Knepley PetscFunctionBegin; 323277c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 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); 32359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 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); 323877c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 323977c88f5bSMatthew G Knepley PetscFunctionReturn(0); 324077c88f5bSMatthew G Knepley } 324177c88f5bSMatthew G Knepley 32429f4ada15SMatthew G. Knepley /*@C 32439f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 32449f4ada15SMatthew G. Knepley 32459f4ada15SMatthew G. Knepley Not collective 32469f4ada15SMatthew G. Knepley 32479f4ada15SMatthew G. Knepley Input Parameters: 32489f4ada15SMatthew G. Knepley + dm - The DMPlex 32499f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 32509f4ada15SMatthew G. Knepley 32519f4ada15SMatthew G. Knepley Output Parameters: 32529f4ada15SMatthew G. Knepley + cone - An array of points which are on the in-edges for point p 32539f4ada15SMatthew G. Knepley - ornt - An array of orientations which are on the in-edges for point p. An orientation is an 32549f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 32559f4ada15SMatthew G. Knepley 32569f4ada15SMatthew G. Knepley Level: beginner 32579f4ada15SMatthew G. Knepley 32589f4ada15SMatthew G. Knepley Notes: 32599f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 32609f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 32619f4ada15SMatthew G. Knepley of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 32629f4ada15SMatthew G. Knepley with the identity. 32639f4ada15SMatthew G. Knepley 32649f4ada15SMatthew G. Knepley Fortran Notes: 32659f4ada15SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 32669f4ada15SMatthew G. Knepley include petsc.h90 in your code. 32679f4ada15SMatthew G. Knepley You must also call DMPlexRestoreCone() after you finish using the returned array. 32689f4ada15SMatthew G. Knepley DMPlexRestoreCone() is not needed/available in C. 32699f4ada15SMatthew G. Knepley 32709f4ada15SMatthew G. Knepley .seealso: `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 32719f4ada15SMatthew G. Knepley @*/ 32729f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 32739f4ada15SMatthew G. Knepley { 32749f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 32759f4ada15SMatthew G. Knepley 32769f4ada15SMatthew G. Knepley PetscFunctionBegin; 32779f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32789f4ada15SMatthew G. Knepley if (mesh->tr) { 32799f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 32809f4ada15SMatthew G. Knepley } else { 32819f4ada15SMatthew G. Knepley PetscInt off; 32829f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 32839f4ada15SMatthew G. Knepley PetscInt dof; 32849f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32859f4ada15SMatthew G. Knepley if (dof) { 32869f4ada15SMatthew G. Knepley if (cone) PetscValidPointer(cone, 3); 32879f4ada15SMatthew G. Knepley if (ornt) PetscValidPointer(ornt, 4); 32889f4ada15SMatthew G. Knepley } 32899f4ada15SMatthew G. Knepley } 32909f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 32919f4ada15SMatthew G. Knepley if (cone) *cone = &mesh->cones[off]; 32929f4ada15SMatthew G. Knepley if (ornt) *ornt = &mesh->coneOrientations[off]; 32939f4ada15SMatthew G. Knepley } 32949f4ada15SMatthew G. Knepley PetscFunctionReturn(0); 32959f4ada15SMatthew G. Knepley } 32969f4ada15SMatthew G. Knepley 32979f4ada15SMatthew G. Knepley /*@C 32989f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 32999f4ada15SMatthew G. Knepley 33009f4ada15SMatthew G. Knepley Not collective 33019f4ada15SMatthew G. Knepley 33029f4ada15SMatthew G. Knepley Input Parameters: 33039f4ada15SMatthew G. Knepley + dm - The DMPlex 33049f4ada15SMatthew G. Knepley . p - The point, which must lie in the chart set with DMPlexSetChart() 33059f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 33069f4ada15SMatthew G. Knepley - ornt - An array of orientations which are on the in-edges for point p. An orientation is an 33079f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 33089f4ada15SMatthew G. Knepley 33099f4ada15SMatthew G. Knepley Level: beginner 33109f4ada15SMatthew G. Knepley 33119f4ada15SMatthew G. Knepley Notes: 33129f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 33139f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 33149f4ada15SMatthew G. Knepley of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 33159f4ada15SMatthew G. Knepley with the identity. 33169f4ada15SMatthew G. Knepley 33179f4ada15SMatthew G. Knepley Fortran Notes: 33189f4ada15SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 33199f4ada15SMatthew G. Knepley include petsc.h90 in your code. 33209f4ada15SMatthew G. Knepley You must also call DMPlexRestoreCone() after you finish using the returned array. 33219f4ada15SMatthew G. Knepley DMPlexRestoreCone() is not needed/available in C. 33229f4ada15SMatthew G. Knepley 33239f4ada15SMatthew G. Knepley .seealso: `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 33249f4ada15SMatthew G. Knepley @*/ 33259f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 33269f4ada15SMatthew G. Knepley { 33279f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 33289f4ada15SMatthew G. Knepley 33299f4ada15SMatthew G. Knepley PetscFunctionBegin; 33309f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33319f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 33329f4ada15SMatthew G. Knepley PetscFunctionReturn(0); 33339f4ada15SMatthew G. Knepley } 33349f4ada15SMatthew G. Knepley 3335552f7358SJed Brown /*@ 3336eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3337552f7358SJed Brown 3338a1cb98faSBarry Smith Not Collective 3339552f7358SJed Brown 3340552f7358SJed Brown Input Parameters: 3341a1cb98faSBarry Smith + mesh - The `DMPLEX` 3342a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3343552f7358SJed Brown 3344552f7358SJed Brown Output Parameter: 3345552f7358SJed Brown . size - The support size for point p 3346552f7358SJed Brown 3347552f7358SJed Brown Level: beginner 3348552f7358SJed Brown 3349a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3350552f7358SJed Brown @*/ 3351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3352d71ae5a4SJacob Faibussowitsch { 3353552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3354552f7358SJed Brown 3355552f7358SJed Brown PetscFunctionBegin; 3356552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3357dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 33589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 3359552f7358SJed Brown PetscFunctionReturn(0); 3360552f7358SJed Brown } 3361552f7358SJed Brown 3362552f7358SJed Brown /*@ 3363eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3364552f7358SJed Brown 3365a1cb98faSBarry Smith Not Collective 3366552f7358SJed Brown 3367552f7358SJed Brown Input Parameters: 3368a1cb98faSBarry Smith + mesh - The `DMPLEX` 3369a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3370552f7358SJed Brown - size - The support size for point p 3371552f7358SJed Brown 3372a1cb98faSBarry Smith Level: beginner 3373552f7358SJed Brown 3374552f7358SJed Brown Note: 3375552f7358SJed Brown This should be called after DMPlexSetChart(). 3376552f7358SJed Brown 3377a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3378552f7358SJed Brown @*/ 3379d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3380d71ae5a4SJacob Faibussowitsch { 3381552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3382552f7358SJed Brown 3383552f7358SJed Brown PetscFunctionBegin; 3384552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 3386552f7358SJed Brown PetscFunctionReturn(0); 3387552f7358SJed Brown } 3388552f7358SJed Brown 3389552f7358SJed Brown /*@C 3390eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3391552f7358SJed Brown 3392a1cb98faSBarry Smith Not Collective 3393552f7358SJed Brown 3394552f7358SJed Brown Input Parameters: 3395a1cb98faSBarry Smith + mesh - The `DMPLEX` 3396a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3397552f7358SJed Brown 3398552f7358SJed Brown Output Parameter: 3399552f7358SJed Brown . support - An array of points which are on the out-edges for point p 3400552f7358SJed Brown 3401552f7358SJed Brown Level: beginner 3402552f7358SJed Brown 3403a1cb98faSBarry Smith Fortran Note: 3404a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3405a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 34063813dfbdSMatthew G Knepley 3407a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3408552f7358SJed Brown @*/ 3409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3410d71ae5a4SJacob Faibussowitsch { 3411552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3412552f7358SJed Brown PetscInt off; 3413552f7358SJed Brown 3414552f7358SJed Brown PetscFunctionBegin; 3415552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3416552f7358SJed Brown PetscValidPointer(support, 3); 34179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3418552f7358SJed Brown *support = &mesh->supports[off]; 3419552f7358SJed Brown PetscFunctionReturn(0); 3420552f7358SJed Brown } 3421552f7358SJed Brown 3422552f7358SJed Brown /*@ 342392371b87SBarry 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 3424552f7358SJed Brown 3425a1cb98faSBarry Smith Not Collective 3426552f7358SJed Brown 3427552f7358SJed Brown Input Parameters: 3428a1cb98faSBarry Smith + mesh - The `DMPLEX` 3429a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 343092371b87SBarry Smith - support - An array of points which are on the out-edges for point p 3431552f7358SJed Brown 3432552f7358SJed Brown Level: beginner 3433552f7358SJed Brown 3434a1cb98faSBarry Smith Note: 3435a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3436a1cb98faSBarry Smith 3437a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3438552f7358SJed Brown @*/ 3439d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3440d71ae5a4SJacob Faibussowitsch { 3441552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3442552f7358SJed Brown PetscInt pStart, pEnd; 3443552f7358SJed Brown PetscInt dof, off, c; 3444552f7358SJed Brown 3445552f7358SJed Brown PetscFunctionBegin; 3446552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 34489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 3449dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(support, 3); 34509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 345163a3b9bcSJacob 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); 3452552f7358SJed Brown for (c = 0; c < dof; ++c) { 345363a3b9bcSJacob 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); 3454552f7358SJed Brown mesh->supports[off + c] = support[c]; 3455552f7358SJed Brown } 3456552f7358SJed Brown PetscFunctionReturn(0); 3457552f7358SJed Brown } 3458552f7358SJed Brown 34597cd05799SMatthew G. Knepley /*@ 3460eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 34617cd05799SMatthew G. Knepley 3462a1cb98faSBarry Smith Not Collective 34637cd05799SMatthew G. Knepley 34647cd05799SMatthew G. Knepley Input Parameters: 3465a1cb98faSBarry Smith + mesh - The `DMPLEX` 3466a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34677cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 34687cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 34697cd05799SMatthew G. Knepley 34707cd05799SMatthew G. Knepley Level: beginner 34717cd05799SMatthew G. Knepley 3472a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34737cd05799SMatthew G. Knepley @*/ 3474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3475d71ae5a4SJacob Faibussowitsch { 3476552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3477552f7358SJed Brown PetscInt pStart, pEnd; 3478552f7358SJed Brown PetscInt dof, off; 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)); 34849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 348563a3b9bcSJacob 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); 348663a3b9bcSJacob 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); 348763a3b9bcSJacob 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); 3488552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 3489552f7358SJed Brown PetscFunctionReturn(0); 3490552f7358SJed Brown } 3491552f7358SJed Brown 3492b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3493d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3494d71ae5a4SJacob Faibussowitsch { 3495b5a892a1SMatthew G. Knepley switch (ct) { 3496b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3497b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3498b5a892a1SMatthew G. Knepley break; 3499b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3500b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3501b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3502b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3503b5a892a1SMatthew G. Knepley break; 3504b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3505b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3506b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3507b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3508b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3509b5a892a1SMatthew G. Knepley break; 3510d71ae5a4SJacob Faibussowitsch default: 3511d71ae5a4SJacob Faibussowitsch return o; 3512b5a892a1SMatthew G. Knepley } 3513b5a892a1SMatthew G. Knepley return o; 3514b5a892a1SMatthew G. Knepley } 3515b5a892a1SMatthew G. Knepley 3516b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3517d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3518d71ae5a4SJacob Faibussowitsch { 3519b5a892a1SMatthew G. Knepley switch (ct) { 3520b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3521b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3522b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3523b5a892a1SMatthew G. Knepley break; 3524b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3525b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3526b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3527b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3528b5a892a1SMatthew G. Knepley break; 3529b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3530b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3531b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3532b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3533b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3534b5a892a1SMatthew G. Knepley break; 3535d71ae5a4SJacob Faibussowitsch default: 3536d71ae5a4SJacob Faibussowitsch return o; 3537b5a892a1SMatthew G. Knepley } 3538b5a892a1SMatthew G. Knepley return o; 3539b5a892a1SMatthew G. Knepley } 3540b5a892a1SMatthew G. Knepley 3541b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3542d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3543d71ae5a4SJacob Faibussowitsch { 3544b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3545b5a892a1SMatthew G. Knepley 3546b5a892a1SMatthew G. Knepley PetscFunctionBegin; 35479566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3548b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3549b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3550b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3551b5a892a1SMatthew G. Knepley 35529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 35539566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 35549566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3555b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3556b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3557b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3558b5a892a1SMatthew G. Knepley 35599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3560b5a892a1SMatthew G. Knepley switch (ct) { 3561b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 35629566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 35639566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3564b5a892a1SMatthew G. Knepley break; 3565b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 35669566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 35679566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 35689566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3569b5a892a1SMatthew G. Knepley break; 3570b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 35719566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 35729566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 35739566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 35749566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3575b5a892a1SMatthew G. Knepley break; 3576d71ae5a4SJacob Faibussowitsch default: 3577d71ae5a4SJacob Faibussowitsch break; 3578b5a892a1SMatthew G. Knepley } 3579b5a892a1SMatthew G. Knepley } 3580b5a892a1SMatthew G. Knepley } 3581b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3582b5a892a1SMatthew G. Knepley } 3583b5a892a1SMatthew G. Knepley 3584d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3585d71ae5a4SJacob Faibussowitsch { 3586b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3587b5a892a1SMatthew G. Knepley PetscInt *closure; 3588b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3589b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3590b5a892a1SMatthew G. Knepley 3591b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3592b5a892a1SMatthew G. Knepley if (ornt) { 35939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3594b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3595b5a892a1SMatthew G. Knepley } 3596b5a892a1SMatthew G. Knepley if (*points) { 3597b5a892a1SMatthew G. Knepley closure = *points; 3598b5a892a1SMatthew G. Knepley } else { 3599b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 36009566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 36019566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3602b5a892a1SMatthew G. Knepley } 3603b5a892a1SMatthew G. Knepley if (useCone) { 36049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &tmpSize)); 36059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &tmp)); 36069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO)); 3607b5a892a1SMatthew G. Knepley } else { 36089566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize)); 36099566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &tmp)); 3610b5a892a1SMatthew G. Knepley } 3611b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3612b5a892a1SMatthew G. Knepley closure[off++] = p; 3613b5a892a1SMatthew G. Knepley closure[off++] = 0; 3614b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3615b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3616b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3617b5a892a1SMatthew G. Knepley } 3618b5a892a1SMatthew G. Knepley } else { 36195f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3620b5a892a1SMatthew G. Knepley 3621b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3622b5a892a1SMatthew G. Knepley closure[off++] = p; 3623b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3624b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3625b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3626b5a892a1SMatthew G. Knepley 36279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3628b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3629b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3630b5a892a1SMatthew G. Knepley } 3631b5a892a1SMatthew G. Knepley } 3632b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3633b5a892a1SMatthew G. Knepley if (points) *points = closure; 3634b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3635b5a892a1SMatthew G. Knepley } 3636b5a892a1SMatthew G. Knepley 3637d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3638d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3639d71ae5a4SJacob Faibussowitsch { 3640b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3641b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3642b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3643b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3644b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3645b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3646b5a892a1SMatthew G. Knepley 3647b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 36489566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 36499566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 36509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 36519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &ornt)); 36529566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3653b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3654b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3655b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 36569371c9d4SSatish Balay if (*points) { 36579371c9d4SSatish Balay pts = *points; 36589371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3659b5a892a1SMatthew G. Knepley c = 0; 3660b5a892a1SMatthew G. Knepley pts[c++] = point; 3661b5a892a1SMatthew G. Knepley pts[c++] = o; 36629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 36639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 36649371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 36659371c9d4SSatish Balay pts[c++] = closure[cl]; 36669371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 36679371c9d4SSatish Balay } 36689566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 36699371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 36709371c9d4SSatish Balay pts[c++] = closure[cl]; 36719371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 36729371c9d4SSatish Balay } 36739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3674b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 36759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3676b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3677b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3678b5a892a1SMatthew G. Knepley } 3679b5a892a1SMatthew G. Knepley if (dim >= 3) { 3680b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3681b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3682b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3683b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3684b5a892a1SMatthew G. Knepley 36859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3686b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 36879566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize)); 36889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, fpoint, &fcone)); 36899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt)); 3690b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3691b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3692b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3693b5a892a1SMatthew G. Knepley 36949371c9d4SSatish Balay for (i = 0; i < c; i += 2) 36959371c9d4SSatish Balay if (pts[i] == cp) break; 3696b5a892a1SMatthew G. Knepley if (i == c) { 36979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3698b5a892a1SMatthew G. Knepley pts[c++] = cp; 3699b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3700b5a892a1SMatthew G. Knepley } 3701b5a892a1SMatthew G. Knepley } 3702b5a892a1SMatthew G. Knepley } 3703b5a892a1SMatthew G. Knepley } 3704b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3705b5a892a1SMatthew G. Knepley *points = pts; 3706b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3707b5a892a1SMatthew G. Knepley } 3708b5a892a1SMatthew G. Knepley 3709d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3710d71ae5a4SJacob Faibussowitsch { 3711b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3712b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3713b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3714b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3715b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3716b5a892a1SMatthew G. Knepley 3717b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 37189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3719b5a892a1SMatthew G. Knepley if (depth == 1) { 37209566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 3721b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3722b5a892a1SMatthew G. Knepley } 37239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3724b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3725b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 37269566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 3727b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3728b5a892a1SMatthew G. Knepley } 37299566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3730b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3731b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3732b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 37339566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 37349371c9d4SSatish Balay if (*points) { 37359371c9d4SSatish Balay closure = *points; 37369371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3737b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3738b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3739b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3740b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3741b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3742b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3743b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3744b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3745b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3746b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 3747b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3748b5a892a1SMatthew G. Knepley const PetscInt *tmp, *tmpO; 3749b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3750b5a892a1SMatthew G. Knepley 3751b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3752b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2; 375363a3b9bcSJacob 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); 3754b5a892a1SMatthew G. Knepley } 3755b5a892a1SMatthew G. Knepley if (useCone) { 37569566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &tmpSize)); 37579566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &tmp)); 37589566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO)); 3759b5a892a1SMatthew G. Knepley } else { 37609566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize)); 37619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &tmp)); 3762b5a892a1SMatthew G. Knepley tmpO = NULL; 3763b5a892a1SMatthew G. Knepley } 3764b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3765b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 3766b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 3767b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 37689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3769b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3770b5a892a1SMatthew G. Knepley PetscInt c; 3771b5a892a1SMatthew G. Knepley 3772b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3773b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3774b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3775b5a892a1SMatthew G. Knepley } 3776b5a892a1SMatthew G. Knepley if (c == closureSize) { 3777b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3778b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3779b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3780b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3781b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3782b5a892a1SMatthew G. Knepley } 3783b5a892a1SMatthew G. Knepley } 3784b5a892a1SMatthew G. Knepley } 37859566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 3786b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 3787b5a892a1SMatthew G. Knepley if (points) *points = closure; 3788b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3789b5a892a1SMatthew G. Knepley } 3790b5a892a1SMatthew G. Knepley 3791552f7358SJed Brown /*@C 3792eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3793552f7358SJed Brown 3794a1cb98faSBarry Smith Not Collective 3795552f7358SJed Brown 3796552f7358SJed Brown Input Parameters: 3797a1cb98faSBarry Smith + dm - The `DMPLEX` 3798b5a892a1SMatthew G. Knepley . p - The mesh point 3799a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 3800552f7358SJed Brown 38016b867d5aSJose E. Roman Input/Output Parameter: 38026b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 38036b867d5aSJose E. Roman if NULL on input, internal storage will be returned, otherwise the provided array is used 38046b867d5aSJose E. Roman 38056b867d5aSJose E. Roman Output Parameter: 38066b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3807552f7358SJed Brown 3808a1cb98faSBarry Smith Level: beginner 3809a1cb98faSBarry Smith 3810552f7358SJed Brown Note: 38110298fd71SBarry Smith If using internal storage (points is NULL on input), each call overwrites the last output. 3812552f7358SJed Brown 38139f22da38SBarry Smith Fortran Note: 3814a1cb98faSBarry Smith The numPoints argument is not present in the Fortran binding since it is internal to the array. 38153813dfbdSMatthew G Knepley 3816a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3817552f7358SJed Brown @*/ 3818d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3819d71ae5a4SJacob Faibussowitsch { 3820b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3821552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3822b5a892a1SMatthew G. Knepley if (numPoints) PetscValidIntPointer(numPoints, 4); 3823b5a892a1SMatthew G. Knepley if (points) PetscValidPointer(points, 5); 38249566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 38259bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 38269bf0dad6SMatthew G. Knepley } 38279bf0dad6SMatthew G. Knepley 3828552f7358SJed Brown /*@C 3829eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3830552f7358SJed Brown 3831a1cb98faSBarry Smith Not Collective 3832552f7358SJed Brown 3833552f7358SJed Brown Input Parameters: 3834a1cb98faSBarry Smith + dm - The `DMPLEX` 3835b5a892a1SMatthew G. Knepley . p - The mesh point 3836a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 3837b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3838b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3839552f7358SJed Brown 3840a1cb98faSBarry Smith Level: beginner 3841a1cb98faSBarry Smith 3842552f7358SJed Brown Note: 38430298fd71SBarry Smith If not using internal storage (points is not NULL on input), this call is unnecessary 3844552f7358SJed Brown 3845a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3846552f7358SJed Brown @*/ 3847d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3848d71ae5a4SJacob Faibussowitsch { 3849b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3850552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38514ff43b2cSJed Brown if (numPoints) *numPoints = 0; 38529566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 3853552f7358SJed Brown PetscFunctionReturn(0); 3854552f7358SJed Brown } 3855552f7358SJed Brown 3856552f7358SJed Brown /*@ 3857eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3858552f7358SJed Brown 3859a1cb98faSBarry Smith Not Collective 3860552f7358SJed Brown 3861552f7358SJed Brown Input Parameter: 3862a1cb98faSBarry Smith . mesh - The `DMPLEX` 3863552f7358SJed Brown 3864552f7358SJed Brown Output Parameters: 3865552f7358SJed Brown + maxConeSize - The maximum number of in-edges 3866552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 3867552f7358SJed Brown 3868552f7358SJed Brown Level: beginner 3869552f7358SJed Brown 3870a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3871552f7358SJed Brown @*/ 3872d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3873d71ae5a4SJacob Faibussowitsch { 3874552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3875552f7358SJed Brown 3876552f7358SJed Brown PetscFunctionBegin; 3877552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38781baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 38791baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 3880552f7358SJed Brown PetscFunctionReturn(0); 3881552f7358SJed Brown } 3882552f7358SJed Brown 3883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 3884d71ae5a4SJacob Faibussowitsch { 3885552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 38866302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 3887552f7358SJed Brown 3888552f7358SJed Brown PetscFunctionBegin; 3889552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 38919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 38929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 38939566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 38946302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 38956302a7fbSVaclav Hapla if (maxSupportSize) { 38969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 38979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 38989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 3899552f7358SJed Brown } 3900552f7358SJed Brown PetscFunctionReturn(0); 3901552f7358SJed Brown } 3902552f7358SJed Brown 3903d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3904d71ae5a4SJacob Faibussowitsch { 3905552f7358SJed Brown PetscFunctionBegin; 39069566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 39079566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 3908ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 3909736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 391095602cf2SAlexis Marboeuf PetscSF sfNatural; 3911f94b4a02SBlaise Bourdin 39123dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 39139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 391495602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 3915c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 3916f94b4a02SBlaise Bourdin } 3917552f7358SJed Brown PetscFunctionReturn(0); 3918552f7358SJed Brown } 3919552f7358SJed Brown 3920d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3921d71ae5a4SJacob Faibussowitsch { 39223dcd263cSBlaise Bourdin PetscInt i = 0; 39232adcc780SMatthew G. Knepley 39242adcc780SMatthew G. Knepley PetscFunctionBegin; 39259566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 39269566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 3927c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 39283dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 39293dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 393095602cf2SAlexis Marboeuf PetscSF sfNatural; 39313dcd263cSBlaise Bourdin 39323dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 39339566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 3934c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 393595602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 3936c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 39373dcd263cSBlaise Bourdin break; 39383dcd263cSBlaise Bourdin } 39393dcd263cSBlaise Bourdin } 39402adcc780SMatthew G. Knepley PetscFunctionReturn(0); 39412adcc780SMatthew G. Knepley } 39422adcc780SMatthew G. Knepley 3943552f7358SJed Brown /*@ 3944eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3945552f7358SJed Brown 3946a1cb98faSBarry Smith Not Collective 3947552f7358SJed Brown 3948552f7358SJed Brown Input Parameter: 3949a1cb98faSBarry Smith . mesh - The `DMPLEX` 3950552f7358SJed Brown 3951552f7358SJed Brown Level: beginner 3952552f7358SJed Brown 3953a1cb98faSBarry Smith Note: 3954a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 3955a1cb98faSBarry Smith 3956a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 3957552f7358SJed Brown @*/ 3958d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 3959d71ae5a4SJacob Faibussowitsch { 3960552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3961552f7358SJed Brown PetscInt *offsets; 3962552f7358SJed Brown PetscInt supportSize; 3963552f7358SJed Brown PetscInt pStart, pEnd, p; 3964552f7358SJed Brown 3965552f7358SJed Brown PetscFunctionBegin; 3966552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 396728b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 39689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 3969552f7358SJed Brown /* Calculate support sizes */ 39709566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3971552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3972552f7358SJed Brown PetscInt dof, off, c; 3973552f7358SJed Brown 39749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 39759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 397648a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 3977552f7358SJed Brown } 39789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 3979552f7358SJed Brown /* Calculate supports */ 39809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 39819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 39829566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 3983552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3984552f7358SJed Brown PetscInt dof, off, c; 3985552f7358SJed Brown 39869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 39879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3988552f7358SJed Brown for (c = off; c < off + dof; ++c) { 3989552f7358SJed Brown const PetscInt q = mesh->cones[c]; 3990552f7358SJed Brown PetscInt offS; 3991552f7358SJed Brown 39929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 39930d644c17SKarl Rupp 3994552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 3995552f7358SJed Brown ++offsets[q]; 3996552f7358SJed Brown } 3997552f7358SJed Brown } 39989566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 39999566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4000552f7358SJed Brown PetscFunctionReturn(0); 4001552f7358SJed Brown } 4002552f7358SJed Brown 4003d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4004d71ae5a4SJacob Faibussowitsch { 4005277ea44aSLisandro Dalcin IS stratumIS; 4006277ea44aSLisandro Dalcin 4007277ea44aSLisandro Dalcin PetscFunctionBegin; 4008277ea44aSLisandro Dalcin if (pStart >= pEnd) PetscFunctionReturn(0); 400976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4010277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4011277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 40129566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4013277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 40149566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 40159371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 40169371c9d4SSatish Balay overlap = PETSC_TRUE; 40179371c9d4SSatish Balay break; 40189371c9d4SSatish Balay } 4019277ea44aSLisandro Dalcin } 402063a3b9bcSJacob 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); 4021277ea44aSLisandro Dalcin } 40229566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 40239566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 40249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 4025277ea44aSLisandro Dalcin PetscFunctionReturn(0); 4026277ea44aSLisandro Dalcin } 4027277ea44aSLisandro Dalcin 4028552f7358SJed Brown /*@ 4029a8d69d7bSBarry Smith DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 40306dd80730SBarry Smith can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 4031552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 4032552f7358SJed Brown the DAG. 4033552f7358SJed Brown 4034bf4602e4SToby Isaac Collective on dm 4035552f7358SJed Brown 4036552f7358SJed Brown Input Parameter: 4037a1cb98faSBarry Smith . mesh - The `DMPLEX` 4038552f7358SJed Brown 4039a1cb98faSBarry Smith Level: beginner 4040552f7358SJed Brown 4041552f7358SJed Brown Notes: 4042a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4043b1bb481bSMatthew 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 4044a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4045a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4046a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4047552f7358SJed Brown 4048b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4049b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4050b1bb481bSMatthew 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 4051b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4052a1cb98faSBarry Smith .vb 4053a1cb98faSBarry Smith cone(c0) = {e0, v2} 4054a1cb98faSBarry Smith cone(e0) = {v0, v1} 4055a1cb98faSBarry Smith .ve 4056a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4057a1cb98faSBarry Smith .vb 4058a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4059a1cb98faSBarry Smith depth 1 = {e0, c0} 4060a1cb98faSBarry Smith .ve 4061b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4062b1bb481bSMatthew Knepley 4063a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4064552f7358SJed Brown 4065a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4066552f7358SJed Brown @*/ 4067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4068d71ae5a4SJacob Faibussowitsch { 4069df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4070aa50250dSMatthew G. Knepley DMLabel label; 4071552f7358SJed Brown PetscInt pStart, pEnd, p; 4072552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 4073552f7358SJed Brown 4074552f7358SJed Brown PetscFunctionBegin; 4075552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40769566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4077277ea44aSLisandro Dalcin 4078277ea44aSLisandro Dalcin /* Create depth label */ 40799566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 40809566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 40819566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4082277ea44aSLisandro Dalcin 4083277ea44aSLisandro Dalcin { 4084552f7358SJed Brown /* Initialize roots and count leaves */ 4085277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4086277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 4087552f7358SJed Brown PetscInt coneSize, supportSize; 4088552f7358SJed Brown 4089277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 40909566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 40919566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4092552f7358SJed Brown if (!coneSize && supportSize) { 4093277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4094277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4095552f7358SJed Brown ++numRoots; 4096552f7358SJed Brown } else if (!supportSize && coneSize) { 4097552f7358SJed Brown ++numLeaves; 4098552f7358SJed Brown } else if (!supportSize && !coneSize) { 4099552f7358SJed Brown /* Isolated points */ 4100277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4101277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4102552f7358SJed Brown } 4103552f7358SJed Brown } 41049566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4105277ea44aSLisandro Dalcin } 4106277ea44aSLisandro Dalcin 4107552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 4108277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4109277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 4110552f7358SJed Brown PetscInt coneSize, supportSize; 4111552f7358SJed Brown 4112277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 41139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 41149566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4115552f7358SJed Brown if (!supportSize && coneSize) { 4116277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4117277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4118552f7358SJed Brown } 4119552f7358SJed Brown } 41209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4121552f7358SJed Brown } else { 4122277ea44aSLisandro Dalcin PetscInt level = 0; 4123277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 4124552f7358SJed Brown 41259566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4126277ea44aSLisandro Dalcin while (qEnd > qStart) { 4127277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4128277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 412974ef644bSMatthew G. Knepley 4130277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 413174ef644bSMatthew G. Knepley const PetscInt *support; 413274ef644bSMatthew G. Knepley PetscInt supportSize, s; 413374ef644bSMatthew G. Knepley 41349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 41359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &support)); 413674ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 4137277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 4138277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 4139552f7358SJed Brown } 4140552f7358SJed Brown } 41419566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &level)); 41429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 41439566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 414474ef644bSMatthew G. Knepley } 414574ef644bSMatthew G. Knepley } 4146bf4602e4SToby Isaac { /* just in case there is an empty process */ 4147bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4148bf4602e4SToby Isaac 41499566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 41509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 415148a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4152bf4602e4SToby Isaac } 41539566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 41549566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 4155552f7358SJed Brown PetscFunctionReturn(0); 4156552f7358SJed Brown } 4157552f7358SJed Brown 4158d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4159d71ae5a4SJacob Faibussowitsch { 4160412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4161412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4162ba2698f1SMatthew G. Knepley 4163412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 41649566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 41659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 41669566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4167ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4168ba2698f1SMatthew G. Knepley if (depth <= 1) { 4169ba2698f1SMatthew G. Knepley switch (pdepth) { 4170d71ae5a4SJacob Faibussowitsch case 0: 4171d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4172d71ae5a4SJacob Faibussowitsch break; 4173ba2698f1SMatthew G. Knepley case 1: 4174ba2698f1SMatthew G. Knepley switch (coneSize) { 4175d71ae5a4SJacob Faibussowitsch case 2: 4176d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4177d71ae5a4SJacob Faibussowitsch break; 4178d71ae5a4SJacob Faibussowitsch case 3: 4179d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4180d71ae5a4SJacob Faibussowitsch break; 4181ba2698f1SMatthew G. Knepley case 4: 4182ba2698f1SMatthew G. Knepley switch (dim) { 4183d71ae5a4SJacob Faibussowitsch case 2: 4184d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4185d71ae5a4SJacob Faibussowitsch break; 4186d71ae5a4SJacob Faibussowitsch case 3: 4187d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4188d71ae5a4SJacob Faibussowitsch break; 4189d71ae5a4SJacob Faibussowitsch default: 4190d71ae5a4SJacob Faibussowitsch break; 4191ba2698f1SMatthew G. Knepley } 4192ba2698f1SMatthew G. Knepley break; 4193d71ae5a4SJacob Faibussowitsch case 5: 4194d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4195d71ae5a4SJacob Faibussowitsch break; 4196d71ae5a4SJacob Faibussowitsch case 6: 4197d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4198d71ae5a4SJacob Faibussowitsch break; 4199d71ae5a4SJacob Faibussowitsch case 8: 4200d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4201d71ae5a4SJacob Faibussowitsch break; 4202d71ae5a4SJacob Faibussowitsch default: 4203d71ae5a4SJacob Faibussowitsch break; 4204ba2698f1SMatthew G. Knepley } 4205ba2698f1SMatthew G. Knepley } 4206ba2698f1SMatthew G. Knepley } else { 4207ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4208ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4209ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4210ba2698f1SMatthew G. Knepley switch (dim) { 4211ba2698f1SMatthew G. Knepley case 1: 4212ba2698f1SMatthew G. Knepley switch (coneSize) { 4213d71ae5a4SJacob Faibussowitsch case 2: 4214d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4215d71ae5a4SJacob Faibussowitsch break; 4216d71ae5a4SJacob Faibussowitsch default: 4217d71ae5a4SJacob Faibussowitsch break; 4218ba2698f1SMatthew G. Knepley } 4219ba2698f1SMatthew G. Knepley break; 4220ba2698f1SMatthew G. Knepley case 2: 4221ba2698f1SMatthew G. Knepley switch (coneSize) { 4222d71ae5a4SJacob Faibussowitsch case 3: 4223d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4224d71ae5a4SJacob Faibussowitsch break; 4225d71ae5a4SJacob Faibussowitsch case 4: 4226d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4227d71ae5a4SJacob Faibussowitsch break; 4228d71ae5a4SJacob Faibussowitsch default: 4229d71ae5a4SJacob Faibussowitsch break; 4230ba2698f1SMatthew G. Knepley } 4231ba2698f1SMatthew G. Knepley break; 4232ba2698f1SMatthew G. Knepley case 3: 4233ba2698f1SMatthew G. Knepley switch (coneSize) { 4234d71ae5a4SJacob Faibussowitsch case 4: 4235d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4236d71ae5a4SJacob Faibussowitsch break; 42379371c9d4SSatish Balay case 5: { 4238da9060c4SMatthew G. Knepley const PetscInt *cone; 4239da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4240da9060c4SMatthew G. Knepley 42419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 42429566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4243da9060c4SMatthew G. Knepley switch (faceConeSize) { 4244d71ae5a4SJacob Faibussowitsch case 3: 4245d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4246d71ae5a4SJacob Faibussowitsch break; 4247d71ae5a4SJacob Faibussowitsch case 4: 4248d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4249d71ae5a4SJacob Faibussowitsch break; 4250da9060c4SMatthew G. Knepley } 42519371c9d4SSatish Balay } break; 4252d71ae5a4SJacob Faibussowitsch case 6: 4253d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4254d71ae5a4SJacob Faibussowitsch break; 4255d71ae5a4SJacob Faibussowitsch default: 4256d71ae5a4SJacob Faibussowitsch break; 4257ba2698f1SMatthew G. Knepley } 4258ba2698f1SMatthew G. Knepley break; 4259d71ae5a4SJacob Faibussowitsch default: 4260d71ae5a4SJacob Faibussowitsch break; 4261ba2698f1SMatthew G. Knepley } 4262ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4263ba2698f1SMatthew G. Knepley switch (coneSize) { 4264d71ae5a4SJacob Faibussowitsch case 2: 4265d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4266d71ae5a4SJacob Faibussowitsch break; 4267d71ae5a4SJacob Faibussowitsch case 3: 4268d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4269d71ae5a4SJacob Faibussowitsch break; 4270d71ae5a4SJacob Faibussowitsch case 4: 4271d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4272d71ae5a4SJacob Faibussowitsch break; 4273d71ae5a4SJacob Faibussowitsch default: 4274d71ae5a4SJacob Faibussowitsch break; 4275ba2698f1SMatthew G. Knepley } 4276ba2698f1SMatthew G. Knepley } 4277ba2698f1SMatthew G. Knepley } 4278412e9a14SMatthew G. Knepley *pt = ct; 4279412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4280ba2698f1SMatthew G. Knepley } 4281412e9a14SMatthew G. Knepley 4282412e9a14SMatthew G. Knepley /*@ 4283412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4284412e9a14SMatthew G. Knepley 4285412e9a14SMatthew G. Knepley Collective on dm 4286412e9a14SMatthew G. Knepley 4287412e9a14SMatthew G. Knepley Input Parameter: 4288a1cb98faSBarry Smith . mesh - The `DMPLEX` 4289412e9a14SMatthew G. Knepley 4290412e9a14SMatthew G. Knepley Level: developer 4291412e9a14SMatthew G. Knepley 4292a1cb98faSBarry Smith Note: 4293a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4294a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4295a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4296412e9a14SMatthew G. Knepley 4297a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4298a1cb98faSBarry Smith 4299a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4300412e9a14SMatthew G. Knepley @*/ 4301d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4302d71ae5a4SJacob Faibussowitsch { 4303412e9a14SMatthew G. Knepley DM_Plex *mesh; 4304412e9a14SMatthew G. Knepley DMLabel ctLabel; 4305412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4306412e9a14SMatthew G. Knepley 4307412e9a14SMatthew G. Knepley PetscFunctionBegin; 4308412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4309412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 43109566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 43119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 43129566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4313412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4314327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4315412e9a14SMatthew G. Knepley PetscInt pdepth; 4316412e9a14SMatthew G. Knepley 43179566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 43189566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 431963a3b9bcSJacob Faibussowitsch PetscCheck(ct != DM_POLYTOPE_UNKNOWN, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 43209566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 4321412e9a14SMatthew G. Knepley } 43229566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 43239566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 4324ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4325ba2698f1SMatthew G. Knepley } 4326ba2698f1SMatthew G. Knepley 4327552f7358SJed Brown /*@C 4328552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4329552f7358SJed Brown 4330552f7358SJed Brown Not Collective 4331552f7358SJed Brown 4332552f7358SJed Brown Input Parameters: 4333a1cb98faSBarry Smith + dm - The `DMPLEX` object 4334552f7358SJed Brown . numPoints - The number of input points for the join 4335552f7358SJed Brown - points - The input points 4336552f7358SJed Brown 4337552f7358SJed Brown Output Parameters: 4338552f7358SJed Brown + numCoveredPoints - The number of points in the join 4339552f7358SJed Brown - coveredPoints - The points in the join 4340552f7358SJed Brown 4341552f7358SJed Brown Level: intermediate 4342552f7358SJed Brown 4343a1cb98faSBarry Smith Note: 4344a1cb98faSBarry Smith Currently, this is restricted to a single level join 4345552f7358SJed Brown 4346a1cb98faSBarry Smith Fortran Note: 4347a1cb98faSBarry Smith The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array. 43483813dfbdSMatthew G Knepley 4349a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4350552f7358SJed Brown @*/ 4351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4352d71ae5a4SJacob Faibussowitsch { 4353552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4354552f7358SJed Brown PetscInt *join[2]; 4355552f7358SJed Brown PetscInt joinSize, i = 0; 4356552f7358SJed Brown PetscInt dof, off, p, c, m; 43576302a7fbSVaclav Hapla PetscInt maxSupportSize; 4358552f7358SJed Brown 4359552f7358SJed Brown PetscFunctionBegin; 4360552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 436148bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 436248bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 436348bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 43646302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 43656302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 43666302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4367552f7358SJed Brown /* Copy in support of first point */ 43689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 43699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4370ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4371552f7358SJed Brown /* Check each successive support */ 4372552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4373552f7358SJed Brown PetscInt newJoinSize = 0; 4374552f7358SJed Brown 43759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 43769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4377552f7358SJed Brown for (c = 0; c < dof; ++c) { 4378552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4379552f7358SJed Brown 4380552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4381552f7358SJed Brown if (point == join[i][m]) { 4382552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4383552f7358SJed Brown break; 4384552f7358SJed Brown } 4385552f7358SJed Brown } 4386552f7358SJed Brown } 4387552f7358SJed Brown joinSize = newJoinSize; 4388552f7358SJed Brown i = 1 - i; 4389552f7358SJed Brown } 4390552f7358SJed Brown *numCoveredPoints = joinSize; 4391552f7358SJed Brown *coveredPoints = join[i]; 43926302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 4393552f7358SJed Brown PetscFunctionReturn(0); 4394552f7358SJed Brown } 4395552f7358SJed Brown 4396552f7358SJed Brown /*@C 4397552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4398552f7358SJed Brown 4399552f7358SJed Brown Not Collective 4400552f7358SJed Brown 4401552f7358SJed Brown Input Parameters: 4402a1cb98faSBarry Smith + dm - The `DMPLEX` object 4403552f7358SJed Brown . numPoints - The number of input points for the join 4404552f7358SJed Brown - points - The input points 4405552f7358SJed Brown 4406552f7358SJed Brown Output Parameters: 4407552f7358SJed Brown + numCoveredPoints - The number of points in the join 4408552f7358SJed Brown - coveredPoints - The points in the join 4409552f7358SJed Brown 4410552f7358SJed Brown Level: intermediate 4411552f7358SJed Brown 4412a1cb98faSBarry Smith Fortran Note: 4413a1cb98faSBarry Smith The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array. 4414a1cb98faSBarry Smith 4415a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4416552f7358SJed Brown @*/ 4417d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4418d71ae5a4SJacob Faibussowitsch { 4419552f7358SJed Brown PetscFunctionBegin; 4420552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4421d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points, 3); 4422d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4); 4423d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 44249566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4425d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4426552f7358SJed Brown PetscFunctionReturn(0); 4427552f7358SJed Brown } 4428552f7358SJed Brown 4429552f7358SJed Brown /*@C 4430552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4431552f7358SJed Brown 4432552f7358SJed Brown Not Collective 4433552f7358SJed Brown 4434552f7358SJed Brown Input Parameters: 4435a1cb98faSBarry Smith + dm - The `DMPLEX` object 4436552f7358SJed Brown . numPoints - The number of input points for the join 4437552f7358SJed Brown - points - The input points 4438552f7358SJed Brown 4439552f7358SJed Brown Output Parameters: 4440552f7358SJed Brown + numCoveredPoints - The number of points in the join 4441552f7358SJed Brown - coveredPoints - The points in the join 4442552f7358SJed Brown 4443552f7358SJed Brown Level: intermediate 4444552f7358SJed Brown 4445a1cb98faSBarry Smith Fortran Note: 4446a1cb98faSBarry Smith The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array. 4447a1cb98faSBarry Smith 4448a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4449552f7358SJed Brown @*/ 4450d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4451d71ae5a4SJacob Faibussowitsch { 4452552f7358SJed Brown PetscInt *offsets, **closures; 4453552f7358SJed Brown PetscInt *join[2]; 4454552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 445524c766afSToby Isaac PetscInt p, d, c, m, ms; 4456552f7358SJed Brown 4457552f7358SJed Brown PetscFunctionBegin; 4458552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 445948bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 446048bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 446148bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 4462552f7358SJed Brown 44639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 44649566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 44659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 44666302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 446724c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 44689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 44699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4470552f7358SJed Brown 4471552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4472552f7358SJed Brown PetscInt closureSize; 4473552f7358SJed Brown 44749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 44750d644c17SKarl Rupp 4476552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4477552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4478552f7358SJed Brown PetscInt pStart, pEnd, i; 4479552f7358SJed Brown 44809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4481552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4482552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4483552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4484552f7358SJed Brown break; 4485552f7358SJed Brown } 4486552f7358SJed Brown } 4487552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4488552f7358SJed Brown } 448963a3b9bcSJacob 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); 4490552f7358SJed Brown } 4491552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4492552f7358SJed Brown PetscInt dof; 4493552f7358SJed Brown 4494552f7358SJed Brown /* Copy in support of first point */ 4495552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4496ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4497552f7358SJed Brown /* Check each successive cone */ 4498552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4499552f7358SJed Brown PetscInt newJoinSize = 0; 4500552f7358SJed Brown 4501552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4502552f7358SJed Brown for (c = 0; c < dof; ++c) { 4503552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4504552f7358SJed Brown 4505552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4506552f7358SJed Brown if (point == join[i][m]) { 4507552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4508552f7358SJed Brown break; 4509552f7358SJed Brown } 4510552f7358SJed Brown } 4511552f7358SJed Brown } 4512552f7358SJed Brown joinSize = newJoinSize; 4513552f7358SJed Brown i = 1 - i; 4514552f7358SJed Brown } 4515552f7358SJed Brown if (joinSize) break; 4516552f7358SJed Brown } 4517552f7358SJed Brown *numCoveredPoints = joinSize; 4518552f7358SJed Brown *coveredPoints = join[i]; 451948a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 45209566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 45219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 45226302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 4523552f7358SJed Brown PetscFunctionReturn(0); 4524552f7358SJed Brown } 4525552f7358SJed Brown 4526552f7358SJed Brown /*@C 4527552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4528552f7358SJed Brown 4529552f7358SJed Brown Not Collective 4530552f7358SJed Brown 4531552f7358SJed Brown Input Parameters: 4532a1cb98faSBarry Smith + dm - The `DMPLEX` object 4533552f7358SJed Brown . numPoints - The number of input points for the meet 4534552f7358SJed Brown - points - The input points 4535552f7358SJed Brown 4536552f7358SJed Brown Output Parameters: 4537552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4538552f7358SJed Brown - coveredPoints - The points in the meet 4539552f7358SJed Brown 4540552f7358SJed Brown Level: intermediate 4541552f7358SJed Brown 4542a1cb98faSBarry Smith Note: 4543a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4544552f7358SJed Brown 45453813dfbdSMatthew G Knepley Fortran Notes: 4546a1cb98faSBarry Smith The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array. 45473813dfbdSMatthew G Knepley 4548a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4549552f7358SJed Brown @*/ 4550d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4551d71ae5a4SJacob Faibussowitsch { 4552552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4553552f7358SJed Brown PetscInt *meet[2]; 4554552f7358SJed Brown PetscInt meetSize, i = 0; 4555552f7358SJed Brown PetscInt dof, off, p, c, m; 45566302a7fbSVaclav Hapla PetscInt maxConeSize; 4557552f7358SJed Brown 4558552f7358SJed Brown PetscFunctionBegin; 4559552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4560dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4561dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveringPoints, 4); 4562064a246eSJacob Faibussowitsch PetscValidPointer(coveringPoints, 5); 45636302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 45646302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 45656302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4566552f7358SJed Brown /* Copy in cone of first point */ 45679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 45689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4569ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4570552f7358SJed Brown /* Check each successive cone */ 4571552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4572552f7358SJed Brown PetscInt newMeetSize = 0; 4573552f7358SJed Brown 45749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 45759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4576552f7358SJed Brown for (c = 0; c < dof; ++c) { 4577552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4578552f7358SJed Brown 4579552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4580552f7358SJed Brown if (point == meet[i][m]) { 4581552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4582552f7358SJed Brown break; 4583552f7358SJed Brown } 4584552f7358SJed Brown } 4585552f7358SJed Brown } 4586552f7358SJed Brown meetSize = newMeetSize; 4587552f7358SJed Brown i = 1 - i; 4588552f7358SJed Brown } 4589552f7358SJed Brown *numCoveringPoints = meetSize; 4590552f7358SJed Brown *coveringPoints = meet[i]; 45916302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 4592552f7358SJed Brown PetscFunctionReturn(0); 4593552f7358SJed Brown } 4594552f7358SJed Brown 4595552f7358SJed Brown /*@C 4596552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4597552f7358SJed Brown 4598552f7358SJed Brown Not Collective 4599552f7358SJed Brown 4600552f7358SJed Brown Input Parameters: 4601a1cb98faSBarry Smith + dm - The `DMPLEX` object 4602552f7358SJed Brown . numPoints - The number of input points for the meet 4603552f7358SJed Brown - points - The input points 4604552f7358SJed Brown 4605552f7358SJed Brown Output Parameters: 4606552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4607552f7358SJed Brown - coveredPoints - The points in the meet 4608552f7358SJed Brown 4609552f7358SJed Brown Level: intermediate 4610552f7358SJed Brown 4611a1cb98faSBarry Smith Fortran Note: 4612a1cb98faSBarry Smith The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array. 46133813dfbdSMatthew G Knepley 4614a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4615552f7358SJed Brown @*/ 4616d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4617d71ae5a4SJacob Faibussowitsch { 4618552f7358SJed Brown PetscFunctionBegin; 4619552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4620d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points, 3); 4621d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4); 4622d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 46239566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4624d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4625552f7358SJed Brown PetscFunctionReturn(0); 4626552f7358SJed Brown } 4627552f7358SJed Brown 4628552f7358SJed Brown /*@C 4629552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4630552f7358SJed Brown 4631552f7358SJed Brown Not Collective 4632552f7358SJed Brown 4633552f7358SJed Brown Input Parameters: 4634a1cb98faSBarry Smith + dm - The `DMPLEX` object 4635552f7358SJed Brown . numPoints - The number of input points for the meet 4636552f7358SJed Brown - points - The input points 4637552f7358SJed Brown 4638552f7358SJed Brown Output Parameters: 4639552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4640552f7358SJed Brown - coveredPoints - The points in the meet 4641552f7358SJed Brown 4642552f7358SJed Brown Level: intermediate 4643552f7358SJed Brown 4644a1cb98faSBarry Smith Fortran Note: 4645a1cb98faSBarry Smith The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array. 46463813dfbdSMatthew G Knepley 4647a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4648552f7358SJed Brown @*/ 4649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4650d71ae5a4SJacob Faibussowitsch { 4651552f7358SJed Brown PetscInt *offsets, **closures; 4652552f7358SJed Brown PetscInt *meet[2]; 4653552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 465424c766afSToby Isaac PetscInt p, h, c, m, mc; 4655552f7358SJed Brown 4656552f7358SJed Brown PetscFunctionBegin; 4657552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4658dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4659dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveredPoints, 4); 4660064a246eSJacob Faibussowitsch PetscValidPointer(coveredPoints, 5); 4661552f7358SJed Brown 46629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 46639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 46649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 46656302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 466624c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 46679566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 46689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4669552f7358SJed Brown 4670552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4671552f7358SJed Brown PetscInt closureSize; 4672552f7358SJed Brown 46739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 46740d644c17SKarl Rupp 4675552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4676552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4677552f7358SJed Brown PetscInt pStart, pEnd, i; 4678552f7358SJed Brown 46799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4680552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4681552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4682552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4683552f7358SJed Brown break; 4684552f7358SJed Brown } 4685552f7358SJed Brown } 4686552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4687552f7358SJed Brown } 468863a3b9bcSJacob 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); 4689552f7358SJed Brown } 4690552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4691552f7358SJed Brown PetscInt dof; 4692552f7358SJed Brown 4693552f7358SJed Brown /* Copy in cone of first point */ 4694552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 4695ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 4696552f7358SJed Brown /* Check each successive cone */ 4697552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4698552f7358SJed Brown PetscInt newMeetSize = 0; 4699552f7358SJed Brown 4700552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 4701552f7358SJed Brown for (c = 0; c < dof; ++c) { 4702552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 4703552f7358SJed Brown 4704552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4705552f7358SJed Brown if (point == meet[i][m]) { 4706552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4707552f7358SJed Brown break; 4708552f7358SJed Brown } 4709552f7358SJed Brown } 4710552f7358SJed Brown } 4711552f7358SJed Brown meetSize = newMeetSize; 4712552f7358SJed Brown i = 1 - i; 4713552f7358SJed Brown } 4714552f7358SJed Brown if (meetSize) break; 4715552f7358SJed Brown } 4716552f7358SJed Brown *numCoveredPoints = meetSize; 4717552f7358SJed Brown *coveredPoints = meet[i]; 471848a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 47199566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 47209566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 47216302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 4722552f7358SJed Brown PetscFunctionReturn(0); 4723552f7358SJed Brown } 4724552f7358SJed Brown 47254e3744c5SMatthew G. Knepley /*@C 4726a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 47274e3744c5SMatthew G. Knepley 47284e3744c5SMatthew G. Knepley Not Collective 47294e3744c5SMatthew G. Knepley 47304e3744c5SMatthew G. Knepley Input Parameters: 4731a1cb98faSBarry Smith + dmA - A `DMPLEX` object 4732a1cb98faSBarry Smith - dmB - A `DMPLEX` object 47334e3744c5SMatthew G. Knepley 47344e3744c5SMatthew G. Knepley Output Parameters: 4735a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 47364e3744c5SMatthew G. Knepley 47374e3744c5SMatthew G. Knepley Level: intermediate 47384e3744c5SMatthew G. Knepley 4739a1cb98faSBarry Smith Note: 47403c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 47414e3744c5SMatthew G. Knepley 4742a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 47434e3744c5SMatthew G. Knepley @*/ 4744d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4745d71ae5a4SJacob Faibussowitsch { 47464e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 47474e3744c5SMatthew G. Knepley 47484e3744c5SMatthew G. Knepley PetscFunctionBegin; 47494e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 47504e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4751dadcf809SJacob Faibussowitsch PetscValidBoolPointer(equal, 3); 47524e3744c5SMatthew G. Knepley 47534e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 47549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 47559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 47564e3744c5SMatthew G. Knepley if (depth != depthB) PetscFunctionReturn(0); 47579566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 47589566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 47594e3744c5SMatthew G. Knepley if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 47604e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 47614e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 47624e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 47634e3744c5SMatthew G. Knepley 47649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 47659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 47669566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 47679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 47689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 47699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 47704e3744c5SMatthew G. Knepley if (coneSize != coneSizeB) PetscFunctionReturn(0); 47714e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 47724e3744c5SMatthew G. Knepley if (cone[c] != coneB[c]) PetscFunctionReturn(0); 47734e3744c5SMatthew G. Knepley if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 47744e3744c5SMatthew G. Knepley } 47759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 47769566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 47779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 47789566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 47794e3744c5SMatthew G. Knepley if (supportSize != supportSizeB) PetscFunctionReturn(0); 47804e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 47814e3744c5SMatthew G. Knepley if (support[s] != supportB[s]) PetscFunctionReturn(0); 47824e3744c5SMatthew G. Knepley } 47834e3744c5SMatthew G. Knepley } 47844e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 47854e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 47864e3744c5SMatthew G. Knepley } 47874e3744c5SMatthew G. Knepley 47887cd05799SMatthew G. Knepley /*@C 47897cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 47907cd05799SMatthew G. Knepley 47917cd05799SMatthew G. Knepley Not Collective 47927cd05799SMatthew G. Knepley 47937cd05799SMatthew G. Knepley Input Parameters: 4794a1cb98faSBarry Smith + dm - The `DMPLEX` 47957cd05799SMatthew G. Knepley . cellDim - The cell dimension 47967cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 47977cd05799SMatthew G. Knepley 47987cd05799SMatthew G. Knepley Output Parameters: 47997cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 48007cd05799SMatthew G. Knepley 48017cd05799SMatthew G. Knepley Level: developer 48027cd05799SMatthew G. Knepley 4803a1cb98faSBarry Smith Note: 48047cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 48057cd05799SMatthew G. Knepley 4806a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 48077cd05799SMatthew G. Knepley @*/ 4808d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4809d71ae5a4SJacob Faibussowitsch { 481082f516ccSBarry Smith MPI_Comm comm; 4811552f7358SJed Brown 4812552f7358SJed Brown PetscFunctionBegin; 48139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4814dadcf809SJacob Faibussowitsch PetscValidIntPointer(numFaceVertices, 4); 4815552f7358SJed Brown switch (cellDim) { 4816d71ae5a4SJacob Faibussowitsch case 0: 4817d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 4818d71ae5a4SJacob Faibussowitsch break; 4819d71ae5a4SJacob Faibussowitsch case 1: 4820d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 4821d71ae5a4SJacob Faibussowitsch break; 4822552f7358SJed Brown case 2: 4823552f7358SJed Brown switch (numCorners) { 482419436ca2SJed Brown case 3: /* triangle */ 482519436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4826552f7358SJed Brown break; 482719436ca2SJed Brown case 4: /* quadrilateral */ 482819436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4829552f7358SJed Brown break; 483019436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 483119436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4832552f7358SJed Brown break; 483319436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 483419436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4835552f7358SJed Brown break; 4836d71ae5a4SJacob Faibussowitsch default: 4837d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4838552f7358SJed Brown } 4839552f7358SJed Brown break; 4840552f7358SJed Brown case 3: 4841552f7358SJed Brown switch (numCorners) { 484219436ca2SJed Brown case 4: /* tetradehdron */ 484319436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 4844552f7358SJed Brown break; 484519436ca2SJed Brown case 6: /* tet cohesive cells */ 484619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4847552f7358SJed Brown break; 484819436ca2SJed Brown case 8: /* hexahedron */ 484919436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4850552f7358SJed Brown break; 485119436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 485219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4853552f7358SJed Brown break; 485419436ca2SJed Brown case 10: /* quadratic tetrahedron */ 485519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4856552f7358SJed Brown break; 485719436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 485819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4859552f7358SJed Brown break; 486019436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 486119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4862552f7358SJed Brown break; 486319436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 486419436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 4865552f7358SJed Brown break; 4866d71ae5a4SJacob Faibussowitsch default: 4867d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4868552f7358SJed Brown } 4869552f7358SJed Brown break; 4870d71ae5a4SJacob Faibussowitsch default: 4871d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 4872552f7358SJed Brown } 4873552f7358SJed Brown PetscFunctionReturn(0); 4874552f7358SJed Brown } 4875552f7358SJed Brown 4876552f7358SJed Brown /*@ 4877a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 4878552f7358SJed Brown 4879552f7358SJed Brown Not Collective 4880552f7358SJed Brown 4881aa50250dSMatthew G. Knepley Input Parameter: 4882a1cb98faSBarry Smith . dm - The `DMPLEX` object 4883552f7358SJed Brown 4884aa50250dSMatthew G. Knepley Output Parameter: 4885a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 4886552f7358SJed Brown 4887552f7358SJed Brown Level: developer 4888552f7358SJed Brown 4889a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 4890aa50250dSMatthew G. Knepley @*/ 4891d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4892d71ae5a4SJacob Faibussowitsch { 4893aa50250dSMatthew G. Knepley PetscFunctionBegin; 4894aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4895aa50250dSMatthew G. Knepley PetscValidPointer(depthLabel, 2); 4896c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 4897aa50250dSMatthew G. Knepley PetscFunctionReturn(0); 4898aa50250dSMatthew G. Knepley } 4899aa50250dSMatthew G. Knepley 4900aa50250dSMatthew G. Knepley /*@ 4901aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 4902aa50250dSMatthew G. Knepley 4903aa50250dSMatthew G. Knepley Not Collective 4904aa50250dSMatthew G. Knepley 4905aa50250dSMatthew G. Knepley Input Parameter: 4906a1cb98faSBarry Smith . dm - The `DMPLEX` object 4907aa50250dSMatthew G. Knepley 4908aa50250dSMatthew G. Knepley Output Parameter: 4909aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 4910aa50250dSMatthew G. Knepley 4911aa50250dSMatthew G. Knepley Level: developer 4912552f7358SJed Brown 4913b1bb481bSMatthew Knepley Notes: 4914a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 4915a1cb98faSBarry Smith 4916a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 4917a1cb98faSBarry Smith 4918dc287ab2SVaclav Hapla An empty mesh gives -1. 4919b1bb481bSMatthew Knepley 4920a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 4921552f7358SJed Brown @*/ 4922d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4923d71ae5a4SJacob Faibussowitsch { 49249f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4925aa50250dSMatthew G. Knepley DMLabel label; 4926aa50250dSMatthew G. Knepley PetscInt d = 0; 4927552f7358SJed Brown 4928552f7358SJed Brown PetscFunctionBegin; 4929552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4930dadcf809SJacob Faibussowitsch PetscValidIntPointer(depth, 2); 49319f4ada15SMatthew G. Knepley if (mesh->tr) { 49329f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 49339f4ada15SMatthew G. Knepley } else { 49349566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 49359566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 4936552f7358SJed Brown *depth = d - 1; 49379f4ada15SMatthew G. Knepley } 4938552f7358SJed Brown PetscFunctionReturn(0); 4939552f7358SJed Brown } 4940552f7358SJed Brown 4941552f7358SJed Brown /*@ 4942552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4943552f7358SJed Brown 4944552f7358SJed Brown Not Collective 4945552f7358SJed Brown 4946552f7358SJed Brown Input Parameters: 4947a1cb98faSBarry Smith + dm - The `DMPLEX` object 4948570fa34dSVaclav Hapla - depth - The requested depth 4949552f7358SJed Brown 4950552f7358SJed Brown Output Parameters: 4951552f7358SJed Brown + start - The first point at this depth 4952552f7358SJed Brown - end - One beyond the last point at this depth 4953552f7358SJed Brown 4954552f7358SJed Brown Level: developer 4955552f7358SJed Brown 4956a1cb98faSBarry Smith Notes: 4957a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4958a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 4959a1cb98faSBarry Smith higher dimension, e.g., "edges". 4960a1cb98faSBarry Smith 4961a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 4962552f7358SJed Brown @*/ 4963d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 4964d71ae5a4SJacob Faibussowitsch { 49659f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4966aa50250dSMatthew G. Knepley DMLabel label; 496763d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 4968552f7358SJed Brown 4969552f7358SJed Brown PetscFunctionBegin; 4970552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49719371c9d4SSatish Balay if (start) { 49729371c9d4SSatish Balay PetscValidIntPointer(start, 3); 49739371c9d4SSatish Balay *start = 0; 49749371c9d4SSatish Balay } 49759371c9d4SSatish Balay if (end) { 49769371c9d4SSatish Balay PetscValidIntPointer(end, 4); 49779371c9d4SSatish Balay *end = 0; 49789371c9d4SSatish Balay } 49799566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 49800d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4981570fa34dSVaclav Hapla if (depth < 0) { 498263d1a920SMatthew G. Knepley if (start) *start = pStart; 498363d1a920SMatthew G. Knepley if (end) *end = pEnd; 498463d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4985552f7358SJed Brown } 49869f4ada15SMatthew G. Knepley if (mesh->tr) { 49879f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 49889f4ada15SMatthew G. Knepley } else { 49899566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 499028b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4991570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 49929f4ada15SMatthew G. Knepley } 4993552f7358SJed Brown PetscFunctionReturn(0); 4994552f7358SJed Brown } 4995552f7358SJed Brown 4996552f7358SJed Brown /*@ 4997552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4998552f7358SJed Brown 4999552f7358SJed Brown Not Collective 5000552f7358SJed Brown 5001552f7358SJed Brown Input Parameters: 5002a1cb98faSBarry Smith + dm - The `DMPLEX` object 5003570fa34dSVaclav Hapla - height - The requested height 5004552f7358SJed Brown 5005552f7358SJed Brown Output Parameters: 5006552f7358SJed Brown + start - The first point at this height 5007552f7358SJed Brown - end - One beyond the last point at this height 5008552f7358SJed Brown 5009552f7358SJed Brown Level: developer 5010552f7358SJed Brown 5011a1cb98faSBarry Smith Notes: 5012a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5013a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5014a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5015a1cb98faSBarry Smith 5016a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5017552f7358SJed Brown @*/ 5018d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5019d71ae5a4SJacob Faibussowitsch { 5020aa50250dSMatthew G. Knepley DMLabel label; 502163d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5022552f7358SJed Brown 5023552f7358SJed Brown PetscFunctionBegin; 5024552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50259371c9d4SSatish Balay if (start) { 50269371c9d4SSatish Balay PetscValidIntPointer(start, 3); 50279371c9d4SSatish Balay *start = 0; 50289371c9d4SSatish Balay } 50299371c9d4SSatish Balay if (end) { 50309371c9d4SSatish Balay PetscValidIntPointer(end, 4); 50319371c9d4SSatish Balay *end = 0; 50329371c9d4SSatish Balay } 50339566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 50340d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 5035570fa34dSVaclav Hapla if (height < 0) { 503663d1a920SMatthew G. Knepley if (start) *start = pStart; 503763d1a920SMatthew G. Knepley if (end) *end = pEnd; 503863d1a920SMatthew G. Knepley PetscFunctionReturn(0); 5039552f7358SJed Brown } 50409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 504128b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 50429566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 5043570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth - 1 - height, start, end)); 5044552f7358SJed Brown PetscFunctionReturn(0); 5045552f7358SJed Brown } 5046552f7358SJed Brown 5047ba2698f1SMatthew G. Knepley /*@ 5048ba2698f1SMatthew G. Knepley DMPlexGetPointDepth - Get the depth of a given point 5049ba2698f1SMatthew G. Knepley 5050ba2698f1SMatthew G. Knepley Not Collective 5051ba2698f1SMatthew G. Knepley 5052d8d19677SJose E. Roman Input Parameters: 5053a1cb98faSBarry Smith + dm - The `DMPLEX` object 5054ba2698f1SMatthew G. Knepley - point - The point 5055ba2698f1SMatthew G. Knepley 5056ba2698f1SMatthew G. Knepley Output Parameter: 5057ba2698f1SMatthew G. Knepley . depth - The depth of the point 5058ba2698f1SMatthew G. Knepley 5059ba2698f1SMatthew G. Knepley Level: intermediate 5060ba2698f1SMatthew G. Knepley 5061a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5062ba2698f1SMatthew G. Knepley @*/ 5063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5064d71ae5a4SJacob Faibussowitsch { 5065ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5066ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 506740a2aa30SMatthew G. Knepley PetscValidIntPointer(depth, 3); 50689566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 5069ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 5070ba2698f1SMatthew G. Knepley } 5071ba2698f1SMatthew G. Knepley 5072ba2698f1SMatthew G. Knepley /*@ 50730c0a32dcSVaclav Hapla DMPlexGetPointHeight - Get the height of a given point 50740c0a32dcSVaclav Hapla 50750c0a32dcSVaclav Hapla Not Collective 50760c0a32dcSVaclav Hapla 5077d8d19677SJose E. Roman Input Parameters: 5078a1cb98faSBarry Smith + dm - The `DMPLEX` object 50790c0a32dcSVaclav Hapla - point - The point 50800c0a32dcSVaclav Hapla 50810c0a32dcSVaclav Hapla Output Parameter: 50820c0a32dcSVaclav Hapla . height - The height of the point 50830c0a32dcSVaclav Hapla 50840c0a32dcSVaclav Hapla Level: intermediate 50850c0a32dcSVaclav Hapla 5086a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 50870c0a32dcSVaclav Hapla @*/ 5088d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5089d71ae5a4SJacob Faibussowitsch { 50900c0a32dcSVaclav Hapla PetscInt n, pDepth; 50910c0a32dcSVaclav Hapla 50920c0a32dcSVaclav Hapla PetscFunctionBegin; 50930c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50940c0a32dcSVaclav Hapla PetscValidIntPointer(height, 3); 50959566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 50969566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 50970c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 50980c0a32dcSVaclav Hapla PetscFunctionReturn(0); 50990c0a32dcSVaclav Hapla } 51000c0a32dcSVaclav Hapla 51010c0a32dcSVaclav Hapla /*@ 5102a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5103ba2698f1SMatthew G. Knepley 5104ba2698f1SMatthew G. Knepley Not Collective 5105ba2698f1SMatthew G. Knepley 5106ba2698f1SMatthew G. Knepley Input Parameter: 5107a1cb98faSBarry Smith . dm - The `DMPLEX` object 5108ba2698f1SMatthew G. Knepley 5109ba2698f1SMatthew G. Knepley Output Parameter: 5110a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5111412e9a14SMatthew G. Knepley 5112ba2698f1SMatthew G. Knepley Level: developer 5113ba2698f1SMatthew G. Knepley 5114a1cb98faSBarry Smith Note: 5115a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5116a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5117a1cb98faSBarry Smith 5118a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5119ba2698f1SMatthew G. Knepley @*/ 5120d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5121d71ae5a4SJacob Faibussowitsch { 5122ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5123ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5124ba2698f1SMatthew G. Knepley PetscValidPointer(celltypeLabel, 2); 51259566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5126ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 5127ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 5128ba2698f1SMatthew G. Knepley } 5129ba2698f1SMatthew G. Knepley 5130ba2698f1SMatthew G. Knepley /*@ 5131ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5132ba2698f1SMatthew G. Knepley 5133ba2698f1SMatthew G. Knepley Not Collective 5134ba2698f1SMatthew G. Knepley 5135d8d19677SJose E. Roman Input Parameters: 5136a1cb98faSBarry Smith + dm - The `DMPLEX` object 5137ba2698f1SMatthew G. Knepley - cell - The cell 5138ba2698f1SMatthew G. Knepley 5139ba2698f1SMatthew G. Knepley Output Parameter: 5140ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5141ba2698f1SMatthew G. Knepley 5142ba2698f1SMatthew G. Knepley Level: intermediate 5143ba2698f1SMatthew G. Knepley 5144a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5145ba2698f1SMatthew G. Knepley @*/ 5146d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5147d71ae5a4SJacob Faibussowitsch { 51489f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5149ba2698f1SMatthew G. Knepley DMLabel label; 5150ba2698f1SMatthew G. Knepley PetscInt ct; 5151ba2698f1SMatthew G. Knepley 5152ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5153ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5154ba2698f1SMatthew G. Knepley PetscValidPointer(celltype, 3); 51559f4ada15SMatthew G. Knepley if (mesh->tr) { 51569f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 51579f4ada15SMatthew G. Knepley } else { 51589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 51599566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 516063a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5161ba2698f1SMatthew G. Knepley *celltype = (DMPolytopeType)ct; 51629f4ada15SMatthew G. Knepley } 5163ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 5164ba2698f1SMatthew G. Knepley } 5165ba2698f1SMatthew G. Knepley 5166412e9a14SMatthew G. Knepley /*@ 5167412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5168412e9a14SMatthew G. Knepley 5169412e9a14SMatthew G. Knepley Not Collective 5170412e9a14SMatthew G. Knepley 5171412e9a14SMatthew G. Knepley Input Parameters: 5172a1cb98faSBarry Smith + dm - The `DMPLEX` object 5173412e9a14SMatthew G. Knepley . cell - The cell 5174412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5175412e9a14SMatthew G. Knepley 5176a1cb98faSBarry Smith Level: advanced 5177a1cb98faSBarry Smith 5178a1cb98faSBarry Smith Note: 5179a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5180412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5181412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5182412e9a14SMatthew G. Knepley DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 5183412e9a14SMatthew G. Knepley 5184a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5185412e9a14SMatthew G. Knepley @*/ 5186d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5187d71ae5a4SJacob Faibussowitsch { 5188412e9a14SMatthew G. Knepley DMLabel label; 5189412e9a14SMatthew G. Knepley 5190412e9a14SMatthew G. Knepley PetscFunctionBegin; 5191412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 51939566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 5194412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 5195412e9a14SMatthew G. Knepley } 5196412e9a14SMatthew G. Knepley 5197d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5198d71ae5a4SJacob Faibussowitsch { 5199efe440bfSMatthew G. Knepley PetscSection section, s; 5200efe440bfSMatthew G. Knepley Mat m; 52013e922f36SToby Isaac PetscInt maxHeight; 5202dd4c3f67SMatthew G. Knepley const char *prefix; 5203552f7358SJed Brown 5204552f7358SJed Brown PetscFunctionBegin; 52059566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5206dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5207dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5208dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 52099566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 52109566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 52119566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 52129566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 52139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 52149566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 52159566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 52169566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 52179566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 52189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 52198f4c458bSMatthew G. Knepley 52209566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 52219566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5222dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5223dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 5224552f7358SJed Brown PetscFunctionReturn(0); 5225552f7358SJed Brown } 5226552f7358SJed Brown 5227d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5228d71ae5a4SJacob Faibussowitsch { 52296858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 52306858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5231f19dbd58SToby Isaac 5232f19dbd58SToby Isaac PetscFunctionBegin; 5233f19dbd58SToby Isaac *field = NULL; 52349566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 52359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 52366858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 52376858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5238f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 52396858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 52406858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5241f19dbd58SToby Isaac } 5242f19dbd58SToby Isaac PetscFunctionReturn(0); 5243f19dbd58SToby Isaac } 5244f19dbd58SToby Isaac 52457cd05799SMatthew G. Knepley /*@C 52467cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 52477cd05799SMatthew G. Knepley 52487cd05799SMatthew G. Knepley Not Collective 52497cd05799SMatthew G. Knepley 52507cd05799SMatthew G. Knepley Input Parameters: 5251a1cb98faSBarry Smith . dm - The `DMPLEX` object 52527cd05799SMatthew G. Knepley 52537cd05799SMatthew G. Knepley Output Parameter: 5254a1cb98faSBarry Smith . section - The `PetscSection` object 52557cd05799SMatthew G. Knepley 52567cd05799SMatthew G. Knepley Level: developer 52577cd05799SMatthew G. Knepley 5258a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 52597cd05799SMatthew G. Knepley @*/ 5260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5261d71ae5a4SJacob Faibussowitsch { 5262552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5263552f7358SJed Brown 5264552f7358SJed Brown PetscFunctionBegin; 5265552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5266552f7358SJed Brown if (section) *section = mesh->coneSection; 5267552f7358SJed Brown PetscFunctionReturn(0); 5268552f7358SJed Brown } 5269552f7358SJed Brown 52707cd05799SMatthew G. Knepley /*@C 52717cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 52727cd05799SMatthew G. Knepley 52737cd05799SMatthew G. Knepley Not Collective 52747cd05799SMatthew G. Knepley 52757cd05799SMatthew G. Knepley Input Parameters: 5276a1cb98faSBarry Smith . dm - The `DMPLEX` object 52777cd05799SMatthew G. Knepley 52787cd05799SMatthew G. Knepley Output Parameter: 5279a1cb98faSBarry Smith . section - The `PetscSection` object 52807cd05799SMatthew G. Knepley 52817cd05799SMatthew G. Knepley Level: developer 52827cd05799SMatthew G. Knepley 5283a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 52847cd05799SMatthew G. Knepley @*/ 5285d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5286d71ae5a4SJacob Faibussowitsch { 52878cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 52888cb4d582SMatthew G. Knepley 52898cb4d582SMatthew G. Knepley PetscFunctionBegin; 52908cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52918cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 52928cb4d582SMatthew G. Knepley PetscFunctionReturn(0); 52938cb4d582SMatthew G. Knepley } 52948cb4d582SMatthew G. Knepley 52957cd05799SMatthew G. Knepley /*@C 52967cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 52977cd05799SMatthew G. Knepley 52987cd05799SMatthew G. Knepley Not Collective 52997cd05799SMatthew G. Knepley 53007cd05799SMatthew G. Knepley Input Parameters: 5301a1cb98faSBarry Smith . dm - The `DMPLEX` object 53027cd05799SMatthew G. Knepley 53037cd05799SMatthew G. Knepley Output Parameter: 53047cd05799SMatthew G. Knepley . cones - The cone for each point 53057cd05799SMatthew G. Knepley 53067cd05799SMatthew G. Knepley Level: developer 53077cd05799SMatthew G. Knepley 5308a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 53097cd05799SMatthew G. Knepley @*/ 5310d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5311d71ae5a4SJacob Faibussowitsch { 5312552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5313552f7358SJed Brown 5314552f7358SJed Brown PetscFunctionBegin; 5315552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5316552f7358SJed Brown if (cones) *cones = mesh->cones; 5317552f7358SJed Brown PetscFunctionReturn(0); 5318552f7358SJed Brown } 5319552f7358SJed Brown 53207cd05799SMatthew G. Knepley /*@C 53217cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 53227cd05799SMatthew G. Knepley 53237cd05799SMatthew G. Knepley Not Collective 53247cd05799SMatthew G. Knepley 53257cd05799SMatthew G. Knepley Input Parameters: 5326a1cb98faSBarry Smith . dm - The `DMPLEX` object 53277cd05799SMatthew G. Knepley 53287cd05799SMatthew G. Knepley Output Parameter: 5329b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 53307cd05799SMatthew G. Knepley 53317cd05799SMatthew G. Knepley Level: developer 53327cd05799SMatthew G. Knepley 5333b5a892a1SMatthew G. Knepley Notes: 5334a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5335b5a892a1SMatthew G. Knepley 5336a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5337b5a892a1SMatthew G. Knepley 5338a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 53397cd05799SMatthew G. Knepley @*/ 5340d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5341d71ae5a4SJacob Faibussowitsch { 5342552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5343552f7358SJed Brown 5344552f7358SJed Brown PetscFunctionBegin; 5345552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5346552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5347552f7358SJed Brown PetscFunctionReturn(0); 5348552f7358SJed Brown } 5349552f7358SJed Brown 5350552f7358SJed Brown /******************************** FEM Support **********************************/ 5351552f7358SJed Brown 53529e8305c2SJed Brown /* 53539e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 53549e8305c2SJed Brown representing a line in the section. 53559e8305c2SJed Brown */ 5356d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section, PetscInt field, PetscInt line, PetscBool vertexchart, PetscInt *Nc, PetscInt *k) 5357d71ae5a4SJacob Faibussowitsch { 53589e8305c2SJed Brown PetscFunctionBeginHot; 53599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5360a433471fSStefano Zampini if (line < 0) { 5361a433471fSStefano Zampini *k = 0; 5362a433471fSStefano Zampini *Nc = 0; 5363a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 53649e8305c2SJed Brown *k = 1; 53659e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 53669e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 53679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 53689e8305c2SJed Brown *k = *k / *Nc + 1; 53699e8305c2SJed Brown } 53709e8305c2SJed Brown PetscFunctionReturn(0); 53719e8305c2SJed Brown } 53729e8305c2SJed Brown 5373a4355906SMatthew Knepley /*@ 5374bc1eb3faSJed Brown 5375bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5376bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 53771bb6d2a8SBarry Smith section provided (or the section of the DM). 5378a4355906SMatthew Knepley 5379a4355906SMatthew Knepley Input Parameters: 5380a4355906SMatthew Knepley + dm - The DM 5381a4355906SMatthew Knepley . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5382a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section 5383a4355906SMatthew Knepley 5384bc1eb3faSJed Brown Example: 5385bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5386bc1eb3faSJed Brown .vb 5387bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5388bc1eb3faSJed Brown 5389bc1eb3faSJed Brown v4 -- e6 -- v3 5390bc1eb3faSJed Brown | | 5391bc1eb3faSJed Brown e7 c0 e8 5392bc1eb3faSJed Brown | | 5393bc1eb3faSJed Brown v1 -- e5 -- v2 5394bc1eb3faSJed Brown .ve 5395bc1eb3faSJed Brown 5396bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5397bc1eb3faSJed Brown dofs in the order of points, e.g., 5398bc1eb3faSJed Brown .vb 5399bc1eb3faSJed Brown c0 -> [0,1,2,3] 5400bc1eb3faSJed Brown v1 -> [4] 5401bc1eb3faSJed Brown ... 5402bc1eb3faSJed Brown e5 -> [8, 9] 5403bc1eb3faSJed Brown .ve 5404bc1eb3faSJed Brown 5405bc1eb3faSJed Brown which corresponds to the dofs 5406bc1eb3faSJed Brown .vb 5407bc1eb3faSJed Brown 6 10 11 7 5408bc1eb3faSJed Brown 13 2 3 15 5409bc1eb3faSJed Brown 12 0 1 14 5410bc1eb3faSJed Brown 4 8 9 5 5411bc1eb3faSJed Brown .ve 5412bc1eb3faSJed Brown 5413bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5414bc1eb3faSJed Brown .vb 5415bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5416bc1eb3faSJed Brown .ve 5417bc1eb3faSJed Brown 5418bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5419bc1eb3faSJed Brown .vb 5420bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5421bc1eb3faSJed Brown .ve 5422bc1eb3faSJed Brown 5423a4355906SMatthew Knepley Level: developer 5424a4355906SMatthew Knepley 5425a1cb98faSBarry Smith Note: 5426a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5427a1cb98faSBarry Smith degree of the basis. 5428a1cb98faSBarry Smith 5429a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5430a4355906SMatthew Knepley @*/ 5431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5432d71ae5a4SJacob Faibussowitsch { 54337391a63aSMatthew G. Knepley DMLabel label; 5434bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 54359e8305c2SJed Brown PetscBool vertexchart; 54363194fc30SMatthew G. Knepley 54373194fc30SMatthew G. Knepley PetscFunctionBegin; 54389566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5439a433471fSStefano Zampini if (dim < 1) PetscFunctionReturn(0); 5440a433471fSStefano Zampini if (point < 0) { 5441a433471fSStefano Zampini PetscInt sStart, sEnd; 5442a433471fSStefano Zampini 54439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5444a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5445a433471fSStefano Zampini } 54469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 54479566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 54489566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 54499371c9d4SSatish Balay if (depth == 1) { 54509371c9d4SSatish Balay eStart = point; 54519371c9d4SSatish Balay } else if (depth == dim) { 54527391a63aSMatthew G. Knepley const PetscInt *cone; 54537391a63aSMatthew G. Knepley 54549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5455d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5456d4e6627bSStefano Zampini else if (dim == 3) { 5457d4e6627bSStefano Zampini const PetscInt *cone2; 54589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5459d4e6627bSStefano Zampini eStart = cone2[0]; 546063a3b9bcSJacob 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); 546163a3b9bcSJacob 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); 54629e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 54639e8305c2SJed Brown PetscInt pStart, pEnd, cStart, cEnd; 54649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd)); 54659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &cStart, &cEnd)); 5466796d0a68SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5467796d0a68SJed Brown else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5468796d0a68SJed Brown else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 54699e8305c2SJed Brown } 54709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5471bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5472bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5473bb197d40SJed Brown PetscInt *perm; 5474bb197d40SJed Brown 54753194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 54769566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 5477bb197d40SJed Brown size += PetscPowInt(k + 1, d) * Nc; 54783194fc30SMatthew G. Knepley } 54799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 54803194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5481bb197d40SJed Brown switch (d) { 5482babf31e0SJed Brown case 1: 54839566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 5484babf31e0SJed Brown /* 5485babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5486babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5487babf31e0SJed Brown */ 5488babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 54899371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 54909371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5491babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5492babf31e0SJed Brown foffset = offset; 5493babf31e0SJed Brown break; 549489eabcffSMatthew G. Knepley case 2: 54953194fc30SMatthew 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} */ 54969566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 54973194fc30SMatthew G. Knepley /* The SEM order is 54983194fc30SMatthew G. Knepley 54993194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 550089eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 55013194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 55023194fc30SMatthew G. Knepley */ 55033194fc30SMatthew G. Knepley { 55043194fc30SMatthew G. Knepley const PetscInt of = 0; 55053194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 55063194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 55073194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 55083194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 55093194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 55103194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 55113194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 55123194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 55133194fc30SMatthew G. Knepley PetscInt o; 55143194fc30SMatthew G. Knepley 55153194fc30SMatthew G. Knepley /* bottom */ 55163194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 55179371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 55189371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 55193194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 55203194fc30SMatthew G. Knepley /* middle */ 55213194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 55223194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 55239371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 55249371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 55253194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 55263194fc30SMatthew G. Knepley } 55273194fc30SMatthew G. Knepley /* top */ 55283194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 55299371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 55309371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 55313194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 55323194fc30SMatthew G. Knepley foffset = offset; 55333194fc30SMatthew G. Knepley } 553489eabcffSMatthew G. Knepley break; 553589eabcffSMatthew G. Knepley case 3: 553689eabcffSMatthew G. Knepley /* The original hex closure is 553789eabcffSMatthew G. Knepley 553889eabcffSMatthew G. Knepley {c, 553989eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 554089eabcffSMatthew 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, 554189eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 554289eabcffSMatthew G. Knepley */ 55439566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 554489eabcffSMatthew G. Knepley /* The SEM order is 554589eabcffSMatthew G. Knepley Bottom Slice 554689eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 554789eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 554889eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 554989eabcffSMatthew G. Knepley 555089eabcffSMatthew G. Knepley Middle Slice (j) 555189eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 555289eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 555389eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 555489eabcffSMatthew G. Knepley 555589eabcffSMatthew G. Knepley Top Slice 555689eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 555789eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 555889eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 555989eabcffSMatthew G. Knepley */ 556089eabcffSMatthew G. Knepley { 556189eabcffSMatthew G. Knepley const PetscInt oc = 0; 556289eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 556389eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 556489eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 556589eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 556689eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 556789eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 556889eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 556989eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 557089eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 557189eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 557289eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 557389eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 557489eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 557589eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 557689eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 557789eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 557889eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 557989eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 558089eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 558189eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 558289eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 558389eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 558489eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 558589eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 558689eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 558789eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 558889eabcffSMatthew G. Knepley PetscInt o, n; 558989eabcffSMatthew G. Knepley 559089eabcffSMatthew G. Knepley /* Bottom Slice */ 559189eabcffSMatthew G. Knepley /* bottom */ 559289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 55939371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 55949371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 559589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 559689eabcffSMatthew G. Knepley /* middle */ 559789eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 559889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 55999371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 56009371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 56019371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 56029371c9d4SSatish Balay } 560389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 56043194fc30SMatthew G. Knepley } 560589eabcffSMatthew G. Knepley /* top */ 560689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 56079371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 56089371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 560989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 561089eabcffSMatthew G. Knepley 561189eabcffSMatthew G. Knepley /* Middle Slice */ 561289eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 561389eabcffSMatthew G. Knepley /* bottom */ 561489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 56159371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 56169371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 561789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 561889eabcffSMatthew G. Knepley /* middle */ 561989eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 562089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 56219371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 56229371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 562389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 562489eabcffSMatthew G. Knepley } 562589eabcffSMatthew G. Knepley /* top */ 562689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 56279371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 56289371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 562989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 563089eabcffSMatthew G. Knepley } 563189eabcffSMatthew G. Knepley 563289eabcffSMatthew G. Knepley /* Top Slice */ 563389eabcffSMatthew G. Knepley /* bottom */ 563489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 56359371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 56369371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 563789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 563889eabcffSMatthew G. Knepley /* middle */ 563989eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 564089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 56419371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 56429371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 564389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 564489eabcffSMatthew G. Knepley } 564589eabcffSMatthew G. Knepley /* top */ 564689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 56479371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 56489371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 564989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 565089eabcffSMatthew G. Knepley 565189eabcffSMatthew G. Knepley foffset = offset; 565289eabcffSMatthew G. Knepley } 565389eabcffSMatthew G. Knepley break; 5654d71ae5a4SJacob Faibussowitsch default: 5655d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 565689eabcffSMatthew G. Knepley } 565789eabcffSMatthew G. Knepley } 565863a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 56593194fc30SMatthew G. Knepley /* Check permutation */ 56603194fc30SMatthew G. Knepley { 56613194fc30SMatthew G. Knepley PetscInt *check; 56623194fc30SMatthew G. Knepley 56639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 56641dca8a05SBarry Smith for (i = 0; i < size; ++i) { 56651dca8a05SBarry Smith check[i] = -1; 56661dca8a05SBarry 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]); 56671dca8a05SBarry Smith } 56683194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 56691dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 56709566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 56713194fc30SMatthew G. Knepley } 56729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 5673a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5674a05c9aa3SJed Brown PetscInt *loc_perm; 56759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 5676a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 5677a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5678a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 5679a05c9aa3SJed Brown } 56809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 5681a05c9aa3SJed Brown } 5682bb197d40SJed Brown } 56833194fc30SMatthew G. Knepley PetscFunctionReturn(0); 56843194fc30SMatthew G. Knepley } 56853194fc30SMatthew G. Knepley 5686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5687d71ae5a4SJacob Faibussowitsch { 5688e071409bSToby Isaac PetscDS prob; 5689e071409bSToby Isaac PetscInt depth, Nf, h; 5690e071409bSToby Isaac DMLabel label; 5691e071409bSToby Isaac 5692e071409bSToby Isaac PetscFunctionBeginHot; 56939566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 5694e071409bSToby Isaac Nf = prob->Nf; 5695e071409bSToby Isaac label = dm->depthLabel; 5696e071409bSToby Isaac *dspace = NULL; 5697e071409bSToby Isaac if (field < Nf) { 5698e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5699e071409bSToby Isaac 5700e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5701e071409bSToby Isaac PetscDualSpace dsp; 5702e071409bSToby Isaac 57039566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 57049566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 57059566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 5706e071409bSToby Isaac h = depth - 1 - h; 5707e071409bSToby Isaac if (h) { 57089566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 5709e071409bSToby Isaac } else { 5710e071409bSToby Isaac *dspace = dsp; 5711e071409bSToby Isaac } 5712e071409bSToby Isaac } 5713e071409bSToby Isaac } 5714e071409bSToby Isaac PetscFunctionReturn(0); 5715e071409bSToby Isaac } 5716e071409bSToby Isaac 5717d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5718d71ae5a4SJacob Faibussowitsch { 571928351e22SJed Brown PetscScalar *array; 572028351e22SJed Brown const PetscScalar *vArray; 5721d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 57221a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5723552f7358SJed Brown 57241b406b76SMatthew G. Knepley PetscFunctionBeginHot; 57259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 57269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 57279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 57289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 57293f7cbbe7SMatthew G. Knepley if (!values || !*values) { 57309df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 57319df71ca4SMatthew G. Knepley PetscInt dof; 5732d9917b9dSMatthew G. Knepley 57339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 57349df71ca4SMatthew G. Knepley size += dof; 57359df71ca4SMatthew G. Knepley } 57369df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 57379df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 57382a3aaacfSMatthew G. Knepley PetscInt dof; 57395a1bb5cfSMatthew G. Knepley 57405a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 57419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 57425a1bb5cfSMatthew G. Knepley size += dof; 57435a1bb5cfSMatthew G. Knepley } 57443f7cbbe7SMatthew G. Knepley if (!values) { 57453f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 57463f7cbbe7SMatthew G. Knepley PetscFunctionReturn(0); 57473f7cbbe7SMatthew G. Knepley } 57489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 5749982e9ed1SMatthew G. Knepley } else { 5750982e9ed1SMatthew G. Knepley array = *values; 5751982e9ed1SMatthew G. Knepley } 57529df71ca4SMatthew G. Knepley size = 0; 575328351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 57549df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 57559df71ca4SMatthew G. Knepley PetscInt dof, off, d; 575628351e22SJed Brown const PetscScalar *varr; 5757d9917b9dSMatthew G. Knepley 57589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 57599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 57609df71ca4SMatthew G. Knepley varr = &vArray[off]; 5761ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 57629df71ca4SMatthew G. Knepley size += dof; 57639df71ca4SMatthew G. Knepley } 57649df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 57659df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 57669df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 57675a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 576828351e22SJed Brown const PetscScalar *varr; 57695a1bb5cfSMatthew G. Knepley 577052ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 57719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 57729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 57735a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 57745a1bb5cfSMatthew G. Knepley if (o >= 0) { 5775ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 57765a1bb5cfSMatthew G. Knepley } else { 5777ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 57785a1bb5cfSMatthew G. Knepley } 57799df71ca4SMatthew G. Knepley size += dof; 57805a1bb5cfSMatthew G. Knepley } 578128351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 57829df71ca4SMatthew G. Knepley if (!*values) { 57835a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 57845a1bb5cfSMatthew G. Knepley *values = array; 57859df71ca4SMatthew G. Knepley } else { 578663a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 57878c312ff3SMatthew G. Knepley *csize = size; 57889df71ca4SMatthew G. Knepley } 57895a1bb5cfSMatthew G. Knepley PetscFunctionReturn(0); 57905a1bb5cfSMatthew G. Knepley } 5791d9917b9dSMatthew G. Knepley 579227f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 5793d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5794d71ae5a4SJacob Faibussowitsch { 579527f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 579627f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 579727f02ce8SMatthew G. Knepley 57989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 579927f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 580027f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 580127f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 580227f02ce8SMatthew G. Knepley points[q * 2] = r; 580327f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 580427f02ce8SMatthew G. Knepley ++q; 580527f02ce8SMatthew G. Knepley } 580627f02ce8SMatthew G. Knepley } 580727f02ce8SMatthew G. Knepley *numPoints = q; 580827f02ce8SMatthew G. Knepley return 0; 580927f02ce8SMatthew G. Knepley } 581027f02ce8SMatthew G. Knepley 581197529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 5812d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5813d71ae5a4SJacob Faibussowitsch { 581427f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 5815923c78e0SToby Isaac PetscInt np, *pts = NULL; 5816923c78e0SToby Isaac 5817923c78e0SToby Isaac PetscFunctionBeginHot; 58189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 581927f02ce8SMatthew G. Knepley if (*clPoints) { 5820923c78e0SToby Isaac PetscInt dof, off; 5821923c78e0SToby Isaac 58229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 58239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 58249566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 5825923c78e0SToby Isaac np = dof / 2; 5826923c78e0SToby Isaac pts = (PetscInt *)&cla[off]; 582727f02ce8SMatthew G. Knepley } else { 58289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts)); 58299566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 5830923c78e0SToby Isaac } 5831923c78e0SToby Isaac *numPoints = np; 5832923c78e0SToby Isaac *points = pts; 5833923c78e0SToby Isaac *clp = cla; 5834923c78e0SToby Isaac PetscFunctionReturn(0); 5835923c78e0SToby Isaac } 5836923c78e0SToby Isaac 5837d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5838d71ae5a4SJacob Faibussowitsch { 5839923c78e0SToby Isaac PetscFunctionBeginHot; 5840923c78e0SToby Isaac if (!*clPoints) { 58419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 5842923c78e0SToby Isaac } else { 58439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 5844923c78e0SToby Isaac } 5845923c78e0SToby Isaac *numPoints = 0; 5846923c78e0SToby Isaac *points = NULL; 5847923c78e0SToby Isaac *clSec = NULL; 5848923c78e0SToby Isaac *clPoints = NULL; 5849923c78e0SToby Isaac *clp = NULL; 5850923c78e0SToby Isaac PetscFunctionReturn(0); 5851923c78e0SToby Isaac } 5852923c78e0SToby Isaac 5853d71ae5a4SJacob 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[]) 5854d71ae5a4SJacob Faibussowitsch { 58551a271a75SMatthew G. Knepley PetscInt offset = 0, p; 585697e99dd9SToby Isaac const PetscInt **perms = NULL; 585797e99dd9SToby Isaac const PetscScalar **flips = NULL; 58581a271a75SMatthew G. Knepley 58591a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5860fe02ba77SJed Brown *size = 0; 58619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 586297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 586397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 586497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 586597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 58661a271a75SMatthew G. Knepley PetscInt dof, off, d; 58671a271a75SMatthew G. Knepley const PetscScalar *varr; 58681a271a75SMatthew G. Knepley 58699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 58709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 58711a271a75SMatthew G. Knepley varr = &vArray[off]; 587297e99dd9SToby Isaac if (clperm) { 587397e99dd9SToby Isaac if (perm) { 587497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 58751a271a75SMatthew G. Knepley } else { 587697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 587797e99dd9SToby Isaac } 587897e99dd9SToby Isaac if (flip) { 587997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 588097e99dd9SToby Isaac } 588197e99dd9SToby Isaac } else { 588297e99dd9SToby Isaac if (perm) { 588397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 588497e99dd9SToby Isaac } else { 588597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 588697e99dd9SToby Isaac } 588797e99dd9SToby Isaac if (flip) { 588897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 58891a271a75SMatthew G. Knepley } 58901a271a75SMatthew G. Knepley } 589197e99dd9SToby Isaac offset += dof; 589297e99dd9SToby Isaac } 58939566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 58941a271a75SMatthew G. Knepley *size = offset; 58951a271a75SMatthew G. Knepley PetscFunctionReturn(0); 58961a271a75SMatthew G. Knepley } 58971a271a75SMatthew G. Knepley 5898d71ae5a4SJacob 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[]) 5899d71ae5a4SJacob Faibussowitsch { 59001a271a75SMatthew G. Knepley PetscInt offset = 0, f; 59011a271a75SMatthew G. Knepley 59021a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5903fe02ba77SJed Brown *size = 0; 59041a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 590597e99dd9SToby Isaac PetscInt p; 590697e99dd9SToby Isaac const PetscInt **perms = NULL; 590797e99dd9SToby Isaac const PetscScalar **flips = NULL; 59081a271a75SMatthew G. Knepley 59099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 591097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 591197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 591297e99dd9SToby Isaac PetscInt fdof, foff, b; 59131a271a75SMatthew G. Knepley const PetscScalar *varr; 591497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 591597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 59161a271a75SMatthew G. Knepley 59179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 59189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 59191a271a75SMatthew G. Knepley varr = &vArray[foff]; 592097e99dd9SToby Isaac if (clperm) { 59219371c9d4SSatish Balay if (perm) { 5922ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 59231a271a75SMatthew G. Knepley } else { 5924ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 59259371c9d4SSatish Balay } 59269371c9d4SSatish Balay if (flip) { 5927ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 59289371c9d4SSatish Balay } 59299371c9d4SSatish Balay } else { 59309371c9d4SSatish Balay if (perm) { 5931ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 59329371c9d4SSatish Balay } else { 5933ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 59349371c9d4SSatish Balay } 59359371c9d4SSatish Balay if (flip) { 5936ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 59379371c9d4SSatish Balay } 59381a271a75SMatthew G. Knepley } 593997e99dd9SToby Isaac offset += fdof; 59401a271a75SMatthew G. Knepley } 59419566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 59421a271a75SMatthew G. Knepley } 59431a271a75SMatthew G. Knepley *size = offset; 59441a271a75SMatthew G. Knepley PetscFunctionReturn(0); 59451a271a75SMatthew G. Knepley } 59461a271a75SMatthew G. Knepley 5947552f7358SJed Brown /*@C 5948552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5949552f7358SJed Brown 5950552f7358SJed Brown Not collective 5951552f7358SJed Brown 5952552f7358SJed Brown Input Parameters: 5953a1cb98faSBarry Smith + dm - The `DM` 5954552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section 5955552f7358SJed Brown . v - The local vector 5956a1cb98faSBarry Smith - point - The point in the `DM` 5957552f7358SJed Brown 59586b867d5aSJose E. Roman Input/Output Parameters: 59596b867d5aSJose E. Roman + csize - The size of the input values array, or NULL; on output the number of values in the closure 59606b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically; 59616b867d5aSJose E. Roman if the user provided NULL, it is a borrowed array and should not be freed 596222c1ee49SMatthew G. Knepley 5963552f7358SJed Brown Level: intermediate 5964552f7358SJed Brown 5965a1cb98faSBarry Smith Notes: 5966a1cb98faSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to NULL in the 5967a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 5968a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 5969a1cb98faSBarry Smith 5970a1cb98faSBarry Smith A typical use could be 5971a1cb98faSBarry Smith .vb 5972a1cb98faSBarry Smith values = NULL; 5973a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 5974a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 5975a1cb98faSBarry Smith <Compute on closure> 5976a1cb98faSBarry Smith } 5977a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 5978a1cb98faSBarry Smith .ve 5979a1cb98faSBarry Smith or 5980a1cb98faSBarry Smith .vb 5981a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 5982a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 5983a1cb98faSBarry Smith clSize = clMaxSize; 5984a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 5985a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 5986a1cb98faSBarry Smith <Compute on closure> 5987a1cb98faSBarry Smith } 5988a1cb98faSBarry Smith } 5989a1cb98faSBarry Smith PetscFree(values); 5990a1cb98faSBarry Smith .ve 5991a1cb98faSBarry Smith 5992a1cb98faSBarry Smith Fortran Note: 5993a1cb98faSBarry Smith The csize argument is not present in the Fortran binding since it is internal to the array. 5994a1cb98faSBarry Smith 5995a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5996552f7358SJed Brown @*/ 5997d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5998d71ae5a4SJacob Faibussowitsch { 5999552f7358SJed Brown PetscSection clSection; 6000d9917b9dSMatthew G. Knepley IS clPoints; 6001552f7358SJed Brown PetscInt *points = NULL; 6002c459fbc1SJed Brown const PetscInt *clp, *perm; 6003c459fbc1SJed Brown PetscInt depth, numFields, numPoints, asize; 6004552f7358SJed Brown 6005d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6006552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 60079566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 60081a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 60091a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 60109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 60119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6012552f7358SJed Brown if (depth == 1 && numFields < 2) { 60139566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 6014552f7358SJed Brown PetscFunctionReturn(0); 6015552f7358SJed Brown } 60161a271a75SMatthew G. Knepley /* Get points */ 60179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6018c459fbc1SJed Brown /* Get sizes */ 6019c459fbc1SJed Brown asize = 0; 6020c459fbc1SJed Brown for (PetscInt p = 0; p < numPoints * 2; p += 2) { 6021c459fbc1SJed Brown PetscInt dof; 60229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 60231a271a75SMatthew G. Knepley asize += dof; 6024552f7358SJed Brown } 6025c459fbc1SJed Brown if (values) { 6026c459fbc1SJed Brown const PetscScalar *vArray; 6027c459fbc1SJed Brown PetscInt size; 6028c459fbc1SJed Brown 6029c459fbc1SJed Brown if (*values) { 603063a3b9bcSJacob Faibussowitsch 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); 60319566063dSJacob Faibussowitsch } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 60329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 60339566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 60341a271a75SMatthew G. Knepley /* Get values */ 60359566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 60369566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 603763a3b9bcSJacob Faibussowitsch PetscCheck(asize == size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size); 60381a271a75SMatthew G. Knepley /* Cleanup array */ 60399566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6040d0f6b257SMatthew G. Knepley } 6041c459fbc1SJed Brown if (csize) *csize = asize; 6042c459fbc1SJed Brown /* Cleanup points */ 60439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6044552f7358SJed Brown PetscFunctionReturn(0); 6045552f7358SJed Brown } 6046552f7358SJed Brown 6047d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6048d71ae5a4SJacob Faibussowitsch { 6049e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6050e5c487bfSMatthew G. Knepley PetscSection clSection; 6051e5c487bfSMatthew G. Knepley IS clPoints; 6052e5c487bfSMatthew G. Knepley PetscScalar *array; 6053e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6054e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6055c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6056c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6057e5c487bfSMatthew G. Knepley 6058e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6059e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 60609566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6061e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6062e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 60639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 60649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 60659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6066e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 60679566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 6068e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 6069e5c487bfSMatthew G. Knepley } 6070e5c487bfSMatthew G. Knepley /* Get points */ 60719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6072c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6073c459fbc1SJed Brown PetscInt dof; 60749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6075c459fbc1SJed Brown clsize += dof; 6076c459fbc1SJed Brown } 60779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6078e5c487bfSMatthew G. Knepley /* Filter points */ 6079e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6080e5c487bfSMatthew G. Knepley PetscInt dep; 6081e5c487bfSMatthew G. Knepley 60829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6083e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6084e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6085e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6086e5c487bfSMatthew G. Knepley ++Np; 6087e5c487bfSMatthew G. Knepley } 6088e5c487bfSMatthew G. Knepley /* Get array */ 6089e5c487bfSMatthew G. Knepley if (!values || !*values) { 6090e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6091e5c487bfSMatthew G. Knepley 6092e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 60939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6094e5c487bfSMatthew G. Knepley asize += dof; 6095e5c487bfSMatthew G. Knepley } 6096e5c487bfSMatthew G. Knepley if (!values) { 60979566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6098e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 6099e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 6100e5c487bfSMatthew G. Knepley } 61019566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6102e5c487bfSMatthew G. Knepley } else { 6103e5c487bfSMatthew G. Knepley array = *values; 6104e5c487bfSMatthew G. Knepley } 61059566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6106e5c487bfSMatthew G. Knepley /* Get values */ 61079566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 61089566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6109e5c487bfSMatthew G. Knepley /* Cleanup points */ 61109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6111e5c487bfSMatthew G. Knepley /* Cleanup array */ 61129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6113e5c487bfSMatthew G. Knepley if (!*values) { 6114e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6115e5c487bfSMatthew G. Knepley *values = array; 6116e5c487bfSMatthew G. Knepley } else { 611763a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6118e5c487bfSMatthew G. Knepley *csize = size; 6119e5c487bfSMatthew G. Knepley } 6120e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 6121e5c487bfSMatthew G. Knepley } 6122e5c487bfSMatthew G. Knepley 6123552f7358SJed Brown /*@C 6124552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6125552f7358SJed Brown 6126552f7358SJed Brown Not collective 6127552f7358SJed Brown 6128552f7358SJed Brown Input Parameters: 6129a1cb98faSBarry Smith + dm - The `DM` 61300298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section 6131552f7358SJed Brown . v - The local vector 6132a1cb98faSBarry Smith . point - The point in the `DM` 61330298fd71SBarry Smith . csize - The number of values in the closure, or NULL 6134552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6135552f7358SJed Brown 6136552f7358SJed Brown Level: intermediate 6137552f7358SJed Brown 6138a1cb98faSBarry Smith Note: 6139a1cb98faSBarry Smith The array values are discarded and not copied back into v. In order to copy values back to v, use `DMPlexVecSetClosure()` 6140a1cb98faSBarry Smith 6141a1cb98faSBarry Smith Fortran Note: 6142a1cb98faSBarry Smith The csize argument is not present in the Fortran binding since it is internal to the array. 6143a1cb98faSBarry Smith 6144a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6145552f7358SJed Brown @*/ 6146d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6147d71ae5a4SJacob Faibussowitsch { 6148552f7358SJed Brown PetscInt size = 0; 6149552f7358SJed Brown 6150552f7358SJed Brown PetscFunctionBegin; 6151552f7358SJed Brown /* Should work without recalculating size */ 61529566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6153c9fdaa05SMatthew G. Knepley *values = NULL; 6154552f7358SJed Brown PetscFunctionReturn(0); 6155552f7358SJed Brown } 6156552f7358SJed Brown 6157d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6158d71ae5a4SJacob Faibussowitsch { 61599371c9d4SSatish Balay *x += y; 61609371c9d4SSatish Balay } 6161d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6162d71ae5a4SJacob Faibussowitsch { 61639371c9d4SSatish Balay *x = y; 61649371c9d4SSatish Balay } 6165552f7358SJed Brown 6166d71ae5a4SJacob 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[]) 6167d71ae5a4SJacob Faibussowitsch { 6168552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6169552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6170552f7358SJed Brown PetscScalar *a; 6171552f7358SJed Brown PetscInt off, cind = 0, k; 6172552f7358SJed Brown 6173552f7358SJed Brown PetscFunctionBegin; 61749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 61759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6176552f7358SJed Brown a = &array[off]; 6177552f7358SJed Brown if (!cdof || setBC) { 617897e99dd9SToby Isaac if (clperm) { 61799371c9d4SSatish Balay if (perm) { 6180ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6181552f7358SJed Brown } else { 6182ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 61839371c9d4SSatish Balay } 61849371c9d4SSatish Balay } else { 61859371c9d4SSatish Balay if (perm) { 6186ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 61879371c9d4SSatish Balay } else { 6188ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 61899371c9d4SSatish Balay } 6190552f7358SJed Brown } 6191552f7358SJed Brown } else { 61929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 619397e99dd9SToby Isaac if (clperm) { 61949371c9d4SSatish Balay if (perm) { 61959371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 61969371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 61979371c9d4SSatish Balay ++cind; 61989371c9d4SSatish Balay continue; 61999371c9d4SSatish Balay } 620097e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6201552f7358SJed Brown } 6202552f7358SJed Brown } else { 6203552f7358SJed Brown for (k = 0; k < dof; ++k) { 62049371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 62059371c9d4SSatish Balay ++cind; 62069371c9d4SSatish Balay continue; 62079371c9d4SSatish Balay } 620897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 620997e99dd9SToby Isaac } 621097e99dd9SToby Isaac } 621197e99dd9SToby Isaac } else { 621297e99dd9SToby Isaac if (perm) { 621397e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 62149371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 62159371c9d4SSatish Balay ++cind; 62169371c9d4SSatish Balay continue; 62179371c9d4SSatish Balay } 621897e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 621997e99dd9SToby Isaac } 622097e99dd9SToby Isaac } else { 622197e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 62229371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 62239371c9d4SSatish Balay ++cind; 62249371c9d4SSatish Balay continue; 62259371c9d4SSatish Balay } 622697e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 622797e99dd9SToby Isaac } 6228552f7358SJed Brown } 6229552f7358SJed Brown } 6230552f7358SJed Brown } 6231552f7358SJed Brown PetscFunctionReturn(0); 6232552f7358SJed Brown } 6233552f7358SJed Brown 6234d71ae5a4SJacob 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[]) 6235d71ae5a4SJacob Faibussowitsch { 6236a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6237a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6238a5e93ea8SMatthew G. Knepley PetscScalar *a; 6239a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6240a5e93ea8SMatthew G. Knepley 6241a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 62429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 62439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6244a5e93ea8SMatthew G. Knepley a = &array[off]; 6245a5e93ea8SMatthew G. Knepley if (cdof) { 62469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 624797e99dd9SToby Isaac if (clperm) { 624897e99dd9SToby Isaac if (perm) { 6249a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6250a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 625197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 625297e99dd9SToby Isaac cind++; 6253a5e93ea8SMatthew G. Knepley } 6254a5e93ea8SMatthew G. Knepley } 6255a5e93ea8SMatthew G. Knepley } else { 6256a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6257a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 625897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 625997e99dd9SToby Isaac cind++; 626097e99dd9SToby Isaac } 626197e99dd9SToby Isaac } 626297e99dd9SToby Isaac } 626397e99dd9SToby Isaac } else { 626497e99dd9SToby Isaac if (perm) { 626597e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 626697e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 626797e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 626897e99dd9SToby Isaac cind++; 626997e99dd9SToby Isaac } 627097e99dd9SToby Isaac } 627197e99dd9SToby Isaac } else { 627297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 627397e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 627497e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 627597e99dd9SToby Isaac cind++; 627697e99dd9SToby Isaac } 6277a5e93ea8SMatthew G. Knepley } 6278a5e93ea8SMatthew G. Knepley } 6279a5e93ea8SMatthew G. Knepley } 6280a5e93ea8SMatthew G. Knepley } 6281a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6282a5e93ea8SMatthew G. Knepley } 6283a5e93ea8SMatthew G. Knepley 6284d71ae5a4SJacob 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[]) 6285d71ae5a4SJacob Faibussowitsch { 6286552f7358SJed Brown PetscScalar *a; 62871a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 62881a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 628997e99dd9SToby Isaac PetscInt cind = 0, b; 6290552f7358SJed Brown 6291552f7358SJed Brown PetscFunctionBegin; 62929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 62939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 62949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 62951a271a75SMatthew G. Knepley a = &array[foff]; 6296552f7358SJed Brown if (!fcdof || setBC) { 629797e99dd9SToby Isaac if (clperm) { 62989371c9d4SSatish Balay if (perm) { 6299ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6300552f7358SJed Brown } else { 6301ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 63029371c9d4SSatish Balay } 63039371c9d4SSatish Balay } else { 63049371c9d4SSatish Balay if (perm) { 6305ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 63069371c9d4SSatish Balay } else { 6307ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 63089371c9d4SSatish Balay } 6309552f7358SJed Brown } 6310552f7358SJed Brown } else { 63119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 631297e99dd9SToby Isaac if (clperm) { 631397e99dd9SToby Isaac if (perm) { 631497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 63159371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 63169371c9d4SSatish Balay ++cind; 63179371c9d4SSatish Balay continue; 63189371c9d4SSatish Balay } 631997e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6320552f7358SJed Brown } 6321552f7358SJed Brown } else { 632297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 63239371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 63249371c9d4SSatish Balay ++cind; 63259371c9d4SSatish Balay continue; 63269371c9d4SSatish Balay } 632797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 632897e99dd9SToby Isaac } 632997e99dd9SToby Isaac } 633097e99dd9SToby Isaac } else { 633197e99dd9SToby Isaac if (perm) { 633297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 63339371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 63349371c9d4SSatish Balay ++cind; 63359371c9d4SSatish Balay continue; 63369371c9d4SSatish Balay } 633797e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 633897e99dd9SToby Isaac } 633997e99dd9SToby Isaac } else { 634097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 63419371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 63429371c9d4SSatish Balay ++cind; 63439371c9d4SSatish Balay continue; 63449371c9d4SSatish Balay } 634597e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6346552f7358SJed Brown } 6347552f7358SJed Brown } 6348552f7358SJed Brown } 6349552f7358SJed Brown } 63501a271a75SMatthew G. Knepley *offset += fdof; 6351552f7358SJed Brown PetscFunctionReturn(0); 6352552f7358SJed Brown } 6353552f7358SJed Brown 6354d71ae5a4SJacob 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[]) 6355d71ae5a4SJacob Faibussowitsch { 6356a5e93ea8SMatthew G. Knepley PetscScalar *a; 63571a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 63581a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 63595da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6360ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6361a5e93ea8SMatthew G. Knepley 6362a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 63639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 63649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 63659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 63669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 63671a271a75SMatthew G. Knepley a = &array[foff]; 6368a5e93ea8SMatthew G. Knepley if (fcdof) { 6369ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 63709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 637197e99dd9SToby Isaac if (clperm) { 637297e99dd9SToby Isaac if (perm) { 6373ba322698SMatthew G. Knepley if (comps) { 6374ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6375ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 63769371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 63779371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 63789371c9d4SSatish Balay ncSet = PETSC_TRUE; 63799371c9d4SSatish Balay } 63809371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 63819371c9d4SSatish Balay ++cind; 63829371c9d4SSatish Balay fcSet = PETSC_TRUE; 63839371c9d4SSatish Balay } 6384ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6385ba322698SMatthew G. Knepley } 6386ba322698SMatthew G. Knepley } else { 638797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 638897e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 638997e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6390a5e93ea8SMatthew G. Knepley ++cind; 6391a5e93ea8SMatthew G. Knepley } 6392a5e93ea8SMatthew G. Knepley } 6393ba322698SMatthew G. Knepley } 6394ba322698SMatthew G. Knepley } else { 6395ba322698SMatthew G. Knepley if (comps) { 6396ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6397ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 63989371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 63999371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 64009371c9d4SSatish Balay ncSet = PETSC_TRUE; 64019371c9d4SSatish Balay } 64029371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 64039371c9d4SSatish Balay ++cind; 64049371c9d4SSatish Balay fcSet = PETSC_TRUE; 64059371c9d4SSatish Balay } 6406ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6407ba322698SMatthew G. Knepley } 6408a5e93ea8SMatthew G. Knepley } else { 640997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 641097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 641197e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 641297e99dd9SToby Isaac ++cind; 641397e99dd9SToby Isaac } 641497e99dd9SToby Isaac } 641597e99dd9SToby Isaac } 6416ba322698SMatthew G. Knepley } 641797e99dd9SToby Isaac } else { 641897e99dd9SToby Isaac if (perm) { 6419ba322698SMatthew G. Knepley if (comps) { 6420ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6421ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 64229371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 64239371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 64249371c9d4SSatish Balay ncSet = PETSC_TRUE; 64259371c9d4SSatish Balay } 64269371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 64279371c9d4SSatish Balay ++cind; 64289371c9d4SSatish Balay fcSet = PETSC_TRUE; 64299371c9d4SSatish Balay } 6430ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6431ba322698SMatthew G. Knepley } 6432ba322698SMatthew G. Knepley } else { 643397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 643497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 643597e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 643697e99dd9SToby Isaac ++cind; 643797e99dd9SToby Isaac } 643897e99dd9SToby Isaac } 6439ba322698SMatthew G. Knepley } 6440ba322698SMatthew G. Knepley } else { 6441ba322698SMatthew G. Knepley if (comps) { 6442ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6443ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 64449371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 64459371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 64469371c9d4SSatish Balay ncSet = PETSC_TRUE; 64479371c9d4SSatish Balay } 64489371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 64499371c9d4SSatish Balay ++cind; 64509371c9d4SSatish Balay fcSet = PETSC_TRUE; 64519371c9d4SSatish Balay } 6452ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6453ba322698SMatthew G. Knepley } 645497e99dd9SToby Isaac } else { 645597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 645697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 645797e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6458a5e93ea8SMatthew G. Knepley ++cind; 6459a5e93ea8SMatthew G. Knepley } 6460a5e93ea8SMatthew G. Knepley } 6461a5e93ea8SMatthew G. Knepley } 6462a5e93ea8SMatthew G. Knepley } 6463a5e93ea8SMatthew G. Knepley } 6464ba322698SMatthew G. Knepley } 64651a271a75SMatthew G. Knepley *offset += fdof; 6466a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6467a5e93ea8SMatthew G. Knepley } 6468a5e93ea8SMatthew G. Knepley 6469d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6470d71ae5a4SJacob Faibussowitsch { 6471552f7358SJed Brown PetscScalar *array; 64721b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 64731b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6474552f7358SJed Brown 64751b406b76SMatthew G. Knepley PetscFunctionBeginHot; 64769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 64779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 64789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 64799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 64809566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6481b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6482b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6483b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6484b6ebb6e6SMatthew G. Knepley 64859371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 64869371c9d4SSatish Balay dof = 0; 64879371c9d4SSatish Balay continue; 64889371c9d4SSatish Balay } 64899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6490b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6491b6ebb6e6SMatthew G. Knepley { 6492b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6493b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6494b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6495b6ebb6e6SMatthew G. Knepley 64969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 64979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6498b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6499b6ebb6e6SMatthew G. Knepley if (!cdof) { 6500b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6501ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6502b6ebb6e6SMatthew G. Knepley } else { 6503ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6504b6ebb6e6SMatthew G. Knepley } 6505b6ebb6e6SMatthew G. Knepley } else { 65069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6507b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6508b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 65099371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 65109371c9d4SSatish Balay ++cind; 65119371c9d4SSatish Balay continue; 65129371c9d4SSatish Balay } 6513b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6514b6ebb6e6SMatthew G. Knepley } 6515b6ebb6e6SMatthew G. Knepley } else { 6516b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 65179371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 65189371c9d4SSatish Balay ++cind; 65199371c9d4SSatish Balay continue; 65209371c9d4SSatish Balay } 6521b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6522b6ebb6e6SMatthew G. Knepley } 6523b6ebb6e6SMatthew G. Knepley } 6524b6ebb6e6SMatthew G. Knepley } 6525b6ebb6e6SMatthew G. Knepley } 6526b6ebb6e6SMatthew G. Knepley } 65279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6528b6ebb6e6SMatthew G. Knepley PetscFunctionReturn(0); 6529b6ebb6e6SMatthew G. Knepley } 65301b406b76SMatthew G. Knepley 65311b406b76SMatthew G. Knepley /*@C 65321b406b76SMatthew G. Knepley DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 65331b406b76SMatthew G. Knepley 65341b406b76SMatthew G. Knepley Not collective 65351b406b76SMatthew G. Knepley 65361b406b76SMatthew G. Knepley Input Parameters: 6537a1cb98faSBarry Smith + dm - The `DM` 65381b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 65391b406b76SMatthew G. Knepley . v - The local vector 6540eaf898f9SPatrick Sanan . point - The point in the DM 65411b406b76SMatthew G. Knepley . values - The array of values 6542a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6543a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 65441b406b76SMatthew G. Knepley 65451b406b76SMatthew G. Knepley Level: intermediate 65461b406b76SMatthew G. Knepley 6547a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 65481b406b76SMatthew G. Knepley @*/ 6549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6550d71ae5a4SJacob Faibussowitsch { 65511b406b76SMatthew G. Knepley PetscSection clSection; 65521b406b76SMatthew G. Knepley IS clPoints; 65531b406b76SMatthew G. Knepley PetscScalar *array; 65541b406b76SMatthew G. Knepley PetscInt *points = NULL; 655527f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6556c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 65571b406b76SMatthew G. Knepley 65581a271a75SMatthew G. Knepley PetscFunctionBeginHot; 65591b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 65609566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 65611a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 65621a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 65639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 65649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 65651b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 65669566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 65671b406b76SMatthew G. Knepley PetscFunctionReturn(0); 65681b406b76SMatthew G. Knepley } 65691a271a75SMatthew G. Knepley /* Get points */ 65709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6571c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6572c459fbc1SJed Brown PetscInt dof; 65739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6574c459fbc1SJed Brown clsize += dof; 6575c459fbc1SJed Brown } 65769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 65771a271a75SMatthew G. Knepley /* Get array */ 65789566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 65791a271a75SMatthew G. Knepley /* Get values */ 6580ef90cfe2SMatthew G. Knepley if (numFields > 0) { 658197e99dd9SToby Isaac PetscInt offset = 0, f; 6582552f7358SJed Brown for (f = 0; f < numFields; ++f) { 658397e99dd9SToby Isaac const PetscInt **perms = NULL; 658497e99dd9SToby Isaac const PetscScalar **flips = NULL; 658597e99dd9SToby Isaac 65869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6587552f7358SJed Brown switch (mode) { 6588552f7358SJed Brown case INSERT_VALUES: 658997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 659097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 659197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 659297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 659397e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 65949371c9d4SSatish Balay } 65959371c9d4SSatish Balay break; 6596552f7358SJed Brown case INSERT_ALL_VALUES: 659797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 659897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 659997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 660097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 660197e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 66029371c9d4SSatish Balay } 66039371c9d4SSatish Balay break; 6604a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 660597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 660697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 660797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 660897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6609ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 66109371c9d4SSatish Balay } 66119371c9d4SSatish Balay break; 6612552f7358SJed Brown case ADD_VALUES: 661397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 661497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 661597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 661697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 661797e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 66189371c9d4SSatish Balay } 66199371c9d4SSatish Balay break; 6620552f7358SJed Brown case ADD_ALL_VALUES: 662197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 662297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 662397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 662497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 662597e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 66269371c9d4SSatish Balay } 66279371c9d4SSatish Balay break; 6628304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 662997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 663097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 663197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 663297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6633ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 66349371c9d4SSatish Balay } 66359371c9d4SSatish Balay break; 6636d71ae5a4SJacob Faibussowitsch default: 6637d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6638552f7358SJed Brown } 66399566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 66401a271a75SMatthew G. Knepley } 6641552f7358SJed Brown } else { 66421a271a75SMatthew G. Knepley PetscInt dof, off; 664397e99dd9SToby Isaac const PetscInt **perms = NULL; 664497e99dd9SToby Isaac const PetscScalar **flips = NULL; 66451a271a75SMatthew G. Knepley 66469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 6647552f7358SJed Brown switch (mode) { 6648552f7358SJed Brown case INSERT_VALUES: 664997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 665097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 665197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 665297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 66539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 665497e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 66559371c9d4SSatish Balay } 66569371c9d4SSatish Balay break; 6657552f7358SJed Brown case INSERT_ALL_VALUES: 665897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 665997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 666097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 666197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 66629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 666397e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 66649371c9d4SSatish Balay } 66659371c9d4SSatish Balay break; 6666a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 666797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 666897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 666997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 667097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 66719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 667297e99dd9SToby Isaac updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 66739371c9d4SSatish Balay } 66749371c9d4SSatish Balay break; 6675552f7358SJed Brown case ADD_VALUES: 667697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 667797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 667897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 667997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 66809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 668197e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 66829371c9d4SSatish Balay } 66839371c9d4SSatish Balay break; 6684552f7358SJed Brown case ADD_ALL_VALUES: 668597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 668697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 668797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 668897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 66899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 669097e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 66919371c9d4SSatish Balay } 66929371c9d4SSatish Balay break; 6693304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 669497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 669597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 669697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 669797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 66989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 669997e99dd9SToby Isaac updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 67009371c9d4SSatish Balay } 67019371c9d4SSatish Balay break; 6702d71ae5a4SJacob Faibussowitsch default: 6703d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6704552f7358SJed Brown } 67059566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 6706552f7358SJed Brown } 67071a271a75SMatthew G. Knepley /* Cleanup points */ 67089566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 67091a271a75SMatthew G. Knepley /* Cleanup array */ 67109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6711552f7358SJed Brown PetscFunctionReturn(0); 6712552f7358SJed Brown } 6713552f7358SJed Brown 6714cfb853baSMatthew G. Knepley PetscErrorCode DMPlexVecSetStar(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6715cfb853baSMatthew G. Knepley { 6716cfb853baSMatthew G. Knepley const PetscInt *supp, *cone; 6717cfb853baSMatthew G. Knepley PetscScalar *a; 6718cfb853baSMatthew G. Knepley PetscInt dim, Ns, dof, off, n = 0; 6719cfb853baSMatthew G. Knepley 6720cfb853baSMatthew G. Knepley PetscFunctionBegin; 6721cfb853baSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6722cfb853baSMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6723cfb853baSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6724cfb853baSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6725cfb853baSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 6726cfb853baSMatthew G. Knepley PetscInt vStart, vEnd; 6727cfb853baSMatthew G. Knepley 6728cfb853baSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 6729cfb853baSMatthew G. Knepley PetscCheck(point >= vStart && point < vEnd, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " must be a vertex in [%" PetscInt_FMT ", %" PetscInt_FMT "]", point, vStart, vEnd); 6730cfb853baSMatthew G. Knepley } 6731cfb853baSMatthew G. Knepley PetscValidScalarPointer(values, 5); 6732cfb853baSMatthew G. Knepley 6733cfb853baSMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 6734cfb853baSMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, point, &Ns)); 6735cfb853baSMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, point, &supp)); 6736cfb853baSMatthew G. Knepley PetscCheck(Ns == 2 * dim, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " has support size %" PetscInt_FMT " != %" PetscInt_FMT, point, Ns, 2 * dim); 6737cfb853baSMatthew G. Knepley PetscCall(VecGetArray(v, &a)); 6738cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetDof(section, point, &dof)); 6739cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetOffset(section, point, &off)); 6740cfb853baSMatthew G. Knepley for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++]; 6741cfb853baSMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) { 6742cfb853baSMatthew G. Knepley // Left edge 6743cfb853baSMatthew G. Knepley PetscCall(DMPlexGetCone(dm, supp[2 * d + 0], &cone)); 6744cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetDof(section, cone[0], &dof)); 6745cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetOffset(section, cone[0], &off)); 6746cfb853baSMatthew G. Knepley for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++]; 6747cfb853baSMatthew G. Knepley // Right edge 6748cfb853baSMatthew G. Knepley PetscCall(DMPlexGetCone(dm, supp[2 * d + 1], &cone)); 6749cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetDof(section, cone[1], &dof)); 6750cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetOffset(section, cone[1], &off)); 6751cfb853baSMatthew G. Knepley for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++]; 6752cfb853baSMatthew G. Knepley } 6753cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(v, &a)); 6754cfb853baSMatthew G. Knepley PetscFunctionReturn(0); 6755cfb853baSMatthew G. Knepley } 6756cfb853baSMatthew G. Knepley 67575f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6758d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 6759d71ae5a4SJacob Faibussowitsch { 67605f790a90SMatthew G. Knepley PetscFunctionBegin; 676111cc89d2SBarry Smith *contains = PETSC_TRUE; 67625f790a90SMatthew G. Knepley if (label) { 6763d6177c40SToby Isaac PetscInt fdof; 67645f790a90SMatthew G. Knepley 676511cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 676611cc89d2SBarry Smith if (!*contains) { 67679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67685f790a90SMatthew G. Knepley *offset += fdof; 676911cc89d2SBarry Smith PetscFunctionReturn(0); 67705f790a90SMatthew G. Knepley } 67715f790a90SMatthew G. Knepley } 67725f790a90SMatthew G. Knepley PetscFunctionReturn(0); 67735f790a90SMatthew G. Knepley } 67745f790a90SMatthew G. Knepley 677597529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6776d71ae5a4SJacob 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) 6777d71ae5a4SJacob Faibussowitsch { 6778e07394fbSMatthew G. Knepley PetscSection clSection; 6779e07394fbSMatthew G. Knepley IS clPoints; 6780e07394fbSMatthew G. Knepley PetscScalar *array; 6781e07394fbSMatthew G. Knepley PetscInt *points = NULL; 678297529cf3SJed Brown const PetscInt *clp; 6783e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 678497e99dd9SToby Isaac PetscInt offset = 0, f; 6785e07394fbSMatthew G. Knepley 6786e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 6787e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 67889566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6789e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6790e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 67919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6792e07394fbSMatthew G. Knepley /* Get points */ 67939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6794e07394fbSMatthew G. Knepley /* Get array */ 67959566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6796e07394fbSMatthew G. Knepley /* Get values */ 6797e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 679897e99dd9SToby Isaac const PetscInt **perms = NULL; 679997e99dd9SToby Isaac const PetscScalar **flips = NULL; 680011cc89d2SBarry Smith PetscBool contains; 680197e99dd9SToby Isaac 6802e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 6803e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6804e07394fbSMatthew G. Knepley PetscInt fdof; 68059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 6806e07394fbSMatthew G. Knepley offset += fdof; 6807e07394fbSMatthew G. Knepley } 6808e07394fbSMatthew G. Knepley continue; 6809e07394fbSMatthew G. Knepley } 68109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6811e07394fbSMatthew G. Knepley switch (mode) { 6812e07394fbSMatthew G. Knepley case INSERT_VALUES: 681397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 681497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 681597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 681697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 681711cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 681811cc89d2SBarry Smith if (!contains) continue; 68199566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 68209371c9d4SSatish Balay } 68219371c9d4SSatish Balay break; 6822e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 682397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 682497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 682597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 682697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 682711cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 682811cc89d2SBarry Smith if (!contains) continue; 68299566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 68309371c9d4SSatish Balay } 68319371c9d4SSatish Balay break; 6832e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 683397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 683497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 683597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 683697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 683711cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 683811cc89d2SBarry Smith if (!contains) continue; 68399566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 68409371c9d4SSatish Balay } 68419371c9d4SSatish Balay break; 6842e07394fbSMatthew G. Knepley case ADD_VALUES: 684397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 684497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 684597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 684697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 684711cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 684811cc89d2SBarry Smith if (!contains) continue; 68499566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 68509371c9d4SSatish Balay } 68519371c9d4SSatish Balay break; 6852e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 685397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 685497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 685597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 685697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 685711cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 685811cc89d2SBarry Smith if (!contains) continue; 68599566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 68609371c9d4SSatish Balay } 68619371c9d4SSatish Balay break; 6862d71ae5a4SJacob Faibussowitsch default: 6863d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6864e07394fbSMatthew G. Knepley } 68659566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6866e07394fbSMatthew G. Knepley } 6867e07394fbSMatthew G. Knepley /* Cleanup points */ 68689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6869e07394fbSMatthew G. Knepley /* Cleanup array */ 68709566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6871e07394fbSMatthew G. Knepley PetscFunctionReturn(0); 6872e07394fbSMatthew G. Knepley } 6873e07394fbSMatthew G. Knepley 6874d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6875d71ae5a4SJacob Faibussowitsch { 6876552f7358SJed Brown PetscMPIInt rank; 6877552f7358SJed Brown PetscInt i, j; 6878552f7358SJed Brown 6879552f7358SJed Brown PetscFunctionBegin; 68809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 688163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 688263a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 688363a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 6884b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 6885557cf195SMatthew G. Knepley if (!values) PetscFunctionReturn(0); 6886b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 68879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 6888b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 6889519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 68909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 6891552f7358SJed Brown #else 68929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 6893552f7358SJed Brown #endif 6894552f7358SJed Brown } 68959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6896552f7358SJed Brown } 6897552f7358SJed Brown PetscFunctionReturn(0); 6898552f7358SJed Brown } 6899552f7358SJed Brown 690005586334SMatthew G. Knepley /* 690105586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 690205586334SMatthew G. Knepley 690305586334SMatthew G. Knepley Input Parameters: 690405586334SMatthew G. Knepley + section - The section for this data layout 690536fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 690605586334SMatthew G. Knepley . point - The point contributing dofs with these indices 690705586334SMatthew G. Knepley . off - The global offset of this point 690805586334SMatthew G. Knepley . loff - The local offset of each field 6909a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 691005586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 691105586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 691205586334SMatthew G. Knepley 691305586334SMatthew G. Knepley Output Parameter: 691405586334SMatthew G. Knepley . indices - Indices for dofs on this point 691505586334SMatthew G. Knepley 691605586334SMatthew G. Knepley Level: developer 691705586334SMatthew G. Knepley 691805586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 691905586334SMatthew G. Knepley */ 6920d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6921d71ae5a4SJacob Faibussowitsch { 6922e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 6923552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6924552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6925552f7358SJed Brown PetscInt cind = 0, k; 6926552f7358SJed Brown 6927552f7358SJed Brown PetscFunctionBegin; 692808401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 69299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 6931552f7358SJed Brown if (!cdof || setBC) { 693205586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 693305586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 693405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 693505586334SMatthew G. Knepley 693605586334SMatthew G. Knepley indices[ind] = off + k; 6937552f7358SJed Brown } 6938552f7358SJed Brown } else { 69399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 69404acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 694105586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 694205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 694305586334SMatthew G. Knepley 69444acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 69454acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 694605586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 69474acb8e1eSToby Isaac ++cind; 69484acb8e1eSToby Isaac } else { 694936fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 6950552f7358SJed Brown } 6951552f7358SJed Brown } 6952552f7358SJed Brown } 6953e6ccafaeSMatthew G Knepley *loff += dof; 6954552f7358SJed Brown PetscFunctionReturn(0); 6955552f7358SJed Brown } 6956552f7358SJed Brown 69577e29afd2SMatthew G. Knepley /* 695836fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 69597e29afd2SMatthew G. Knepley 696036fa2b79SJed Brown Input Parameters: 696136fa2b79SJed Brown + section - a section (global or local) 696236fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 696336fa2b79SJed Brown . point - point within section 696436fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 696536fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 696636fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 696736fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 696836fa2b79SJed Brown . permsoff - offset 696936fa2b79SJed Brown - indperm - index permutation 697036fa2b79SJed Brown 697136fa2b79SJed Brown Output Parameter: 697236fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 697336fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 697436fa2b79SJed Brown 697536fa2b79SJed Brown Notes: 697636fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 697736fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 697836fa2b79SJed Brown in the local vector. 697936fa2b79SJed Brown 698036fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 698136fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 698236fa2b79SJed Brown 698336fa2b79SJed Brown Developer Note: 698436fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 698536fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 698636fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 698736fa2b79SJed Brown 698836fa2b79SJed Brown Example: 698936fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 699036fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 699136fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 699236fa2b79SJed 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. 699336fa2b79SJed Brown 699436fa2b79SJed Brown Level: developer 69957e29afd2SMatthew G. Knepley */ 6996d71ae5a4SJacob 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[]) 6997d71ae5a4SJacob Faibussowitsch { 6998552f7358SJed Brown PetscInt numFields, foff, f; 6999552f7358SJed Brown 7000552f7358SJed Brown PetscFunctionBegin; 700108401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 70029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7003552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 70044acb8e1eSToby Isaac PetscInt fdof, cfdof; 7005552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 70064acb8e1eSToby Isaac PetscInt cind = 0, b; 70074acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7008552f7358SJed Brown 70099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 70109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7011552f7358SJed Brown if (!cfdof || setBC) { 701205586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 701305586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 701405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 701505586334SMatthew G. Knepley 701605586334SMatthew G. Knepley indices[ind] = off + foff + b; 701705586334SMatthew G. Knepley } 7018552f7358SJed Brown } else { 70199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 702005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 702105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 702205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 702305586334SMatthew G. Knepley 70244acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 702505586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7026552f7358SJed Brown ++cind; 7027552f7358SJed Brown } else { 702836fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7029552f7358SJed Brown } 7030552f7358SJed Brown } 7031552f7358SJed Brown } 703236fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7033552f7358SJed Brown foffs[f] += fdof; 7034552f7358SJed Brown } 7035552f7358SJed Brown PetscFunctionReturn(0); 7036552f7358SJed Brown } 7037552f7358SJed Brown 70387e29afd2SMatthew G. Knepley /* 70397e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 70407e29afd2SMatthew G. Knepley 70417e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7042645102dcSJed Brown 7043645102dcSJed Brown Notes: 7044645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7045645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 70467e29afd2SMatthew G. Knepley */ 7047d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7048d71ae5a4SJacob Faibussowitsch { 70497e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 70507e29afd2SMatthew G. Knepley 70517e29afd2SMatthew G. Knepley PetscFunctionBegin; 70529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 70537e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 70547e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 70557e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 70567e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 70577e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 70587e29afd2SMatthew G. Knepley 70599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 70609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 70619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7062645102dcSJed Brown if (!cfdof) { 706305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 706405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 706505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 706605586334SMatthew G. Knepley 706705586334SMatthew G. Knepley indices[ind] = foff + b; 706805586334SMatthew G. Knepley } 70697e29afd2SMatthew G. Knepley } else { 70709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 707105586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 707205586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 707305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 707405586334SMatthew G. Knepley 70757e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 707605586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 70777e29afd2SMatthew G. Knepley ++cind; 70787e29afd2SMatthew G. Knepley } else { 707905586334SMatthew G. Knepley indices[ind] = foff + b - cind; 70807e29afd2SMatthew G. Knepley } 70817e29afd2SMatthew G. Knepley } 70827e29afd2SMatthew G. Knepley } 70837e29afd2SMatthew G. Knepley foffs[f] += fdof; 70847e29afd2SMatthew G. Knepley } 70857e29afd2SMatthew G. Knepley PetscFunctionReturn(0); 70867e29afd2SMatthew G. Knepley } 70877e29afd2SMatthew G. Knepley 7088d71ae5a4SJacob 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) 7089d71ae5a4SJacob Faibussowitsch { 7090d3d1a6afSToby Isaac Mat cMat; 7091d3d1a6afSToby Isaac PetscSection aSec, cSec; 7092d3d1a6afSToby Isaac IS aIS; 7093d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7094d3d1a6afSToby Isaac const PetscInt *anchors; 7095e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 7096d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7097d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 7098d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 7099d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7100d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 7101d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 7102d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 71036ecaa68aSToby Isaac PetscScalar *newValues = NULL, *tmpValues; 7104d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7105d3d1a6afSToby Isaac 7106d3d1a6afSToby Isaac PetscFunctionBegin; 7107d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7108d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 71099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7110d3d1a6afSToby Isaac 71119566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7112d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7113d3d1a6afSToby Isaac if (aSec) { 71149566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 71159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 71169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7117d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7118d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7119d3d1a6afSToby Isaac * into the global matrix anyway) */ 7120d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7121d3d1a6afSToby Isaac PetscInt b = points[p]; 71224b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7123d3d1a6afSToby Isaac 71249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7125ad540459SPierre Jolivet if (!bSecDof) continue; 712648a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7127d3d1a6afSToby Isaac if (bDof) { 7128d3d1a6afSToby Isaac /* this point is constrained */ 7129d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7130d3d1a6afSToby Isaac PetscInt bOff, q; 7131d3d1a6afSToby Isaac 7132d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 7133d3d1a6afSToby Isaac newNumPoints += bDof; 71349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7135d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7136d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7137d3d1a6afSToby Isaac PetscInt aDof; 7138d3d1a6afSToby Isaac 71399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7140d3d1a6afSToby Isaac newNumIndices += aDof; 7141d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7142d3d1a6afSToby Isaac PetscInt fDof; 7143d3d1a6afSToby Isaac 71449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7145d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7146d3d1a6afSToby Isaac } 7147d3d1a6afSToby Isaac } 71489371c9d4SSatish Balay } else { 7149d3d1a6afSToby Isaac /* this point is not constrained */ 7150d3d1a6afSToby Isaac newNumPoints++; 71514b2f2278SToby Isaac newNumIndices += bSecDof; 7152d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7153d3d1a6afSToby Isaac PetscInt fDof; 7154d3d1a6afSToby Isaac 71559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7156d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7157d3d1a6afSToby Isaac } 7158d3d1a6afSToby Isaac } 7159d3d1a6afSToby Isaac } 7160d3d1a6afSToby Isaac } 7161d3d1a6afSToby Isaac if (!anyConstrained) { 716272b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 716372b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 716472b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 716572b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 71669566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 7167d3d1a6afSToby Isaac PetscFunctionReturn(0); 7168d3d1a6afSToby Isaac } 7169d3d1a6afSToby Isaac 71706ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 71716ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 71726ecaa68aSToby Isaac 7173f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7174d3d1a6afSToby Isaac 71756ecaa68aSToby Isaac if (!outPoints && !outValues) { 71766ecaa68aSToby Isaac if (offsets) { 7177ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 71786ecaa68aSToby Isaac } 71799566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 71806ecaa68aSToby Isaac PetscFunctionReturn(0); 71816ecaa68aSToby Isaac } 71826ecaa68aSToby Isaac 71831dca8a05SBarry 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); 7184d3d1a6afSToby Isaac 71859566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7186d3d1a6afSToby Isaac 7187d3d1a6afSToby Isaac /* workspaces */ 7188d3d1a6afSToby Isaac if (numFields) { 7189d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 71909566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 71919566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7192d3d1a6afSToby Isaac } 71939371c9d4SSatish Balay } else { 71949566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 71959566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0])); 7196d3d1a6afSToby Isaac } 7197d3d1a6afSToby Isaac 7198d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 7199d3d1a6afSToby Isaac if (numFields) { 72004b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 72014b2f2278SToby Isaac 7202d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7203d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 72044b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7205d3d1a6afSToby Isaac 72069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 72074b2f2278SToby Isaac if (!bSecDof) { 72084b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 72094b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 72104b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 72114b2f2278SToby Isaac } 72124b2f2278SToby Isaac continue; 72134b2f2278SToby Isaac } 721448a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7215d3d1a6afSToby Isaac if (bDof) { 7216d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7217d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 7218d3d1a6afSToby Isaac 72199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 72209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7221d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7222d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7223d3d1a6afSToby Isaac PetscInt aFDof; 7224d3d1a6afSToby Isaac 72259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 7226d3d1a6afSToby Isaac allFDof += aFDof; 7227d3d1a6afSToby Isaac } 7228d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = allFDof; 7229d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = fDof * allFDof; 7230d3d1a6afSToby Isaac } 72319371c9d4SSatish Balay } else { 7232d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7233d3d1a6afSToby Isaac PetscInt fDof; 7234d3d1a6afSToby Isaac 72359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7236d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = fDof; 7237d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = 0; 7238d3d1a6afSToby Isaac } 7239d3d1a6afSToby Isaac } 7240d3d1a6afSToby Isaac } 72414b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 72424b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 72434b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 7244d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7245d3d1a6afSToby Isaac newPointOffsets[f][p + 1] += newPointOffsets[f][p]; 7246d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] += pointMatOffsets[f][p]; 7247d3d1a6afSToby Isaac } 724819f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 724919f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 72509566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 7251d3d1a6afSToby Isaac } 72529371c9d4SSatish Balay } else { 7253d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7254d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 72554b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7256d3d1a6afSToby Isaac 72579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 72584b2f2278SToby Isaac if (!bSecDof) { 72594b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 72604b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 72614b2f2278SToby Isaac continue; 72624b2f2278SToby Isaac } 726348a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7264d3d1a6afSToby Isaac if (bDof) { 72654b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 7266d3d1a6afSToby Isaac 72679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7268d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7269d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 7270d3d1a6afSToby Isaac 72719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7272d3d1a6afSToby Isaac allDof += aDof; 7273d3d1a6afSToby Isaac } 7274d3d1a6afSToby Isaac newPointOffsets[0][p + 1] = allDof; 72754b2f2278SToby Isaac pointMatOffsets[0][p + 1] = bSecDof * allDof; 72769371c9d4SSatish Balay } else { 72774b2f2278SToby Isaac newPointOffsets[0][p + 1] = bSecDof; 7278d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] = 0; 7279d3d1a6afSToby Isaac } 7280d3d1a6afSToby Isaac } 7281d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 7282d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 7283d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7284d3d1a6afSToby Isaac newPointOffsets[0][p + 1] += newPointOffsets[0][p]; 7285d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] += pointMatOffsets[0][p]; 7286d3d1a6afSToby Isaac } 72879566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 7288d3d1a6afSToby Isaac } 7289d3d1a6afSToby Isaac 72906ecaa68aSToby Isaac /* output arrays */ 72919566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 72926ecaa68aSToby Isaac 7293d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 72949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 72959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 72969566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices)); 72979566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 7298d3d1a6afSToby Isaac if (numFields) { 7299d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 7300d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7301d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 73024b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7303d3d1a6afSToby Isaac 73049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7305ad540459SPierre Jolivet if (!bSecDof) continue; 730648a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7307d3d1a6afSToby Isaac if (bDof) { 7308d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7309d3d1a6afSToby Isaac 7310d3d1a6afSToby Isaac fStart[0] = 0; 7311d3d1a6afSToby Isaac fEnd[0] = 0; 7312d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7313d3d1a6afSToby Isaac PetscInt fDof; 7314d3d1a6afSToby Isaac 73159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7316d3d1a6afSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7317d3d1a6afSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7318d3d1a6afSToby Isaac } 73199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 73209566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7321d3d1a6afSToby Isaac 7322d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7323d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7324d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7325d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7326d3d1a6afSToby Isaac 7327d3d1a6afSToby Isaac fAnchorStart[f + 1] = fAnchorStart[f] + fDof; 7328d3d1a6afSToby Isaac fAnchorEnd[f + 1] = fAnchorStart[f + 1]; 7329d3d1a6afSToby Isaac } 73309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7331d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7332d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7333d3d1a6afSToby Isaac 7334d3d1a6afSToby 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 */ 7335d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7336d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 73379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 73389566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7339d3d1a6afSToby Isaac } 7340d3d1a6afSToby Isaac newP += bDof; 7341d3d1a6afSToby Isaac 73426ecaa68aSToby Isaac if (outValues) { 7343d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 734448a46eb9SPierre 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])); 7345d3d1a6afSToby Isaac } 73469371c9d4SSatish Balay } else { 7347d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7348d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7349d3d1a6afSToby Isaac newP++; 7350d3d1a6afSToby Isaac } 7351d3d1a6afSToby Isaac } 7352d3d1a6afSToby Isaac } else { 7353d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7354d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7355d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 73564b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7357d3d1a6afSToby Isaac 73589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7359ad540459SPierre Jolivet if (!bSecDof) continue; 736048a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7361d3d1a6afSToby Isaac if (bDof) { 7362d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7363d3d1a6afSToby Isaac 73649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 73659566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7366d3d1a6afSToby Isaac 73679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7368d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7369d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7370d3d1a6afSToby Isaac 7371d3d1a6afSToby 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 */ 7372d3d1a6afSToby Isaac 7373d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7374d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 73759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 73769566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7377d3d1a6afSToby Isaac } 7378d3d1a6afSToby Isaac newP += bDof; 7379d3d1a6afSToby Isaac 7380d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 738148a46eb9SPierre Jolivet if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p])); 73829371c9d4SSatish Balay } else { 7383d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7384d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7385d3d1a6afSToby Isaac newP++; 7386d3d1a6afSToby Isaac } 7387d3d1a6afSToby Isaac } 7388d3d1a6afSToby Isaac } 7389d3d1a6afSToby Isaac 73906ecaa68aSToby Isaac if (outValues) { 73919566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 73929566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices)); 7393d3d1a6afSToby Isaac /* multiply constraints on the right */ 7394d3d1a6afSToby Isaac if (numFields) { 7395d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7396d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7397d3d1a6afSToby Isaac 7398d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7399d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7400d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7401d3d1a6afSToby Isaac PetscInt c, r, k; 7402d3d1a6afSToby Isaac PetscInt dof; 7403d3d1a6afSToby Isaac 74049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7405ad540459SPierre Jolivet if (!dof) continue; 7406d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7407d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p + 1] - cStart; 7408d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7409d3d1a6afSToby Isaac 7410d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7411d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7412ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7413d3d1a6afSToby Isaac } 7414d3d1a6afSToby Isaac } 74159371c9d4SSatish Balay } else { 7416d3d1a6afSToby Isaac /* copy this column as is */ 7417d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7418ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7419d3d1a6afSToby Isaac } 7420d3d1a6afSToby Isaac } 7421d3d1a6afSToby Isaac oldOff += dof; 7422d3d1a6afSToby Isaac } 7423d3d1a6afSToby Isaac } 74249371c9d4SSatish Balay } else { 7425d3d1a6afSToby Isaac PetscInt oldOff = 0; 7426d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7427d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7428d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7429d3d1a6afSToby Isaac PetscInt c, r, k; 7430d3d1a6afSToby Isaac PetscInt dof; 7431d3d1a6afSToby Isaac 74329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7433ad540459SPierre Jolivet if (!dof) continue; 7434d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7435d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p + 1] - cStart; 7436d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7437d3d1a6afSToby Isaac 7438d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7439d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7440ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7441d3d1a6afSToby Isaac } 7442d3d1a6afSToby Isaac } 74439371c9d4SSatish Balay } else { 7444d3d1a6afSToby Isaac /* copy this column as is */ 7445d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7446ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7447d3d1a6afSToby Isaac } 7448d3d1a6afSToby Isaac } 7449d3d1a6afSToby Isaac oldOff += dof; 7450d3d1a6afSToby Isaac } 7451d3d1a6afSToby Isaac } 7452d3d1a6afSToby Isaac 74536ecaa68aSToby Isaac if (multiplyLeft) { 74549566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues)); 74559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices)); 7456d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7457d3d1a6afSToby Isaac if (numFields) { 7458d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7459d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7460d3d1a6afSToby Isaac 7461d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7462d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7463d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7464d3d1a6afSToby Isaac PetscInt c, r, k; 7465d3d1a6afSToby Isaac PetscInt dof; 7466d3d1a6afSToby Isaac 74679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7468d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7469d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p + 1] - rStart; 7470d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7471d3d1a6afSToby Isaac 7472d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7473d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7474ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7475d3d1a6afSToby Isaac } 7476d3d1a6afSToby Isaac } 74779371c9d4SSatish Balay } else { 7478d3d1a6afSToby Isaac /* copy this row as is */ 7479d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7480ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7481d3d1a6afSToby Isaac } 7482d3d1a6afSToby Isaac } 7483d3d1a6afSToby Isaac oldOff += dof; 7484d3d1a6afSToby Isaac } 7485d3d1a6afSToby Isaac } 74869371c9d4SSatish Balay } else { 7487d3d1a6afSToby Isaac PetscInt oldOff = 0; 7488d3d1a6afSToby Isaac 7489d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7490d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7491d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7492d3d1a6afSToby Isaac PetscInt c, r, k; 7493d3d1a6afSToby Isaac PetscInt dof; 7494d3d1a6afSToby Isaac 74959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7496d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7497d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p + 1] - rStart; 7498d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7499d3d1a6afSToby Isaac 7500d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7501d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7502ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7503d3d1a6afSToby Isaac } 7504d3d1a6afSToby Isaac } 75059371c9d4SSatish Balay } else { 7506d3d1a6afSToby Isaac /* copy this row as is */ 75079fc93327SToby Isaac for (r = 0; r < dof; r++) { 7508ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7509d3d1a6afSToby Isaac } 7510d3d1a6afSToby Isaac } 7511d3d1a6afSToby Isaac oldOff += dof; 7512d3d1a6afSToby Isaac } 7513d3d1a6afSToby Isaac } 7514d3d1a6afSToby Isaac 75159566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 75169371c9d4SSatish Balay } else { 75176ecaa68aSToby Isaac newValues = tmpValues; 75186ecaa68aSToby Isaac } 75196ecaa68aSToby Isaac } 75206ecaa68aSToby Isaac 7521d3d1a6afSToby Isaac /* clean up */ 75229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices)); 75239566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 75246ecaa68aSToby Isaac 7525d3d1a6afSToby Isaac if (numFields) { 7526d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 75279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 75289566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 75299566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7530d3d1a6afSToby Isaac } 75319371c9d4SSatish Balay } else { 75329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 75339566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 75349566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0])); 7535d3d1a6afSToby Isaac } 75369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7537d3d1a6afSToby Isaac 7538d3d1a6afSToby Isaac /* output */ 75396ecaa68aSToby Isaac if (outPoints) { 7540d3d1a6afSToby Isaac *outPoints = newPoints; 75419371c9d4SSatish Balay } else { 75429566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 75436ecaa68aSToby Isaac } 7544ad540459SPierre Jolivet if (outValues) *outValues = newValues; 7545ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 7546d3d1a6afSToby Isaac PetscFunctionReturn(0); 7547d3d1a6afSToby Isaac } 7548d3d1a6afSToby Isaac 75494a1e0b3eSMatthew G. Knepley /*@C 755071f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 75517cd05799SMatthew G. Knepley 75527cd05799SMatthew G. Knepley Not collective 75537cd05799SMatthew G. Knepley 75547cd05799SMatthew G. Knepley Input Parameters: 7555a1cb98faSBarry Smith + dm - The `DM` 7556a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7557a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 755871f0bbf9SMatthew G. Knepley . point - The point defining the closure 755971f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 75607cd05799SMatthew G. Knepley 756171f0bbf9SMatthew G. Knepley Output Parameters: 756271f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 756371f0bbf9SMatthew G. Knepley . indices - The dof indices 756471f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 756571f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 75667cd05799SMatthew G. Knepley 7567a1cb98faSBarry Smith Level: advanced 756836fa2b79SJed Brown 7569a1cb98faSBarry Smith Notes: 7570a1cb98faSBarry Smith Must call `DMPlexRestoreClosureIndices()` to free allocated memory 7571a1cb98faSBarry Smith 7572a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 757336fa2b79SJed Brown of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 757436fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 757536fa2b79SJed Brown indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 757636fa2b79SJed Brown indices (with the above semantics) are implied. 75777cd05799SMatthew G. Knepley 7578a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 7579a1cb98faSBarry Smith `PetscSection`, `DMGetGlobalSection()` 75804a1e0b3eSMatthew G. Knepley @*/ 7581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7582d71ae5a4SJacob Faibussowitsch { 758371f0bbf9SMatthew G. Knepley /* Closure ordering */ 75847773e69fSMatthew G. Knepley PetscSection clSection; 75857773e69fSMatthew G. Knepley IS clPoints; 758671f0bbf9SMatthew G. Knepley const PetscInt *clp; 758771f0bbf9SMatthew G. Knepley PetscInt *points; 758871f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 758971f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 75904acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 759171f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 759271f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 759371f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 759471f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 759571f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 759671f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 759771f0bbf9SMatthew G. Knepley 759871f0bbf9SMatthew G. Knepley PetscInt *idx; 759971f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 760071f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 76017773e69fSMatthew G. Knepley 760271f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 76037773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 76047773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 760536fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7606dadcf809SJacob Faibussowitsch if (numIndices) PetscValidIntPointer(numIndices, 6); 760771f0bbf9SMatthew G. Knepley if (indices) PetscValidPointer(indices, 7); 7608dadcf809SJacob Faibussowitsch if (outOffsets) PetscValidIntPointer(outOffsets, 8); 760971f0bbf9SMatthew G. Knepley if (values) PetscValidPointer(values, 9); 76109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 761163a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 76129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 761371f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 76149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7615c459fbc1SJed Brown if (useClPerm) { 7616c459fbc1SJed Brown PetscInt depth, clsize; 76179566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7618c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7619c459fbc1SJed Brown PetscInt dof; 76209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7621c459fbc1SJed Brown clsize += dof; 7622c459fbc1SJed Brown } 76239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7624c459fbc1SJed Brown } 762571f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 762671f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 76277773e69fSMatthew G. Knepley PetscInt dof, fdof; 76287773e69fSMatthew G. Knepley 76299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 76307773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 76319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 76327773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 76337773e69fSMatthew G. Knepley } 763471f0bbf9SMatthew G. Knepley Ni += dof; 76357773e69fSMatthew G. Knepley } 76367773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 76371dca8a05SBarry 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); 763871f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 763971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 76409566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 76419566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 764271f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 764371f0bbf9SMatthew G. Knepley if (values && flips[f]) { 764471f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 76456ecaa68aSToby Isaac 764671f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 764771f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 764871f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 764971f0bbf9SMatthew G. Knepley 76509566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 76519566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 765271f0bbf9SMatthew G. Knepley if (flip) { 765371f0bbf9SMatthew G. Knepley PetscInt i, j, k; 765471f0bbf9SMatthew G. Knepley 765571f0bbf9SMatthew G. Knepley if (!valCopy) { 76569566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 765771f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 765871f0bbf9SMatthew G. Knepley *values = valCopy; 765971f0bbf9SMatthew G. Knepley } 766071f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 766171f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 766271f0bbf9SMatthew G. Knepley 766371f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 766471f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 766571f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 76666ecaa68aSToby Isaac } 76676ecaa68aSToby Isaac } 766871f0bbf9SMatthew G. Knepley } 766971f0bbf9SMatthew G. Knepley foffset += fdof; 767071f0bbf9SMatthew G. Knepley } 767171f0bbf9SMatthew G. Knepley } 767271f0bbf9SMatthew G. Knepley } 767371f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 76749566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 767571f0bbf9SMatthew G. Knepley if (NclC) { 76769566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 767771f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 76789566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 76799566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 768071f0bbf9SMatthew G. Knepley } 768171f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 76829566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 76839566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 768471f0bbf9SMatthew G. Knepley } 76859566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 768671f0bbf9SMatthew G. Knepley Ncl = NclC; 768771f0bbf9SMatthew G. Knepley Ni = NiC; 768871f0bbf9SMatthew G. Knepley points = pointsC; 768971f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 769071f0bbf9SMatthew G. Knepley } 769171f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 76929566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 769371f0bbf9SMatthew G. Knepley if (Nf) { 769471f0bbf9SMatthew G. Knepley PetscInt idxOff; 769571f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 769671f0bbf9SMatthew G. Knepley 76979371c9d4SSatish Balay if (outOffsets) { 76989371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 76999371c9d4SSatish Balay } 77009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 770171f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 770271f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 770371f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 770471f0bbf9SMatthew G. Knepley 77059566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 77067773e69fSMatthew G. Knepley } 77077773e69fSMatthew G. Knepley } else { 770871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 770971f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 771071f0bbf9SMatthew G. Knepley 77119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 771271f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 771371f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 771471f0bbf9SMatthew G. Knepley * global section. */ 77159566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 771671f0bbf9SMatthew G. Knepley } 771771f0bbf9SMatthew G. Knepley } 771871f0bbf9SMatthew G. Knepley } else { 771971f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 772071f0bbf9SMatthew G. Knepley 772171f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 772271f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 77234acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 77244acb8e1eSToby Isaac 77259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 772671f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 772771f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 77289566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 77297773e69fSMatthew G. Knepley } 77307773e69fSMatthew G. Knepley } 773171f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 773271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 77339566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 77349566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 77354acb8e1eSToby Isaac } 773671f0bbf9SMatthew G. Knepley if (NclC) { 77379566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 77387773e69fSMatthew G. Knepley } else { 77399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 77407773e69fSMatthew G. Knepley } 774171f0bbf9SMatthew G. Knepley 774271f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 774371f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 77447773e69fSMatthew G. Knepley PetscFunctionReturn(0); 77457773e69fSMatthew G. Knepley } 77467773e69fSMatthew G. Knepley 77477cd05799SMatthew G. Knepley /*@C 774871f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 77497cd05799SMatthew G. Knepley 77507cd05799SMatthew G. Knepley Not collective 77517cd05799SMatthew G. Knepley 77527cd05799SMatthew G. Knepley Input Parameters: 7753a1cb98faSBarry Smith + dm - The `DM` 7754a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7755a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 775671f0bbf9SMatthew G. Knepley . point - The point defining the closure 775771f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 775871f0bbf9SMatthew G. Knepley 775971f0bbf9SMatthew G. Knepley Output Parameters: 776071f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 776171f0bbf9SMatthew G. Knepley . indices - The dof indices 776271f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 776371f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 776471f0bbf9SMatthew G. Knepley 7765a1cb98faSBarry Smith Level: advanced 776671f0bbf9SMatthew G. Knepley 7767a1cb98faSBarry Smith Notes: 7768a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 7769a1cb98faSBarry Smith 7770a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 777171f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 777271f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 777371f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 777471f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 77757cd05799SMatthew G. Knepley 7776a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 77777cd05799SMatthew G. Knepley @*/ 7778d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7779d71ae5a4SJacob Faibussowitsch { 77807773e69fSMatthew G. Knepley PetscFunctionBegin; 77817773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7782064a246eSJacob Faibussowitsch PetscValidPointer(indices, 7); 77839566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 77847773e69fSMatthew G. Knepley PetscFunctionReturn(0); 77857773e69fSMatthew G. Knepley } 77867773e69fSMatthew G. Knepley 77877f5d1fdeSMatthew G. Knepley /*@C 77887f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 77897f5d1fdeSMatthew G. Knepley 77907f5d1fdeSMatthew G. Knepley Not collective 77917f5d1fdeSMatthew G. Knepley 77927f5d1fdeSMatthew G. Knepley Input Parameters: 7793a1cb98faSBarry Smith + dm - The `DM` 7794ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section 7795ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section 77967f5d1fdeSMatthew G. Knepley . A - The matrix 7797a1cb98faSBarry Smith . point - The point in the `DM` 77987f5d1fdeSMatthew G. Knepley . values - The array of values 7799a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 78007f5d1fdeSMatthew G. Knepley 78017f5d1fdeSMatthew G. Knepley Level: intermediate 78027f5d1fdeSMatthew G. Knepley 7803a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 78047f5d1fdeSMatthew G. Knepley @*/ 7805d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7806d71ae5a4SJacob Faibussowitsch { 7807552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 7808552f7358SJed Brown PetscInt *indices; 780971f0bbf9SMatthew G. Knepley PetscInt numIndices; 781071f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 7811552f7358SJed Brown PetscErrorCode ierr; 7812552f7358SJed Brown 7813552f7358SJed Brown PetscFunctionBegin; 7814552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 78159566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 78163dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 78179566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 78183dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 78193dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7820552f7358SJed Brown 78219566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 78220d644c17SKarl Rupp 78239566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 7824d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 78254a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7826552f7358SJed Brown if (ierr) { 7827552f7358SJed Brown PetscMPIInt rank; 7828552f7358SJed Brown 78299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 78309566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 78319566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 78329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 78339566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 7834c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 7835552f7358SJed Brown } 78364a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 78374a1e0b3eSMatthew G. Knepley PetscInt i; 78389566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 783963a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 78409566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 78414a1e0b3eSMatthew G. Knepley } 784271f0bbf9SMatthew G. Knepley 78439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 78449566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 784571f0bbf9SMatthew G. Knepley PetscFunctionReturn(0); 78464acb8e1eSToby Isaac } 784771f0bbf9SMatthew G. Knepley 78484a1e0b3eSMatthew G. Knepley /*@C 78494a1e0b3eSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 78504a1e0b3eSMatthew G. Knepley 78514a1e0b3eSMatthew G. Knepley Not collective 78524a1e0b3eSMatthew G. Knepley 78534a1e0b3eSMatthew G. Knepley Input Parameters: 7854a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 78554a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 78564a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7857a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 78584a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 78594a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 78604a1e0b3eSMatthew G. Knepley . A - The matrix 7861a1cb98faSBarry Smith . point - The point in the `DM` 78624a1e0b3eSMatthew G. Knepley . values - The array of values 7863a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 78644a1e0b3eSMatthew G. Knepley 78654a1e0b3eSMatthew G. Knepley Level: intermediate 78664a1e0b3eSMatthew G. Knepley 7867a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 78684a1e0b3eSMatthew G. Knepley @*/ 7869d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7870d71ae5a4SJacob Faibussowitsch { 787171f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 787271f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 787371f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 787471f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 787571f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 787671f0bbf9SMatthew G. Knepley 787771f0bbf9SMatthew G. Knepley PetscFunctionBegin; 787871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 78799566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 788071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 78819566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 788271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 788371f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 78849566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 788571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 78869566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 788771f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 788871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 788971f0bbf9SMatthew G. Knepley 78909566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 78919566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 789271f0bbf9SMatthew G. Knepley 78939566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 7894d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 78954a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 789671f0bbf9SMatthew G. Knepley if (ierr) { 789771f0bbf9SMatthew G. Knepley PetscMPIInt rank; 789871f0bbf9SMatthew G. Knepley 78999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 79009566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 79019566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 79029566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 79039566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values)); 79049566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7905d3d1a6afSToby Isaac } 790671f0bbf9SMatthew G. Knepley 79079566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 79089566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 79099566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7910552f7358SJed Brown PetscFunctionReturn(0); 7911552f7358SJed Brown } 7912552f7358SJed Brown 7913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7914d71ae5a4SJacob Faibussowitsch { 7915de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 7916de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 7917de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 7918de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 791917c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7920de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 7921412e9a14SMatthew G. Knepley DMPolytopeType ct; 79224ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7923de41b84cSMatthew G. Knepley PetscErrorCode ierr; 7924de41b84cSMatthew G. Knepley 7925de41b84cSMatthew G. Knepley PetscFunctionBegin; 7926de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7927de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 79289566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 7929de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 79309566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 7931de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 79329566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 7933de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 79349566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 7935de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7936de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 79379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 793863a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 79399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 79409566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 7941de41b84cSMatthew G. Knepley /* Column indices */ 79429566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 79434ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 7944de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 7945de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 79469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 7947de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 7948de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7949de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 7950de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 7951de41b84cSMatthew G. Knepley ++q; 7952de41b84cSMatthew G. Knepley } 7953de41b84cSMatthew G. Knepley } 7954de41b84cSMatthew G. Knepley numCPoints = q; 7955de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 7956de41b84cSMatthew G. Knepley PetscInt fdof; 7957de41b84cSMatthew G. Knepley 79589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 79594ca5e9f5SMatthew G. Knepley if (!dof) continue; 7960de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 79619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 7962de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 7963de41b84cSMatthew G. Knepley } 7964de41b84cSMatthew G. Knepley numCIndices += dof; 7965de41b84cSMatthew G. Knepley } 7966de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 7967de41b84cSMatthew G. Knepley /* Row indices */ 79689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7969412e9a14SMatthew G. Knepley { 7970012bc364SMatthew G. Knepley DMPlexTransform tr; 7971012bc364SMatthew G. Knepley DMPolytopeType *rct; 7972012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7973012bc364SMatthew G. Knepley 79749566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 79759566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 79769566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7977012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 79789566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7979412e9a14SMatthew G. Knepley } 79809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 7981de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 7982de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 79839566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 7984de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 79859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 7986de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 7987de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 79889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 79894ca5e9f5SMatthew G. Knepley if (!dof) continue; 79909371c9d4SSatish Balay for (s = 0; s < q; ++s) 79919371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 79924ca5e9f5SMatthew G. Knepley if (s < q) continue; 7993de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 7994de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 7995de41b84cSMatthew G. Knepley ++q; 7996de41b84cSMatthew G. Knepley } 7997de41b84cSMatthew G. Knepley } 79989566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 7999de41b84cSMatthew G. Knepley } 8000de41b84cSMatthew G. Knepley numFPoints = q; 8001de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8002de41b84cSMatthew G. Knepley PetscInt fdof; 8003de41b84cSMatthew G. Knepley 80049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 80054ca5e9f5SMatthew G. Knepley if (!dof) continue; 8006de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 80079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8008de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8009de41b84cSMatthew G. Knepley } 8010de41b84cSMatthew G. Knepley numFIndices += dof; 8011de41b84cSMatthew G. Knepley } 8012de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8013de41b84cSMatthew G. Knepley 80141dca8a05SBarry 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); 80151dca8a05SBarry 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); 80169566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 80179566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8018de41b84cSMatthew G. Knepley if (numFields) { 80194acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 80204acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 80214acb8e1eSToby Isaac 80224acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 80239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 80249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8025de41b84cSMatthew G. Knepley } 80264acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 80279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 80289566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 80294acb8e1eSToby Isaac } 80304acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 80319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 80329566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 80334acb8e1eSToby Isaac } 80344acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 80359566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 80369566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8037de41b84cSMatthew G. Knepley } 8038de41b84cSMatthew G. Knepley } else { 80394acb8e1eSToby Isaac const PetscInt **permsF = NULL; 80404acb8e1eSToby Isaac const PetscInt **permsC = NULL; 80414acb8e1eSToby Isaac 80429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 80439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 80444acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 80454acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 80464acb8e1eSToby Isaac 80479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 80489566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8049de41b84cSMatthew G. Knepley } 80504acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 80514acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 80524acb8e1eSToby Isaac 80539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 80549566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8055de41b84cSMatthew G. Knepley } 80569566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 80579566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8058de41b84cSMatthew G. Knepley } 80599566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 80604acb8e1eSToby Isaac /* TODO: flips */ 8061d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8062de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8063de41b84cSMatthew G. Knepley if (ierr) { 8064de41b84cSMatthew G. Knepley PetscMPIInt rank; 8065de41b84cSMatthew G. Knepley 80669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 80679566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 80689566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 80699566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 80709566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8071de41b84cSMatthew G. Knepley } 80729566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 80739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 80749566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 80759566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8076de41b84cSMatthew G. Knepley PetscFunctionReturn(0); 8077de41b84cSMatthew G. Knepley } 8078de41b84cSMatthew G. Knepley 8079d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8080d71ae5a4SJacob Faibussowitsch { 80817c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 80827c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 80837c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 808417c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8085412e9a14SMatthew G. Knepley DMPolytopeType ct; 80867c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 80877c927364SMatthew G. Knepley 80887c927364SMatthew G. Knepley PetscFunctionBegin; 80897c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 80907c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 80919566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 80927c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 80939566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 80947c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 80959566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 80967c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 80979566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 80987c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 80999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 810063a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 81019566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 81029566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 81037c927364SMatthew G. Knepley /* Column indices */ 81049566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 81057c927364SMatthew G. Knepley maxFPoints = numCPoints; 81067c927364SMatthew G. Knepley /* Compress out points not in the section */ 81077c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 81089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 81097c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 81107c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 81117c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 81127c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 81137c927364SMatthew G. Knepley ++q; 81147c927364SMatthew G. Knepley } 81157c927364SMatthew G. Knepley } 81167c927364SMatthew G. Knepley numCPoints = q; 81177c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 81187c927364SMatthew G. Knepley PetscInt fdof; 81197c927364SMatthew G. Knepley 81209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 81217c927364SMatthew G. Knepley if (!dof) continue; 81227c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 81239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 81247c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 81257c927364SMatthew G. Knepley } 81267c927364SMatthew G. Knepley numCIndices += dof; 81277c927364SMatthew G. Knepley } 81287c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 81297c927364SMatthew G. Knepley /* Row indices */ 81309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8131412e9a14SMatthew G. Knepley { 8132012bc364SMatthew G. Knepley DMPlexTransform tr; 8133012bc364SMatthew G. Knepley DMPolytopeType *rct; 8134012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8135012bc364SMatthew G. Knepley 81369566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 81379566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 81389566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8139012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 81409566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8141412e9a14SMatthew G. Knepley } 81429566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 81437c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 81447c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 81459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 81467c927364SMatthew G. Knepley /* Compress out points not in the section */ 81479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 81487c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 81497c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 81509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 81517c927364SMatthew G. Knepley if (!dof) continue; 81529371c9d4SSatish Balay for (s = 0; s < q; ++s) 81539371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 81547c927364SMatthew G. Knepley if (s < q) continue; 81557c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 81567c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 81577c927364SMatthew G. Knepley ++q; 81587c927364SMatthew G. Knepley } 81597c927364SMatthew G. Knepley } 81609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 81617c927364SMatthew G. Knepley } 81627c927364SMatthew G. Knepley numFPoints = q; 81637c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 81647c927364SMatthew G. Knepley PetscInt fdof; 81657c927364SMatthew G. Knepley 81669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 81677c927364SMatthew G. Knepley if (!dof) continue; 81687c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 81699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 81707c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 81717c927364SMatthew G. Knepley } 81727c927364SMatthew G. Knepley numFIndices += dof; 81737c927364SMatthew G. Knepley } 81747c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 81757c927364SMatthew G. Knepley 81761dca8a05SBarry 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); 81771dca8a05SBarry 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); 81787c927364SMatthew G. Knepley if (numFields) { 81794acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 81804acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 81814acb8e1eSToby Isaac 81824acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 81839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 81849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 81857c927364SMatthew G. Knepley } 81864acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 81879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 81889566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 81894acb8e1eSToby Isaac } 81904acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 81919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 81929566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 81934acb8e1eSToby Isaac } 81944acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 81959566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 81969566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 81977c927364SMatthew G. Knepley } 81987c927364SMatthew G. Knepley } else { 81994acb8e1eSToby Isaac const PetscInt **permsF = NULL; 82004acb8e1eSToby Isaac const PetscInt **permsC = NULL; 82014acb8e1eSToby Isaac 82029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 82039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 82044acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 82054acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 82064acb8e1eSToby Isaac 82079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 82089566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 82097c927364SMatthew G. Knepley } 82104acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 82114acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 82124acb8e1eSToby Isaac 82139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 82149566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 82157c927364SMatthew G. Knepley } 82169566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 82179566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 82187c927364SMatthew G. Knepley } 82199566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 82209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 82217c927364SMatthew G. Knepley PetscFunctionReturn(0); 82227c927364SMatthew G. Knepley } 82237c927364SMatthew G. Knepley 82247cd05799SMatthew G. Knepley /*@C 82257cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 82267cd05799SMatthew G. Knepley 82277cd05799SMatthew G. Knepley Input Parameter: 8228a1cb98faSBarry Smith . dm - The `DMPLEX` object 82297cd05799SMatthew G. Knepley 82307cd05799SMatthew G. Knepley Output Parameter: 82317cd05799SMatthew G. Knepley . cellHeight - The height of a cell 82327cd05799SMatthew G. Knepley 82337cd05799SMatthew G. Knepley Level: developer 82347cd05799SMatthew G. Knepley 8235a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 82367cd05799SMatthew G. Knepley @*/ 8237d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8238d71ae5a4SJacob Faibussowitsch { 8239552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8240552f7358SJed Brown 8241552f7358SJed Brown PetscFunctionBegin; 8242552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8243dadcf809SJacob Faibussowitsch PetscValidIntPointer(cellHeight, 2); 8244552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 8245552f7358SJed Brown PetscFunctionReturn(0); 8246552f7358SJed Brown } 8247552f7358SJed Brown 82487cd05799SMatthew G. Knepley /*@C 82497cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 82507cd05799SMatthew G. Knepley 82517cd05799SMatthew G. Knepley Input Parameters: 8252a1cb98faSBarry Smith + dm - The `DMPLEX` object 82537cd05799SMatthew G. Knepley - cellHeight - The height of a cell 82547cd05799SMatthew G. Knepley 82557cd05799SMatthew G. Knepley Level: developer 82567cd05799SMatthew G. Knepley 8257a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 82587cd05799SMatthew G. Knepley @*/ 8259d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8260d71ae5a4SJacob Faibussowitsch { 8261552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8262552f7358SJed Brown 8263552f7358SJed Brown PetscFunctionBegin; 8264552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8265552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 8266552f7358SJed Brown PetscFunctionReturn(0); 8267552f7358SJed Brown } 8268552f7358SJed Brown 8269e6139122SMatthew G. Knepley /*@ 8270e6139122SMatthew G. Knepley DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 8271e6139122SMatthew G. Knepley 8272e6139122SMatthew G. Knepley Input Parameter: 8273a1cb98faSBarry Smith . dm - The `DMPLEX` object 8274e6139122SMatthew G. Knepley 8275e6139122SMatthew G. Knepley Output Parameters: 82762a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL 82772a9f31c0SMatthew G. Knepley - gcEnd - The upper bound on ghost cells, or NULL 8278e6139122SMatthew G. Knepley 82792a9f31c0SMatthew G. Knepley Level: advanced 8280e6139122SMatthew G. Knepley 8281a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 8282e6139122SMatthew G. Knepley @*/ 8283d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 8284d71ae5a4SJacob Faibussowitsch { 8285412e9a14SMatthew G. Knepley DMLabel ctLabel; 8286e6139122SMatthew G. Knepley 8287e6139122SMatthew G. Knepley PetscFunctionBegin; 8288e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 82899566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 82909566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd)); 8291695799ffSMatthew G. Knepley // Reset label for fast lookup 8292695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 8293e6139122SMatthew G. Knepley PetscFunctionReturn(0); 8294e6139122SMatthew G. Knepley } 8295e6139122SMatthew G. Knepley 8296d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8297d71ae5a4SJacob Faibussowitsch { 8298552f7358SJed Brown PetscSection section, globalSection; 8299552f7358SJed Brown PetscInt *numbers, p; 8300552f7358SJed Brown 8301552f7358SJed Brown PetscFunctionBegin; 8302d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 83039566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 83049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 830548a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 83069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 83079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 83089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8309552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 83109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8311ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8312ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8313552f7358SJed Brown } 83149566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8315ef48cebcSMatthew G. Knepley if (globalSize) { 8316ef48cebcSMatthew G. Knepley PetscLayout layout; 83179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 83189566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 83199566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8320ef48cebcSMatthew G. Knepley } 83219566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 83229566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 8323552f7358SJed Brown PetscFunctionReturn(0); 8324552f7358SJed Brown } 8325552f7358SJed Brown 8326d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8327d71ae5a4SJacob Faibussowitsch { 8328412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8329552f7358SJed Brown 8330552f7358SJed Brown PetscFunctionBegin; 83319566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 83329566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 83339566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 83349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 833581ed3555SMatthew G. Knepley PetscFunctionReturn(0); 8336552f7358SJed Brown } 833781ed3555SMatthew G. Knepley 83388dab3259SMatthew G. Knepley /*@ 83397cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 83407cd05799SMatthew G. Knepley 83417cd05799SMatthew G. Knepley Input Parameter: 8342a1cb98faSBarry Smith . dm - The `DMPLEX` object 83437cd05799SMatthew G. Knepley 83447cd05799SMatthew G. Knepley Output Parameter: 83457cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 83467cd05799SMatthew G. Knepley 83477cd05799SMatthew G. Knepley Level: developer 83487cd05799SMatthew G. Knepley 8349a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 83507cd05799SMatthew G. Knepley @*/ 8351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8352d71ae5a4SJacob Faibussowitsch { 835381ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 835481ed3555SMatthew G. Knepley 835581ed3555SMatthew G. Knepley PetscFunctionBegin; 835681ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 83579566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8358552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 8359552f7358SJed Brown PetscFunctionReturn(0); 8360552f7358SJed Brown } 8361552f7358SJed Brown 8362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8363d71ae5a4SJacob Faibussowitsch { 8364412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 836581ed3555SMatthew G. Knepley 836681ed3555SMatthew G. Knepley PetscFunctionBegin; 836781ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 83689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 83699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 837081ed3555SMatthew G. Knepley PetscFunctionReturn(0); 837181ed3555SMatthew G. Knepley } 837281ed3555SMatthew G. Knepley 83738dab3259SMatthew G. Knepley /*@ 83746aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 83757cd05799SMatthew G. Knepley 83767cd05799SMatthew G. Knepley Input Parameter: 8377a1cb98faSBarry Smith . dm - The `DMPLEX` object 83787cd05799SMatthew G. Knepley 83797cd05799SMatthew G. Knepley Output Parameter: 83807cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 83817cd05799SMatthew G. Knepley 83827cd05799SMatthew G. Knepley Level: developer 83837cd05799SMatthew G. Knepley 8384a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 83857cd05799SMatthew G. Knepley @*/ 8386d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8387d71ae5a4SJacob Faibussowitsch { 8388552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8389552f7358SJed Brown 8390552f7358SJed Brown PetscFunctionBegin; 8391552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 83929566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8393552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 8394552f7358SJed Brown PetscFunctionReturn(0); 8395552f7358SJed Brown } 8396552f7358SJed Brown 83978dab3259SMatthew G. Knepley /*@ 8398966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8399966484cfSJed Brown 8400966484cfSJed Brown Collective on dm 84017cd05799SMatthew G. Knepley 84027cd05799SMatthew G. Knepley Input Parameter: 8403a1cb98faSBarry Smith . dm - The `DMPLEX` object 84047cd05799SMatthew G. Knepley 84057cd05799SMatthew G. Knepley Output Parameter: 84067cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 84077cd05799SMatthew G. Knepley 8408a1cb98faSBarry Smith Level: developer 8409966484cfSJed Brown 8410a1cb98faSBarry Smith Notes: 8411a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8412966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8413966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8414966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8415966484cfSJed Brown 8416966484cfSJed Brown The partitioned mesh is 8417966484cfSJed Brown ``` 8418966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8419966484cfSJed Brown ``` 8420966484cfSJed Brown and its global numbering is 8421966484cfSJed Brown ``` 8422966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8423966484cfSJed Brown ``` 8424966484cfSJed Brown Then the global numbering is provided as 8425966484cfSJed Brown ``` 8426966484cfSJed Brown [0] Number of indices in set 5 8427966484cfSJed Brown [0] 0 0 8428966484cfSJed Brown [0] 1 1 8429966484cfSJed Brown [0] 2 3 8430966484cfSJed Brown [0] 3 4 8431966484cfSJed Brown [0] 4 -6 8432966484cfSJed Brown [1] Number of indices in set 3 8433966484cfSJed Brown [1] 0 2 8434966484cfSJed Brown [1] 1 5 8435966484cfSJed Brown [1] 2 6 8436966484cfSJed Brown ``` 8437966484cfSJed Brown 8438a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 84397cd05799SMatthew G. Knepley @*/ 8440d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8441d71ae5a4SJacob Faibussowitsch { 8442ef48cebcSMatthew G. Knepley IS nums[4]; 8443862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8444ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 84450c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8446ef48cebcSMatthew G. Knepley 8447ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8448ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 84500c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 84519566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 84520c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8453862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8454862913ffSStefano Zampini PetscInt end; 8455862913ffSStefano Zampini 8456862913ffSStefano Zampini depths[d] = depth - d; 84579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 84580c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8459862913ffSStefano Zampini } 84600c15888dSMatthew G. Knepley if (empty) 84610c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 84620c15888dSMatthew G. Knepley depths[d] = -1; 84630c15888dSMatthew G. Knepley starts[d] = -1; 84640c15888dSMatthew G. Knepley } 84650c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 84661c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8467ad540459SPierre 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]); 84680c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8469ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8470ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8471ef48cebcSMatthew G. Knepley 84729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 84739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8474ef48cebcSMatthew G. Knepley shift += gsize; 8475ef48cebcSMatthew G. Knepley } 84769566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)dm), depth + 1, nums, globalPointNumbers)); 84779566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 8478ef48cebcSMatthew G. Knepley PetscFunctionReturn(0); 8479ef48cebcSMatthew G. Knepley } 8480ef48cebcSMatthew G. Knepley 848108a22f4bSMatthew G. Knepley /*@ 848208a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 848308a22f4bSMatthew G. Knepley 848408a22f4bSMatthew G. Knepley Input Parameter: 8485a1cb98faSBarry Smith . dm - The `DMPLEX` object 848608a22f4bSMatthew G. Knepley 848708a22f4bSMatthew G. Knepley Output Parameter: 848808a22f4bSMatthew G. Knepley . ranks - The rank field 848908a22f4bSMatthew G. Knepley 8490a1cb98faSBarry Smith Options Database Key: 849108a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 849208a22f4bSMatthew G. Knepley 849308a22f4bSMatthew G. Knepley Level: intermediate 849408a22f4bSMatthew G. Knepley 8495a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()` 849608a22f4bSMatthew G. Knepley @*/ 8497d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8498d71ae5a4SJacob Faibussowitsch { 849908a22f4bSMatthew G. Knepley DM rdm; 850008a22f4bSMatthew G. Knepley PetscFE fe; 850108a22f4bSMatthew G. Knepley PetscScalar *r; 850208a22f4bSMatthew G. Knepley PetscMPIInt rank; 8503a55f9a55SMatthew G. Knepley DMPolytopeType ct; 850408a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8505a55f9a55SMatthew G. Knepley PetscBool simplex; 850608a22f4bSMatthew G. Knepley 850708a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8508f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8509f95ace6aSMatthew G. Knepley PetscValidPointer(ranks, 2); 85109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 85119566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 85129566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 85139566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 85149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8515a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 85169566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 85179566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 85189566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 85199566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 85209566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 85219566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 85229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 85239566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 852408a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 852508a22f4bSMatthew G. Knepley PetscScalar *lr; 852608a22f4bSMatthew G. Knepley 85279566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 852871f09efeSPierre Jolivet if (lr) *lr = rank; 852908a22f4bSMatthew G. Knepley } 85309566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 85319566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 853208a22f4bSMatthew G. Knepley PetscFunctionReturn(0); 853308a22f4bSMatthew G. Knepley } 853408a22f4bSMatthew G. Knepley 8535ca8062c8SMatthew G. Knepley /*@ 853618e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 853718e14f0cSMatthew G. Knepley 853818e14f0cSMatthew G. Knepley Input Parameters: 853918e14f0cSMatthew G. Knepley + dm - The DMPlex 854018e14f0cSMatthew G. Knepley - label - The DMLabel 854118e14f0cSMatthew G. Knepley 854218e14f0cSMatthew G. Knepley Output Parameter: 854318e14f0cSMatthew G. Knepley . val - The label value field 854418e14f0cSMatthew G. Knepley 854518e14f0cSMatthew G. Knepley Options Database Keys: 854618e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 854718e14f0cSMatthew G. Knepley 854818e14f0cSMatthew G. Knepley Level: intermediate 854918e14f0cSMatthew G. Knepley 8550a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()` 855118e14f0cSMatthew G. Knepley @*/ 8552d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8553d71ae5a4SJacob Faibussowitsch { 855418e14f0cSMatthew G. Knepley DM rdm; 855518e14f0cSMatthew G. Knepley PetscFE fe; 855618e14f0cSMatthew G. Knepley PetscScalar *v; 855718e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 855818e14f0cSMatthew G. Knepley 855918e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 856018e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 856118e14f0cSMatthew G. Knepley PetscValidPointer(label, 2); 856218e14f0cSMatthew G. Knepley PetscValidPointer(val, 3); 85639566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 85649566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 85659566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 85669566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "label_value")); 85679566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 85689566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 85699566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 85709566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 85719566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 85729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*val, "label_value")); 85739566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 857418e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 857518e14f0cSMatthew G. Knepley PetscScalar *lv; 857618e14f0cSMatthew G. Knepley PetscInt cval; 857718e14f0cSMatthew G. Knepley 85789566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 85799566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 858018e14f0cSMatthew G. Knepley *lv = cval; 858118e14f0cSMatthew G. Knepley } 85829566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 85839566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 858418e14f0cSMatthew G. Knepley PetscFunctionReturn(0); 858518e14f0cSMatthew G. Knepley } 858618e14f0cSMatthew G. Knepley 858718e14f0cSMatthew G. Knepley /*@ 8588ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8589ca8062c8SMatthew G. Knepley 859069916449SMatthew G. Knepley Input Parameter: 8591a1cb98faSBarry Smith . dm - The `DMPLEX` object 8592a1cb98faSBarry Smith 8593a1cb98faSBarry Smith Level: developer 8594ca8062c8SMatthew G. Knepley 859595eb5ee5SVaclav Hapla Notes: 859695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 859795eb5ee5SVaclav Hapla 859895eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8599ca8062c8SMatthew G. Knepley 8600a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8601ca8062c8SMatthew G. Knepley @*/ 8602d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 8603d71ae5a4SJacob Faibussowitsch { 8604ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8605ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8606ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 860757beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 860857beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8609ca8062c8SMatthew G. Knepley 8610ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8611ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86129566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 86139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 86149566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8615ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 86169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8617ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 86189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 86199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8620ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 862142e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 862242e66dfaSMatthew G. Knepley PetscInt d; 862342e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 86249371c9d4SSatish Balay if (cone[c] == cone[d]) { 86259371c9d4SSatish Balay dup = PETSC_TRUE; 86269371c9d4SSatish Balay break; 86279371c9d4SSatish Balay } 862842e66dfaSMatthew G. Knepley } 86299566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 86309566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8631ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8632ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8633ca8062c8SMatthew G. Knepley } 863442e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 863563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 863648a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 86379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 863863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 863948a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 86409566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 864163a3b9bcSJacob 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]); 8642f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8643ca8062c8SMatthew G. Knepley } 864442e66dfaSMatthew G. Knepley } 86459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 86469371c9d4SSatish Balay if (p != pp) { 86479371c9d4SSatish Balay storagecheck = PETSC_FALSE; 86489371c9d4SSatish Balay continue; 86499371c9d4SSatish Balay } 86509566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 86519566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8652ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 86539566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 86549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8655ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 86569566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 86579371c9d4SSatish Balay if (cone[c] != pp) { 86589371c9d4SSatish Balay c = 0; 86599371c9d4SSatish Balay break; 86609371c9d4SSatish Balay } 8661ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8662ca8062c8SMatthew G. Knepley } 8663ca8062c8SMatthew G. Knepley if (c >= coneSize) { 866463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 866548a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 86669566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 866763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 866848a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 86699566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 867063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8671ca8062c8SMatthew G. Knepley } 8672ca8062c8SMatthew G. Knepley } 8673ca8062c8SMatthew G. Knepley } 867457beb4faSStefano Zampini if (storagecheck) { 86759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 86769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 867763a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 867857beb4faSStefano Zampini } 8679ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8680ca8062c8SMatthew G. Knepley } 8681ca8062c8SMatthew G. Knepley 8682412e9a14SMatthew G. Knepley /* 8683412e9a14SMatthew 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. 8684412e9a14SMatthew G. Knepley */ 8685d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8686d71ae5a4SJacob Faibussowitsch { 8687412e9a14SMatthew G. Knepley DMPolytopeType cct; 8688412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8689412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8690412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8691412e9a14SMatthew G. Knepley 8692412e9a14SMatthew G. Knepley PetscFunctionBegin; 8693412e9a14SMatthew G. Knepley *unsplit = 0; 8694412e9a14SMatthew G. Knepley switch (ct) { 8695d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 8696d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 8697d71ae5a4SJacob Faibussowitsch break; 8698412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 86999566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 87009566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8701412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 87029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 8703412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8704412e9a14SMatthew G. Knepley } 8705412e9a14SMatthew G. Knepley break; 8706412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8707412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 87089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 87099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8710412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 87119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 87129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8713412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 87149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8715412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8716412e9a14SMatthew G. Knepley PetscInt p; 87179371c9d4SSatish Balay for (p = 0; p < npt; ++p) 87189371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 8719412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8720412e9a14SMatthew G. Knepley } 8721412e9a14SMatthew G. Knepley } 8722412e9a14SMatthew G. Knepley } 8723412e9a14SMatthew G. Knepley break; 8724d71ae5a4SJacob Faibussowitsch default: 8725d71ae5a4SJacob Faibussowitsch break; 8726412e9a14SMatthew G. Knepley } 8727412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 87289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8729412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8730412e9a14SMatthew G. Knepley } 8731412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 8732412e9a14SMatthew G. Knepley } 8733412e9a14SMatthew G. Knepley 8734ca8062c8SMatthew G. Knepley /*@ 8735ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8736ca8062c8SMatthew G. Knepley 8737ca8062c8SMatthew G. Knepley Input Parameters: 8738a1cb98faSBarry Smith + dm - The `DMPLEX` object 873958723a97SMatthew G. Knepley - cellHeight - Normally 0 8740ca8062c8SMatthew G. Knepley 8741a1cb98faSBarry Smith Level: developer 8742a1cb98faSBarry Smith 874395eb5ee5SVaclav Hapla Notes: 874495eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 874525c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 8746ca8062c8SMatthew G. Knepley 874795eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 874895eb5ee5SVaclav Hapla 8749a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8750ca8062c8SMatthew G. Knepley @*/ 8751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8752d71ae5a4SJacob Faibussowitsch { 8753412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 8754412e9a14SMatthew G. Knepley DMPolytopeType ct; 8755412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 8756ca8062c8SMatthew G. Knepley 8757ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8758ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87599566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 87609566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 87619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8762412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8763412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 8764412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 876558723a97SMatthew G. Knepley 87669566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 876763a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 8768412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 8769412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 87709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 877163a3b9bcSJacob 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)); 8772412e9a14SMatthew G. Knepley } 87739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 877458723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 877558723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 8776412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 877758723a97SMatthew G. Knepley } 87789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8779412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 8780412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8781412e9a14SMatthew G. Knepley PetscInt unsplit; 878242363296SMatthew G. Knepley 87839566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8784412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 878542363296SMatthew G. Knepley } 878663a3b9bcSJacob 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)); 878742363296SMatthew G. Knepley } 8788ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8789ca8062c8SMatthew G. Knepley } 87909bf0dad6SMatthew G. Knepley 87919bf0dad6SMatthew G. Knepley /*@ 87929bf0dad6SMatthew 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 87939bf0dad6SMatthew G. Knepley 8794a1cb98faSBarry Smith Collective on dm 8795899ea2b8SJacob Faibussowitsch 87969bf0dad6SMatthew G. Knepley Input Parameters: 8797a1cb98faSBarry Smith + dm - The `DMPLEX` object 87989bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 87999bf0dad6SMatthew G. Knepley 8800a1cb98faSBarry Smith Level: developer 8801a1cb98faSBarry Smith 880245da879fSVaclav Hapla Notes: 880345da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 880445da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 880545da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 880645da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 88079bf0dad6SMatthew G. Knepley 8808a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 880995eb5ee5SVaclav Hapla 8810a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 88119bf0dad6SMatthew G. Knepley @*/ 8812d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8813d71ae5a4SJacob Faibussowitsch { 8814ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8815899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 88169bf0dad6SMatthew G. Knepley 88179bf0dad6SMatthew G. Knepley PetscFunctionBegin; 88189bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88198f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 882045da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 88218f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 88228f6815adSVaclav Hapla PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"); 88238f6815adSVaclav Hapla PetscFunctionReturn(0); 8824899ea2b8SJacob Faibussowitsch } 8825899ea2b8SJacob Faibussowitsch 88269566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 88279566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 88289566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8829ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 88309566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 88313554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8832412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 8833412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 8834ba2698f1SMatthew G. Knepley DMPolytopeType ct; 8835412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 8836412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 88379bf0dad6SMatthew G. Knepley 88389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 88399566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8840412e9a14SMatthew G. Knepley if (unsplit) continue; 88419566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 88429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 88439566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 88449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 88459bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 88469bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 88479bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 88489bf0dad6SMatthew G. Knepley } 88499566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 885063a3b9bcSJacob 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); 88519bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 8852d4961f80SStefano Zampini DMPolytopeType fct; 88539bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 88549bf0dad6SMatthew G. Knepley 88559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 88569566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 88579bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 88589bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 88599bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 88609bf0dad6SMatthew G. Knepley } 886163a3b9bcSJacob 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]); 88629bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 8863b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 8864b5a892a1SMatthew G. Knepley PetscInt v1; 8865b5a892a1SMatthew G. Knepley 88669566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 886763a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 88689566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 886963a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 88709566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 887163a3b9bcSJacob 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]); 8872b5a892a1SMatthew G. Knepley } 88739bf0dad6SMatthew G. Knepley } 88749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 8875412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 88769bf0dad6SMatthew G. Knepley } 88779566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 88789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 88799bf0dad6SMatthew G. Knepley } 88803554e41dSMatthew G. Knepley } 8881552f7358SJed Brown PetscFunctionReturn(0); 8882552f7358SJed Brown } 88833913d7c8SMatthew G. Knepley 8884bb6a34a8SMatthew G. Knepley /*@ 8885bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 8886bb6a34a8SMatthew G. Knepley 8887bb6a34a8SMatthew G. Knepley Input Parameter: 8888a1cb98faSBarry Smith . dm - The `DMPLEX` object 8889a1cb98faSBarry Smith 8890a1cb98faSBarry Smith Level: developer 8891bb6a34a8SMatthew G. Knepley 889295eb5ee5SVaclav Hapla Notes: 889395eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 889495eb5ee5SVaclav Hapla 889595eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8896bb6a34a8SMatthew G. Knepley 8897a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8898bb6a34a8SMatthew G. Knepley @*/ 8899d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 8900d71ae5a4SJacob Faibussowitsch { 8901a2a9e04cSMatthew G. Knepley Vec coordinates; 8902bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 8903bb6a34a8SMatthew G. Knepley PetscReal vol; 890451a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 8905bb6a34a8SMatthew G. Knepley 8906bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 89079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 89089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 890951a74b61SMatthew G. Knepley if (dim != dE) PetscFunctionReturn(0); 89109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8911bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 89129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8913a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 89149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8915dd4c3f67SMatthew G. Knepley if (!coordinates) PetscFunctionReturn(0); 8916412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8917412e9a14SMatthew G. Knepley DMPolytopeType ct; 8918412e9a14SMatthew G. Knepley PetscInt unsplit; 8919412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 8920412e9a14SMatthew G. Knepley 89219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 8922412e9a14SMatthew G. Knepley switch (ct) { 8923412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 8924412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8925d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8926d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 8927d71ae5a4SJacob Faibussowitsch break; 8928d71ae5a4SJacob Faibussowitsch default: 8929d71ae5a4SJacob Faibussowitsch break; 8930412e9a14SMatthew G. Knepley } 8931412e9a14SMatthew G. Knepley switch (ct) { 8932412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 8933412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8934412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8935d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 8936d71ae5a4SJacob Faibussowitsch continue; 8937d71ae5a4SJacob Faibussowitsch default: 8938d71ae5a4SJacob Faibussowitsch break; 8939412e9a14SMatthew G. Knepley } 89409566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8941412e9a14SMatthew G. Knepley if (unsplit) continue; 89429566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 89431dca8a05SBarry 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); 894463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 89456858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 89466858538eSMatthew G. Knepley if (depth > 1) { 89479566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 89481dca8a05SBarry 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); 894963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 8950bb6a34a8SMatthew G. Knepley } 8951bb6a34a8SMatthew G. Knepley } 8952bb6a34a8SMatthew G. Knepley PetscFunctionReturn(0); 8953bb6a34a8SMatthew G. Knepley } 8954bb6a34a8SMatthew G. Knepley 895503da9461SVaclav Hapla /*@ 89567726db96SVaclav Hapla DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex. 89577726db96SVaclav Hapla 8958a1cb98faSBarry Smith Collective on dm 895903da9461SVaclav Hapla 896003da9461SVaclav Hapla Input Parameters: 8961a1cb98faSBarry Smith + dm - The `DMPLEX` object 8962a1cb98faSBarry Smith . pointSF - The `PetscSF`, or NULL for `PointSF` attached to `DM` 8963a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 8964a1cb98faSBarry Smith 8965a1cb98faSBarry Smith Level: developer 896603da9461SVaclav Hapla 8967e83a0d2dSVaclav Hapla Notes: 8968e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 896903da9461SVaclav Hapla 8970a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 897195eb5ee5SVaclav Hapla 8972d7d32a9aSMatthew G. Knepley Extra roots can come from priodic cuts, where additional points appear on the boundary 8973d7d32a9aSMatthew G. Knepley 8974a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 897503da9461SVaclav Hapla @*/ 8976d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 8977d71ae5a4SJacob Faibussowitsch { 89787726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 89797726db96SVaclav Hapla const PetscInt *locals; 89807726db96SVaclav Hapla const PetscSFNode *remotes; 8981f0cfc026SVaclav Hapla PetscBool distributed; 89827726db96SVaclav Hapla MPI_Comm comm; 89837726db96SVaclav Hapla PetscMPIInt rank; 898403da9461SVaclav Hapla 898503da9461SVaclav Hapla PetscFunctionBegin; 898603da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89877726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 89887726db96SVaclav Hapla else pointSF = dm->sf; 89897726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 89907726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 89917726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 89927726db96SVaclav Hapla { 89937726db96SVaclav Hapla PetscMPIInt mpiFlag; 89947726db96SVaclav Hapla 89957726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 89967726db96SVaclav 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); 89977726db96SVaclav Hapla } 89987726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 89999566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 90007726db96SVaclav Hapla if (!distributed) { 90017726db96SVaclav 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); 90028918e3e2SVaclav Hapla PetscFunctionReturn(0); 90038918e3e2SVaclav Hapla } 90047726db96SVaclav 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); 90057726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 900603da9461SVaclav Hapla 90077726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 90087726db96SVaclav Hapla { 90097726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 90107726db96SVaclav Hapla 90117726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 90127726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9013d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 90147726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 90157726db96SVaclav Hapla } 90167726db96SVaclav Hapla 90177726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 90187726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 90197726db96SVaclav 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); 90207726db96SVaclav Hapla } 90217726db96SVaclav Hapla 90227726db96SVaclav Hapla /* Check there are no cells in interface */ 90237726db96SVaclav Hapla if (!overlap) { 90247726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 90257726db96SVaclav Hapla 90269566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 90279566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9028f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 90297726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9030f5869d18SMatthew G. Knepley 90317726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 90327726db96SVaclav Hapla } 903303da9461SVaclav Hapla } 9034ece87651SVaclav Hapla 90357726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 90367726db96SVaclav Hapla { 90377726db96SVaclav Hapla const PetscInt *rootdegree; 90387726db96SVaclav Hapla 90397726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 90407726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9041f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 90427726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9043f5869d18SMatthew G. Knepley const PetscInt *cone; 9044f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9045f5869d18SMatthew G. Knepley 90469566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 90479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9048f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9049f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 90507726db96SVaclav Hapla if (locals) { 90519566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 90527726db96SVaclav Hapla } else { 90537726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 90547726db96SVaclav Hapla } 905563a3b9bcSJacob 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]); 9056f5869d18SMatthew G. Knepley } 9057f5869d18SMatthew G. Knepley } 9058ece87651SVaclav Hapla } 90597726db96SVaclav Hapla } 906003da9461SVaclav Hapla PetscFunctionReturn(0); 906103da9461SVaclav Hapla } 906203da9461SVaclav Hapla 90637f9d8d6cSVaclav Hapla /*@ 90647f9d8d6cSVaclav Hapla DMPlexCheck - Perform various checks of Plex sanity 90657f9d8d6cSVaclav Hapla 90667f9d8d6cSVaclav Hapla Input Parameter: 9067a1cb98faSBarry Smith . dm - The `DMPLEX` object 9068a1cb98faSBarry Smith 9069a1cb98faSBarry Smith Level: developer 90707f9d8d6cSVaclav Hapla 90717f9d8d6cSVaclav Hapla Notes: 90727f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 90737f9d8d6cSVaclav Hapla 90747f9d8d6cSVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 90757f9d8d6cSVaclav Hapla 90767f9d8d6cSVaclav Hapla Currently does not include DMPlexCheckCellShape(). 90777f9d8d6cSVaclav Hapla 9078a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, DMCreate(), DMSetFromOptions() 90797f9d8d6cSVaclav Hapla @*/ 9080d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9081d71ae5a4SJacob Faibussowitsch { 90827f9d8d6cSVaclav Hapla PetscInt cellHeight; 90837f9d8d6cSVaclav Hapla 9084b5a892a1SMatthew G. Knepley PetscFunctionBegin; 90857f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 90869566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 90879566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 90889566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 90899566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9090d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 90919566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 9092b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 9093b5a892a1SMatthew G. Knepley } 9094b5a892a1SMatthew G. Knepley 90959371c9d4SSatish Balay typedef struct cell_stats { 9096068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9097068a5610SStefano Zampini PetscInt count; 9098068a5610SStefano Zampini } cell_stats_t; 9099068a5610SStefano Zampini 9100d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9101d71ae5a4SJacob Faibussowitsch { 9102068a5610SStefano Zampini PetscInt i, N = *len; 9103068a5610SStefano Zampini 9104068a5610SStefano Zampini for (i = 0; i < N; i++) { 9105068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9106068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9107068a5610SStefano Zampini 9108068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9109068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9110068a5610SStefano Zampini B->sum += A->sum; 9111068a5610SStefano Zampini B->squaresum += A->squaresum; 9112068a5610SStefano Zampini B->count += A->count; 9113068a5610SStefano Zampini } 9114068a5610SStefano Zampini } 9115068a5610SStefano Zampini 9116068a5610SStefano Zampini /*@ 911743fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9118068a5610SStefano Zampini 91198261a58bSMatthew G. Knepley Collective on dm 91208261a58bSMatthew G. Knepley 9121068a5610SStefano Zampini Input Parameters: 9122a1cb98faSBarry Smith + dm - The `DMPLEX` object 912343fa8764SMatthew G. Knepley . output - If true, statistics will be displayed on stdout 9124a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9125a1cb98faSBarry Smith 9126a1cb98faSBarry Smith Level: developer 9127068a5610SStefano Zampini 912895eb5ee5SVaclav Hapla Notes: 912995eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 913095eb5ee5SVaclav Hapla 9131a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9132068a5610SStefano Zampini 9133a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9134068a5610SStefano Zampini @*/ 9135d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9136d71ae5a4SJacob Faibussowitsch { 9137068a5610SStefano Zampini DM dmCoarse; 913843fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 913943fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 914043fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 914143fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9142412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 914343fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9144068a5610SStefano Zampini 9145068a5610SStefano Zampini PetscFunctionBegin; 9146068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9147068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9148068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9149068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9150068a5610SStefano Zampini stats.count = 0; 9151068a5610SStefano Zampini 91529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 91539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 91549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 91559566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 91569566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 91579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9158412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9159068a5610SStefano Zampini PetscInt i; 9160068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9161068a5610SStefano Zampini 91629566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 916363a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 916443fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9165068a5610SStefano Zampini frobJ += J[i] * J[i]; 9166068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9167068a5610SStefano Zampini } 9168068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9169068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9170068a5610SStefano Zampini 9171068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9172068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9173068a5610SStefano Zampini stats.sum += cond; 9174068a5610SStefano Zampini stats.squaresum += cond2; 9175068a5610SStefano Zampini stats.count++; 91768261a58bSMatthew G. Knepley if (output && cond > limit) { 917743fa8764SMatthew G. Knepley PetscSection coordSection; 917843fa8764SMatthew G. Knepley Vec coordsLocal; 917943fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 918043fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 918143fa8764SMatthew G. Knepley 91829566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 91839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 91849566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 918563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 918643fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 918763a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 918843fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 91899566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 91909566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 919143fa8764SMatthew G. Knepley } 91929566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 919343fa8764SMatthew G. Knepley } 91949566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 919543fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 919643fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 919743fa8764SMatthew G. Knepley 919843fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 919943fa8764SMatthew G. Knepley PetscReal len; 920043fa8764SMatthew G. Knepley 92019566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 920263a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 920343fa8764SMatthew G. Knepley } 920443fa8764SMatthew G. Knepley } 92059566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 92069566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 920743fa8764SMatthew G. Knepley } 9208068a5610SStefano Zampini } 92099566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9210068a5610SStefano Zampini 9211068a5610SStefano Zampini if (size > 1) { 9212068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9213068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9214068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9215068a5610SStefano Zampini MPI_Op statReduce; 9216068a5610SStefano Zampini 92179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 92189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 92199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 92209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 92219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 92229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9223068a5610SStefano Zampini } else { 92249566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9225068a5610SStefano Zampini } 9226dd400576SPatrick Sanan if (rank == 0) { 9227068a5610SStefano Zampini count = globalStats.count; 9228068a5610SStefano Zampini min = globalStats.min; 9229068a5610SStefano Zampini max = globalStats.max; 9230068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9231068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9232068a5610SStefano Zampini } 9233068a5610SStefano Zampini 923448a46eb9SPierre 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)); 92359566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9236068a5610SStefano Zampini 92379566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9238068a5610SStefano Zampini if (dmCoarse) { 9239068a5610SStefano Zampini PetscBool isplex; 9240068a5610SStefano Zampini 92419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 92421baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9243068a5610SStefano Zampini } 9244068a5610SStefano Zampini PetscFunctionReturn(0); 9245068a5610SStefano Zampini } 9246068a5610SStefano Zampini 9247f108dbd7SJacob Faibussowitsch /*@ 9248f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9249f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9250f108dbd7SJacob Faibussowitsch 92516ed19f2fSJacob Faibussowitsch Collective on dm 9252f108dbd7SJacob Faibussowitsch 9253f108dbd7SJacob Faibussowitsch Input Parameters: 9254a1cb98faSBarry Smith + dm - The `DMPLEX` object 9255a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9256f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9257f108dbd7SJacob Faibussowitsch 9258f108dbd7SJacob Faibussowitsch Output Parameters: 9259f108dbd7SJacob Faibussowitsch + OrthQual - Vec containing orthogonal quality per cell 9260a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9261f108dbd7SJacob Faibussowitsch 9262f108dbd7SJacob Faibussowitsch Options Database Keys: 9263a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9264f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9265f108dbd7SJacob Faibussowitsch 9266a1cb98faSBarry Smith Level: intermediate 9267a1cb98faSBarry Smith 9268f108dbd7SJacob Faibussowitsch Notes: 9269f108dbd7SJacob Faibussowitsch Orthogonal quality is given by the following formula: 9270f108dbd7SJacob Faibussowitsch 9271a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9272f108dbd7SJacob Faibussowitsch 9273f108dbd7SJacob 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 9274f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9275f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9276f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9277f108dbd7SJacob Faibussowitsch 9278f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9279f108dbd7SJacob Faibussowitsch 9280a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9281f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9282f108dbd7SJacob Faibussowitsch 9283f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9284f108dbd7SJacob Faibussowitsch 9285a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9286f108dbd7SJacob Faibussowitsch @*/ 9287d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9288d71ae5a4SJacob Faibussowitsch { 92896ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 92906ed19f2fSJacob Faibussowitsch PetscInt *idx; 92916ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9292f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 92936ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9294f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9295f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9296f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9297f108dbd7SJacob Faibussowitsch IS glob; 9298f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9299f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9300f108dbd7SJacob Faibussowitsch 9301f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9302f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9303ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 9304f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQual, 4); 93056bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 93069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 93079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 930863a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 93096ed19f2fSJacob Faibussowitsch { 93106ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 93116ed19f2fSJacob Faibussowitsch 93129566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9313f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9314f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9315f108dbd7SJacob Faibussowitsch 93169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 931798921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9318f108dbd7SJacob Faibussowitsch } 93196ed19f2fSJacob Faibussowitsch } 9320f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 9321f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQualLabel, 5); 93229566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 93239566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 93249371c9d4SSatish Balay } else { 93259371c9d4SSatish Balay *OrthQualLabel = NULL; 93269371c9d4SSatish Balay } 93279566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 93289566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 93299566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 93309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 93319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 93329566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 93339566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 93349566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 93359566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 93369566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 93379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 93389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 93399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 93409566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 93419566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 93429566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 93439566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 93449566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 93456ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 93466ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9347f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9348f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9349898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9350f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9351f108dbd7SJacob Faibussowitsch 93526ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9353f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9354f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 93559566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 93569566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9357f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 93589566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 93596ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 93606ed19f2fSJacob Faibussowitsch PetscInt i; 93616ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9362f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9363f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9364f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9365f108dbd7SJacob Faibussowitsch 9366f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9367f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 93689566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9369f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 93706ed19f2fSJacob Faibussowitsch { 93716ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 93726ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 93736ed19f2fSJacob Faibussowitsch 93749566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 93759566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 93769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 93776ed19f2fSJacob Faibussowitsch } 9378f108dbd7SJacob Faibussowitsch 9379f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9380f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9381f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9382f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9383f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9384addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9385addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9386addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9387f108dbd7SJacob Faibussowitsch } 9388addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9389addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9390addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9391f108dbd7SJacob Faibussowitsch 9392f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9393f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9394f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9395f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9396f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9397f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9398f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9399f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9400f108dbd7SJacob Faibussowitsch } 9401ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9402ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9403f108dbd7SJacob Faibussowitsch } 94049566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 94059566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9406f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 94076ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9408f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 94099566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9410f108dbd7SJacob Faibussowitsch } 9411f108dbd7SJacob Faibussowitsch } 94129566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 94139566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 94149566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 94159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 94169566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 94179566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9418f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 94199566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9420f108dbd7SJacob Faibussowitsch } 94219566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 94229566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vwr)); 94239566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 9424f108dbd7SJacob Faibussowitsch PetscFunctionReturn(0); 9425f108dbd7SJacob Faibussowitsch } 9426f108dbd7SJacob Faibussowitsch 9427d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 94281eb70e55SToby Isaac * interpolator construction */ 9429d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9430d71ae5a4SJacob Faibussowitsch { 94311eb70e55SToby Isaac PetscSection section, newSection, gsection; 94321eb70e55SToby Isaac PetscSF sf; 94331eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 94341eb70e55SToby Isaac 94351eb70e55SToby Isaac PetscFunctionBegin; 94361eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94371eb70e55SToby Isaac PetscValidPointer(odm, 2); 94389566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 94399566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 94409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 94411eb70e55SToby Isaac if (!ghasConstraints) { 94429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 94431eb70e55SToby Isaac *odm = dm; 94441eb70e55SToby Isaac PetscFunctionReturn(0); 94451eb70e55SToby Isaac } 94469566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 94479566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 94489566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 94499566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 94509566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 94519566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 94529566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 94531eb70e55SToby Isaac PetscFunctionReturn(0); 94541eb70e55SToby Isaac } 94551eb70e55SToby Isaac 9456d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9457d71ae5a4SJacob Faibussowitsch { 94581eb70e55SToby Isaac DM dmco, dmfo; 94591eb70e55SToby Isaac Mat interpo; 94601eb70e55SToby Isaac Vec rscale; 94611eb70e55SToby Isaac Vec cglobalo, clocal; 94621eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 94631eb70e55SToby Isaac PetscBool regular; 94641eb70e55SToby Isaac 94651eb70e55SToby Isaac PetscFunctionBegin; 94669566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 94679566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 94689566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 94699566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 94709566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 94719566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 94729566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 94739566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 94749566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 94759566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 94769566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 94779566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 94789566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 94799566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 94809566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 94819566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 94829566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 94839566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 94849566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 94859566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 94869566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 94879566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 94889566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 94899566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 94901eb70e55SToby Isaac *shift = fglobal; 94919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 94929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 94939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 94949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 94959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 94969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 94979566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 94989566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 94991eb70e55SToby Isaac PetscFunctionReturn(0); 95001eb70e55SToby Isaac } 95011eb70e55SToby Isaac 9502d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9503d71ae5a4SJacob Faibussowitsch { 95041eb70e55SToby Isaac PetscObject shifto; 95051eb70e55SToby Isaac Vec shift; 95061eb70e55SToby Isaac 95071eb70e55SToby Isaac PetscFunctionBegin; 95081eb70e55SToby Isaac if (!interp) { 95091eb70e55SToby Isaac Vec rscale; 95101eb70e55SToby Isaac 95119566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 95129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 95131eb70e55SToby Isaac } else { 95149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 95151eb70e55SToby Isaac } 95169566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 95171eb70e55SToby Isaac if (!shifto) { 95189566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 95199566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 95201eb70e55SToby Isaac shifto = (PetscObject)shift; 95219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 95221eb70e55SToby Isaac } 95231eb70e55SToby Isaac shift = (Vec)shifto; 95249566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 95259566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 95269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 95271eb70e55SToby Isaac PetscFunctionReturn(0); 95281eb70e55SToby Isaac } 95291eb70e55SToby Isaac 9530bceba477SMatthew G. Knepley /* Pointwise interpolation 9531bceba477SMatthew G. Knepley Just code FEM for now 9532bceba477SMatthew G. Knepley u^f = I u^c 95334ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 95344ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 95354ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9536bceba477SMatthew G. Knepley */ 9537d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9538d71ae5a4SJacob Faibussowitsch { 9539bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9540bceba477SMatthew G. Knepley PetscInt m, n; 9541a063dac3SMatthew G. Knepley void *ctx; 954268132eb9SMatthew G. Knepley DM cdm; 9543cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9544bceba477SMatthew G. Knepley 9545bceba477SMatthew G. Knepley PetscFunctionBegin; 95469566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 95479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 95489566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 95499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 955068132eb9SMatthew G. Knepley 95519566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 95529566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 95539566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 95549566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 95559566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 955668132eb9SMatthew G. Knepley 95579566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 95589566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 95599566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 95609566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 95619566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 95624db47ee9SStefano Zampini if (scaling) { 95635d1c2e58SMatthew G. Knepley /* Use naive scaling */ 95649566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 95654db47ee9SStefano Zampini } 9566a063dac3SMatthew G. Knepley PetscFunctionReturn(0); 9567a063dac3SMatthew G. Knepley } 9568bceba477SMatthew G. Knepley 9569d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9570d71ae5a4SJacob Faibussowitsch { 95716dbf9973SLawrence Mitchell VecScatter ctx; 957290748bafSMatthew G. Knepley 9573a063dac3SMatthew G. Knepley PetscFunctionBegin; 95749566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 95759566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 95769566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 9577bceba477SMatthew G. Knepley PetscFunctionReturn(0); 9578bceba477SMatthew G. Knepley } 9579bceba477SMatthew G. Knepley 9580d71ae5a4SJacob 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[]) 9581d71ae5a4SJacob Faibussowitsch { 958200635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 958300635df3SMatthew G. Knepley PetscInt c; 958400635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 95853e9753d6SMatthew G. Knepley } 95863e9753d6SMatthew G. Knepley 9587d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9588d71ae5a4SJacob Faibussowitsch { 9589b4937a87SMatthew G. Knepley DM dmc; 9590b4937a87SMatthew G. Knepley PetscDS ds; 9591b4937a87SMatthew G. Knepley Vec ones, locmass; 9592b4937a87SMatthew G. Knepley IS cellIS; 9593b4937a87SMatthew G. Knepley PetscFormKey key; 9594b4937a87SMatthew G. Knepley PetscInt depth; 9595b4937a87SMatthew G. Knepley 9596b4937a87SMatthew G. Knepley PetscFunctionBegin; 95979566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 95989566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 95999566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 96009566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 96019566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 96029566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 96039566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 96049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 96059566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 96069566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 96079566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9608b4937a87SMatthew G. Knepley key.label = NULL; 9609b4937a87SMatthew G. Knepley key.value = 0; 9610b4937a87SMatthew G. Knepley key.field = 0; 9611b4937a87SMatthew G. Knepley key.part = 0; 96129566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 96139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 96149566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 96159566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 96169566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 96179566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 96189566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 96199566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 9620b4937a87SMatthew G. Knepley PetscFunctionReturn(0); 9621b4937a87SMatthew G. Knepley } 9622b4937a87SMatthew G. Knepley 9623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9624d71ae5a4SJacob Faibussowitsch { 9625bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9626bd041c0cSMatthew G. Knepley PetscInt m, n; 9627bd041c0cSMatthew G. Knepley void *ctx; 9628bd041c0cSMatthew G. Knepley DM cdm; 9629bd041c0cSMatthew G. Knepley PetscBool regular; 9630bd041c0cSMatthew G. Knepley 9631bd041c0cSMatthew G. Knepley PetscFunctionBegin; 96323e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 96333e9753d6SMatthew G. Knepley DM dmc; 96343e9753d6SMatthew G. Knepley PetscDS ds; 9635b4937a87SMatthew G. Knepley PetscWeakForm wf; 96363e9753d6SMatthew G. Knepley Vec u; 96373e9753d6SMatthew G. Knepley IS cellIS; 963806ad1575SMatthew G. Knepley PetscFormKey key; 96393e9753d6SMatthew G. Knepley PetscInt depth; 96403e9753d6SMatthew G. Knepley 96419566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 96429566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 96439566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 96449566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 96459566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 96469566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 96479566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 96488d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 96499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 96509566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 96519566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 96526528b96dSMatthew G. Knepley key.label = NULL; 96536528b96dSMatthew G. Knepley key.value = 0; 96546528b96dSMatthew G. Knepley key.field = 0; 965506ad1575SMatthew G. Knepley key.part = 0; 96569566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 96579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 96588d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 96599566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 96603e9753d6SMatthew G. Knepley } else { 96619566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 96629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 96639566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 96649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9665bd041c0cSMatthew G. Knepley 96669566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 96679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 96689566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 96699566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9670bd041c0cSMatthew G. Knepley 96719566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 96729566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 96739566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 96749566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 96753e9753d6SMatthew G. Knepley } 96769566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 9677bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 9678bd041c0cSMatthew G. Knepley } 9679bd041c0cSMatthew G. Knepley 96800aef6b92SMatthew G. Knepley /*@ 96810aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 96820aef6b92SMatthew G. Knepley 96830aef6b92SMatthew G. Knepley Input Parameter: 9684a1cb98faSBarry Smith . dm - The `DMPLEX` object 96850aef6b92SMatthew G. Knepley 96860aef6b92SMatthew G. Knepley Output Parameter: 96870aef6b92SMatthew G. Knepley . regular - The flag 96880aef6b92SMatthew G. Knepley 96890aef6b92SMatthew G. Knepley Level: intermediate 96900aef6b92SMatthew G. Knepley 9691a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 96920aef6b92SMatthew G. Knepley @*/ 9693d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9694d71ae5a4SJacob Faibussowitsch { 96950aef6b92SMatthew G. Knepley PetscFunctionBegin; 96960aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9697dadcf809SJacob Faibussowitsch PetscValidBoolPointer(regular, 2); 96980aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 96990aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 97000aef6b92SMatthew G. Knepley } 97010aef6b92SMatthew G. Knepley 97020aef6b92SMatthew G. Knepley /*@ 97030aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 97040aef6b92SMatthew G. Knepley 97050aef6b92SMatthew G. Knepley Input Parameters: 9706a1cb98faSBarry Smith + dm - The `DMPLEX` object 97070aef6b92SMatthew G. Knepley - regular - The flag 97080aef6b92SMatthew G. Knepley 97090aef6b92SMatthew G. Knepley Level: intermediate 97100aef6b92SMatthew G. Knepley 9711a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 97120aef6b92SMatthew G. Knepley @*/ 9713d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9714d71ae5a4SJacob Faibussowitsch { 97150aef6b92SMatthew G. Knepley PetscFunctionBegin; 97160aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97170aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 97180aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 97190aef6b92SMatthew G. Knepley } 97200aef6b92SMatthew G. Knepley 9721a68b90caSToby Isaac /*@ 9722f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9723a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 9724a68b90caSToby Isaac 9725a1cb98faSBarry Smith Not Collective 9726a68b90caSToby Isaac 9727f899ff85SJose E. Roman Input Parameter: 9728a1cb98faSBarry Smith . dm - The `DMPLEX` object 9729a68b90caSToby Isaac 9730a68b90caSToby Isaac Output Parameters: 9731a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9732a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9733a68b90caSToby Isaac 9734a68b90caSToby Isaac Level: intermediate 9735a68b90caSToby Isaac 9736a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 9737a68b90caSToby Isaac @*/ 9738d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9739d71ae5a4SJacob Faibussowitsch { 9740a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9741a68b90caSToby Isaac 9742a68b90caSToby Isaac PetscFunctionBegin; 9743a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97449566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 9745a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 9746a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 9747a68b90caSToby Isaac PetscFunctionReturn(0); 9748a68b90caSToby Isaac } 9749a68b90caSToby Isaac 9750a68b90caSToby Isaac /*@ 9751f7c74593SToby Isaac DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9752f7c74593SToby Isaac when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9753a68b90caSToby Isaac point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9754a68b90caSToby Isaac 9755a1cb98faSBarry Smith Collective on dm 9756a68b90caSToby Isaac 9757a68b90caSToby Isaac Input Parameters: 9758a1cb98faSBarry Smith + dm - The `DMPLEX` object 9759a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 9760a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 9761a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 9762a68b90caSToby Isaac 9763a68b90caSToby Isaac Level: intermediate 9764a68b90caSToby Isaac 9765a1cb98faSBarry Smith Notes: 9766a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 9767a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 9768a1cb98faSBarry Smith 9769a1cb98faSBarry Smith The reference counts of anchorSection and anchorIS are incremented. 9770a1cb98faSBarry Smith 9771a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9772a68b90caSToby Isaac @*/ 9773d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9774d71ae5a4SJacob Faibussowitsch { 9775a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9776e228b242SToby Isaac PetscMPIInt result; 9777a68b90caSToby Isaac 9778a68b90caSToby Isaac PetscFunctionBegin; 9779a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9780e228b242SToby Isaac if (anchorSection) { 9781e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 97829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 97831dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 9784e228b242SToby Isaac } 9785e228b242SToby Isaac if (anchorIS) { 9786e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 97879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 97881dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 9789e228b242SToby Isaac } 9790a68b90caSToby Isaac 97919566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 97929566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 9793a68b90caSToby Isaac plex->anchorSection = anchorSection; 9794a68b90caSToby Isaac 97959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 97969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 9797a68b90caSToby Isaac plex->anchorIS = anchorIS; 9798a68b90caSToby Isaac 9799cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9800a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 9801a68b90caSToby Isaac const PetscInt *anchors; 9802a68b90caSToby Isaac 98039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 98049566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 98059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 9806a68b90caSToby Isaac for (a = 0; a < size; a++) { 9807a68b90caSToby Isaac PetscInt p; 9808a68b90caSToby Isaac 9809a68b90caSToby Isaac p = anchors[a]; 9810a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 9811a68b90caSToby Isaac PetscInt dof; 9812a68b90caSToby Isaac 98139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 9814a68b90caSToby Isaac if (dof) { 98159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 981663a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 9817a68b90caSToby Isaac } 9818a68b90caSToby Isaac } 9819a68b90caSToby Isaac } 98209566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 9821a68b90caSToby Isaac } 9822f7c74593SToby Isaac /* reset the generic constraints */ 98239566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 9824a68b90caSToby Isaac PetscFunctionReturn(0); 9825a68b90caSToby Isaac } 9826a68b90caSToby Isaac 9827d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9828d71ae5a4SJacob Faibussowitsch { 9829f7c74593SToby Isaac PetscSection anchorSection; 98306995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9831a68b90caSToby Isaac 9832a68b90caSToby Isaac PetscFunctionBegin; 9833a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 98349566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 98359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 98369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 98376995de1eSToby Isaac if (numFields) { 9838719ab38cSToby Isaac PetscInt f; 98399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 9840719ab38cSToby Isaac 9841719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 9842719ab38cSToby Isaac PetscInt numComp; 9843719ab38cSToby Isaac 98449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 98459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 9846719ab38cSToby Isaac } 98476995de1eSToby Isaac } 98489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 98499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 98506995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 98516995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 98526995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 98539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 9854a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 98559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 9856a68b90caSToby Isaac if (dof) { 98579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 98589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 9859a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 98609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 98619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 9862a68b90caSToby Isaac } 9863a68b90caSToby Isaac } 9864a68b90caSToby Isaac } 98659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 98669566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 9867a68b90caSToby Isaac PetscFunctionReturn(0); 9868a68b90caSToby Isaac } 9869a68b90caSToby Isaac 9870d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9871d71ae5a4SJacob Faibussowitsch { 9872f7c74593SToby Isaac PetscSection aSec; 9873ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 98740ac89760SToby Isaac const PetscInt *anchors; 98750ac89760SToby Isaac PetscInt numFields, f; 987666ad2231SToby Isaac IS aIS; 9877e19f7ee6SMark Adams MatType mtype; 9878e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 98790ac89760SToby Isaac 98800ac89760SToby Isaac PetscFunctionBegin; 98810ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 98829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 98839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 98849566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 98859566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 98869566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 98879566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 98889566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 98899566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 9890e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 9891e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9892e19f7ee6SMark Adams else mtype = MATSEQAIJ; 98939566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 98949566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 98959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 98966995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 98979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 98989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 98999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 99000ac89760SToby Isaac i[0] = 0; 99019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 99020ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 9903f19733c5SToby Isaac PetscInt rDof, rOff, r; 9904f19733c5SToby Isaac 99059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 9906f19733c5SToby Isaac if (!rDof) continue; 99079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 99080ac89760SToby Isaac if (numFields) { 99090ac89760SToby Isaac for (f = 0; f < numFields; f++) { 99100ac89760SToby Isaac annz = 0; 9911f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 9912f19733c5SToby Isaac a = anchors[rOff + r]; 9913ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 99149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 99150ac89760SToby Isaac annz += aDof; 99160ac89760SToby Isaac } 99179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 99189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 9919ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 99200ac89760SToby Isaac } 99212f7452b8SBarry Smith } else { 99220ac89760SToby Isaac annz = 0; 99239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 99240ac89760SToby Isaac for (q = 0; q < dof; q++) { 9925ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 9926ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 99279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 99280ac89760SToby Isaac annz += aDof; 99290ac89760SToby Isaac } 99309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 99319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 9932ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 99330ac89760SToby Isaac } 99340ac89760SToby Isaac } 99350ac89760SToby Isaac nnz = i[m]; 99369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 99370ac89760SToby Isaac offset = 0; 99380ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 99390ac89760SToby Isaac if (numFields) { 99400ac89760SToby Isaac for (f = 0; f < numFields; f++) { 99419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 99420ac89760SToby Isaac for (q = 0; q < dof; q++) { 99430ac89760SToby Isaac PetscInt rDof, rOff, r; 99449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 99459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 99460ac89760SToby Isaac for (r = 0; r < rDof; r++) { 99470ac89760SToby Isaac PetscInt s; 99480ac89760SToby Isaac 99490ac89760SToby Isaac a = anchors[rOff + r]; 9950ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 99519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 99529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 9953ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 99540ac89760SToby Isaac } 99550ac89760SToby Isaac } 99560ac89760SToby Isaac } 99572f7452b8SBarry Smith } else { 99589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 99590ac89760SToby Isaac for (q = 0; q < dof; q++) { 99600ac89760SToby Isaac PetscInt rDof, rOff, r; 99619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 99629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 99630ac89760SToby Isaac for (r = 0; r < rDof; r++) { 99640ac89760SToby Isaac PetscInt s; 99650ac89760SToby Isaac 99660ac89760SToby Isaac a = anchors[rOff + r]; 9967ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 99689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 99699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 9970ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 99710ac89760SToby Isaac } 99720ac89760SToby Isaac } 99730ac89760SToby Isaac } 99740ac89760SToby Isaac } 99759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 99769566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 99779566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 99789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 99790ac89760SToby Isaac PetscFunctionReturn(0); 99800ac89760SToby Isaac } 99810ac89760SToby Isaac 9982d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9983d71ae5a4SJacob Faibussowitsch { 9984f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9985f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 998666ad2231SToby Isaac Mat cMat; 998766ad2231SToby Isaac 998866ad2231SToby Isaac PetscFunctionBegin; 998966ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 99909566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 999166ad2231SToby Isaac if (anchorSection) { 999244a7f3ddSMatthew G. Knepley PetscInt Nf; 9993e228b242SToby Isaac 99949566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 99959566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 99969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 99979566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 99989566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 99999566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 100009566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 100019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1000266ad2231SToby Isaac } 1000366ad2231SToby Isaac PetscFunctionReturn(0); 1000466ad2231SToby Isaac } 10005a93c429eSMatthew G. Knepley 10006d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10007d71ae5a4SJacob Faibussowitsch { 10008a93c429eSMatthew G. Knepley IS subis; 10009a93c429eSMatthew G. Knepley PetscSection section, subsection; 10010a93c429eSMatthew G. Knepley 10011a93c429eSMatthew G. Knepley PetscFunctionBegin; 100129566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1001328b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1001428b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10015a93c429eSMatthew G. Knepley /* Create subdomain */ 100169566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 10017a93c429eSMatthew G. Knepley /* Create submodel */ 100189566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 100199566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 100209566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 100219566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 100229566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10023a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10024a93c429eSMatthew G. Knepley if (is) { 10025a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10026a93c429eSMatthew G. Knepley IS spIS; 10027a93c429eSMatthew G. Knepley const PetscInt *spmap; 10028a93c429eSMatthew G. Knepley PetscInt *subIndices; 10029a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10030a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10031a93c429eSMatthew G. Knepley 100329566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 100339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 100349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 100359566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 100369566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 100379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10038a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10039a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10040a93c429eSMatthew G. Knepley 100419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10042a93c429eSMatthew G. Knepley if (gdof > 0) { 10043a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10044a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10045a93c429eSMatthew G. Knepley 100469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 100479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10048a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10049a93c429eSMatthew G. Knepley } 10050a93c429eSMatthew G. Knepley subSize += pSubSize; 10051a93c429eSMatthew G. Knepley if (pSubSize) { 10052a93c429eSMatthew G. Knepley if (bs < 0) { 10053a93c429eSMatthew G. Knepley bs = pSubSize; 10054a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10055a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10056a93c429eSMatthew G. Knepley bs = 1; 10057a93c429eSMatthew G. Knepley } 10058a93c429eSMatthew G. Knepley } 10059a93c429eSMatthew G. Knepley } 10060a93c429eSMatthew G. Knepley } 10061a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 100629371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 100639371c9d4SSatish Balay bsLocal[1] = bs; 100649566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 100659371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 100669371c9d4SSatish Balay bs = 1; 100679371c9d4SSatish Balay } else { 100689371c9d4SSatish Balay bs = bsMinMax[0]; 100699371c9d4SSatish Balay } 100709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10071a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10072a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10073a93c429eSMatthew G. Knepley 100749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10075a93c429eSMatthew G. Knepley if (gdof > 0) { 10076a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10077a93c429eSMatthew G. Knepley 100789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10079a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10080a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10081a93c429eSMatthew G. Knepley 10082a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10083a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 100849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 100859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10086a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10087a93c429eSMatthew G. Knepley } 100889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 100899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10090ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10091a93c429eSMatthew G. Knepley } 10092a93c429eSMatthew G. Knepley } 10093a93c429eSMatthew G. Knepley } 100949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 100959566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10096a93c429eSMatthew G. Knepley if (bs > 1) { 10097a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10098a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10099a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10100a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 101019371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 101029371c9d4SSatish Balay set = 0; 101039371c9d4SSatish Balay break; 101049371c9d4SSatish Balay } 10105a93c429eSMatthew G. Knepley } 10106a93c429eSMatthew G. Knepley } 101079566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10108a93c429eSMatthew G. Knepley } 10109a93c429eSMatthew G. Knepley /* Attach nullspace */ 10110a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10111a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10112a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10113a93c429eSMatthew G. Knepley } 10114a93c429eSMatthew G. Knepley if (f < Nf) { 10115a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 101169566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 101176823f3c5SBlaise Bourdin 101189566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 101199566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10120a93c429eSMatthew G. Knepley } 10121a93c429eSMatthew G. Knepley } 10122a93c429eSMatthew G. Knepley PetscFunctionReturn(0); 10123a93c429eSMatthew G. Knepley } 10124c0f0dcc3SMatthew G. Knepley 10125c0f0dcc3SMatthew G. Knepley /*@ 10126c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10127c0f0dcc3SMatthew G. Knepley 10128a1cb98faSBarry Smith Input Parameters: 10129a1cb98faSBarry Smith + dm - The `DM` 10130a1cb98faSBarry Smith - dummy - unused argument 10131a1cb98faSBarry Smith 10132a1cb98faSBarry Smith Options Database Key: 10133a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10134c0f0dcc3SMatthew G. Knepley 10135c0f0dcc3SMatthew G. Knepley Level: developer 10136c0f0dcc3SMatthew G. Knepley 10137a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10138c0f0dcc3SMatthew G. Knepley @*/ 10139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10140d71ae5a4SJacob Faibussowitsch { 10141e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG) 10142c0f0dcc3SMatthew G. Knepley PetscStageLog stageLog; 10143c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10144c0f0dcc3SMatthew G. Knepley PetscLogStage stage; 10145c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10146c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10147c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10148c0f0dcc3SMatthew G. Knepley const char *name; 10149e5ed2c37SJose E. Roman #endif 10150c0f0dcc3SMatthew G. Knepley 10151c0f0dcc3SMatthew G. Knepley PetscFunctionBegin; 10152c0f0dcc3SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10153c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG) 101549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 101559566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 101569566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 101579566063dSJacob Faibussowitsch PetscCall(PetscLogGetStageLog(&stageLog)); 101589566063dSJacob Faibussowitsch PetscCall(PetscStageLogGetCurrent(stageLog, &stage)); 101599566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 101609566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 10161c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10162c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10163c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1016463a3b9bcSJacob 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))); 10165c0f0dcc3SMatthew G. Knepley #else 10166c0f0dcc3SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 10167c0f0dcc3SMatthew G. Knepley #endif 10168c0f0dcc3SMatthew G. Knepley PetscFunctionReturn(0); 10169c0f0dcc3SMatthew G. Knepley } 10170