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; 14252a1336SBarry Smith PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart; 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: 229318fe57SMatthew G. Knepley . 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 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 289318fe57SMatthew G. Knepley If the mesh has no cells, this returns PETSC_FALSE. 299318fe57SMatthew G. Knepley 309318fe57SMatthew G. Knepley Level: intermediate 319318fe57SMatthew G. Knepley 32db781477SPatrick Sanan .seealso `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 339318fe57SMatthew G. Knepley @*/ 349371c9d4SSatish Balay PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) { 359318fe57SMatthew G. Knepley DMPolytopeType ct; 369318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 379318fe57SMatthew G. Knepley 389318fe57SMatthew G. Knepley PetscFunctionBegin; 399566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 409371c9d4SSatish Balay if (cEnd <= cStart) { 419371c9d4SSatish Balay *simplex = PETSC_FALSE; 429371c9d4SSatish Balay PetscFunctionReturn(0); 439371c9d4SSatish Balay } 449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 459318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 469318fe57SMatthew G. Knepley PetscFunctionReturn(0); 479318fe57SMatthew G. Knepley } 489318fe57SMatthew G. Knepley 499318fe57SMatthew G. Knepley /*@ 50412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 51e5337592SStefano Zampini 52d8d19677SJose E. Roman Input Parameters: 53412e9a14SMatthew G. Knepley + dm - The DMPlex object 54412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 55e5337592SStefano Zampini 56e5337592SStefano Zampini Output Parameters: 57412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 58412e9a14SMatthew G. Knepley - cEnd - The upper bound on "normal"" cells 59e5337592SStefano Zampini 60412e9a14SMatthew G. Knepley Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 61e5337592SStefano Zampini 62412e9a14SMatthew G. Knepley Level: developer 63e5337592SStefano Zampini 64db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 65e5337592SStefano Zampini @*/ 669371c9d4SSatish Balay PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) { 67412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 68412e9a14SMatthew G. Knepley PetscInt cS, cE, c; 69e5337592SStefano Zampini 70e5337592SStefano Zampini PetscFunctionBegin; 719566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE)); 72412e9a14SMatthew G. Knepley for (c = cS; c < cE; ++c) { 73412e9a14SMatthew G. Knepley DMPolytopeType cct; 74412e9a14SMatthew G. Knepley 759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &cct)); 76412e9a14SMatthew G. Knepley if ((PetscInt)cct < 0) break; 77412e9a14SMatthew G. Knepley switch (cct) { 78ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 79ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 80ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 81ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 82ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 839371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: ct = cct; break; 84412e9a14SMatthew G. Knepley default: break; 85e5337592SStefano Zampini } 86412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) break; 87e5337592SStefano Zampini } 88412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) { 89412e9a14SMatthew G. Knepley DMLabel ctLabel; 90412e9a14SMatthew G. Knepley 919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 929566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE)); 93695799ffSMatthew G. Knepley // Reset label for fast lookup 94695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 95e5337592SStefano Zampini } 96412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 97412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 98e5337592SStefano Zampini PetscFunctionReturn(0); 99e5337592SStefano Zampini } 100e5337592SStefano Zampini 1019371c9d4SSatish Balay PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) { 102412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 103a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 1047e42fee7SMatthew G. Knepley 1057e42fee7SMatthew G. Knepley PetscFunctionBegin; 106e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 1079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1099566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 1109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1117e42fee7SMatthew G. Knepley if (field >= 0) { 1129566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 1139566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 1147e42fee7SMatthew G. Knepley } else { 1159566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 1169566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 1177e42fee7SMatthew G. Knepley } 1189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 119a99a26bcSAdrian Croucher if (globalvcdof[0]) { 1207e42fee7SMatthew G. Knepley *sStart = vStart; 1217e42fee7SMatthew G. Knepley *sEnd = vEnd; 122f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 1237e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 124a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 1257e42fee7SMatthew G. Knepley *sStart = cStart; 1267e42fee7SMatthew G. Knepley *sEnd = cEnd; 127f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 1287e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 129e630c359SToby Isaac } else { 130e630c359SToby Isaac if (field >= 0) { 131e630c359SToby Isaac const char *fieldname; 132e630c359SToby Isaac 1339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 13463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 135e630c359SToby Isaac } else { 13663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 137e630c359SToby Isaac } 138e630c359SToby Isaac } 1397e42fee7SMatthew G. Knepley PetscFunctionReturn(0); 1407e42fee7SMatthew G. Knepley } 1417e42fee7SMatthew G. Knepley 1426913077dSMatthew G. Knepley /*@ 1436913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 1446913077dSMatthew G. Knepley 1456913077dSMatthew G. Knepley Collective on dm 1466913077dSMatthew G. Knepley 1476913077dSMatthew G. Knepley Input Parameters: 1486913077dSMatthew G. Knepley + dm - The DMPlex 1496913077dSMatthew G. Knepley . n - The number of vectors 1506913077dSMatthew G. Knepley . u - The array of local vectors 1516913077dSMatthew G. Knepley - viewer - The Draw viewer 1526913077dSMatthew G. Knepley 1536913077dSMatthew G. Knepley Level: advanced 1546913077dSMatthew G. Knepley 155db781477SPatrick Sanan .seealso: `VecViewFromOptions()`, `VecView()` 1566913077dSMatthew G. Knepley @*/ 1579371c9d4SSatish Balay PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) { 1586913077dSMatthew G. Knepley PetscDS ds; 1596913077dSMatthew G. Knepley PetscDraw draw = NULL; 1606913077dSMatthew G. Knepley PetscDrawLG lg; 1616913077dSMatthew G. Knepley Vec coordinates; 1626913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 1636913077dSMatthew G. Knepley PetscReal *vals; 1646913077dSMatthew G. Knepley PetscInt *Nc; 1656913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 1666913077dSMatthew G. Knepley char **names; 1676913077dSMatthew G. Knepley 1686913077dSMatthew G. Knepley PetscFunctionBegin; 1699566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 1709566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 1719566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 1729566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 1736913077dSMatthew G. Knepley 1749566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 1756913077dSMatthew G. Knepley if (!draw) PetscFunctionReturn(0); 1769566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 1776913077dSMatthew G. Knepley 1789566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 1796913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 1806913077dSMatthew G. Knepley const char *vname; 1816913077dSMatthew G. Knepley 1829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 1836913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1846913077dSMatthew G. Knepley PetscObject disc; 1856913077dSMatthew G. Knepley const char *fname; 1866913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 1876913077dSMatthew G. Knepley 1889566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 1896913077dSMatthew G. Knepley /* TODO Create names for components */ 1906913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 1919566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 1929566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(tmpname, vname)); 1939566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN)); 1949566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN)); 1959566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 1966913077dSMatthew G. Knepley } 1976913077dSMatthew G. Knepley } 1986913077dSMatthew G. Knepley } 1999566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 2006913077dSMatthew G. Knepley /* Just add P_1 support for now */ 2019566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2039566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 2049566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 2056913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 2066913077dSMatthew G. Knepley PetscScalar *x, *svals; 2076913077dSMatthew G. Knepley 2089566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 2096913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 2109566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 2116913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 2126913077dSMatthew G. Knepley } 2139566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 2146913077dSMatthew G. Knepley } 2159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 2169566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 2179566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 2189566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 2196913077dSMatthew G. Knepley 2209566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 2219566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 2226913077dSMatthew G. Knepley PetscFunctionReturn(0); 2236913077dSMatthew G. Knepley } 2246913077dSMatthew G. Knepley 2259371c9d4SSatish Balay static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) { 2266913077dSMatthew G. Knepley DM dm; 2276913077dSMatthew G. Knepley 2286913077dSMatthew G. Knepley PetscFunctionBegin; 2299566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 2309566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 2316913077dSMatthew G. Knepley PetscFunctionReturn(0); 2326913077dSMatthew G. Knepley } 2336913077dSMatthew G. Knepley 2349371c9d4SSatish Balay static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) { 235e412dcbdSMatthew G. Knepley DM dm; 236d1df6f1dSMatthew G. Knepley PetscSection s; 237e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 238e412dcbdSMatthew G. Knepley DM cdm; 239e412dcbdSMatthew G. Knepley PetscSection coordSection; 240e412dcbdSMatthew G. Knepley Vec coordinates; 241e412dcbdSMatthew G. Knepley const PetscScalar *coords, *array; 242e412dcbdSMatthew G. Knepley PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 243339e3443SMatthew G. Knepley PetscReal vbound[2], time; 2446913077dSMatthew G. Knepley PetscBool flg; 245d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 246e412dcbdSMatthew G. Knepley const char *name; 247339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 248e412dcbdSMatthew G. Knepley 249e412dcbdSMatthew G. Knepley PetscFunctionBegin; 2509566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2519566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 2529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 2539566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 2549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 2559566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 2569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 2579566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 2589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2609566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 261e412dcbdSMatthew G. Knepley 2629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 2639566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 264e412dcbdSMatthew G. Knepley 2659566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 2669566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 267e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 2689371c9d4SSatish Balay bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); 2699371c9d4SSatish Balay bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 2709371c9d4SSatish Balay bound[1] = PetscMin(bound[1], PetscRealPart(coords[c + 1])); 2719371c9d4SSatish Balay bound[3] = PetscMax(bound[3], PetscRealPart(coords[c + 1])); 272e412dcbdSMatthew G. Knepley } 2739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 2749566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 275e412dcbdSMatthew G. Knepley 276d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 277d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 278d1df6f1dSMatthew G. Knepley DM fdm = dm; 279d1df6f1dSMatthew G. Knepley Vec fv = v; 280d1df6f1dSMatthew G. Knepley IS fis; 281d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 282d1df6f1dSMatthew G. Knepley const char *fname; 283d1df6f1dSMatthew G. Knepley 2849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 2859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 286d1df6f1dSMatthew G. Knepley 2879566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 288ad540459SPierre Jolivet else prefix[0] = '\0'; 289d1df6f1dSMatthew G. Knepley if (Nf > 1) { 2909566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 2919566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 2929566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 2939566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 294d1df6f1dSMatthew G. Knepley } 295d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 296d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 297d1df6f1dSMatthew G. Knepley 2989566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 29963a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 30063a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 3019566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 302d1df6f1dSMatthew G. Knepley 303d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 3049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 305339e3443SMatthew G. Knepley if (!flg) { 3069566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 3079566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 308d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 309339e3443SMatthew G. Knepley } 3109566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 3119566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 3129566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3])); 313e412dcbdSMatthew G. Knepley 3149566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 315e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 31699a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 317e56f9228SJed Brown PetscInt numCoords, color[4] = {-1, -1, -1, -1}; 318e412dcbdSMatthew G. Knepley 3199566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 320339e3443SMatthew G. Knepley if (a) { 321d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 322339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 323339e3443SMatthew G. Knepley } else { 324339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 325339e3443SMatthew G. Knepley PetscInt numVals, va; 326339e3443SMatthew G. Knepley 3279566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 32863a3b9bcSJacob 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); 329d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 330d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 331d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 332d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 333339e3443SMatthew G. Knepley break; 334d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 335d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 336d1df6f1dSMatthew 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]); 337d1df6f1dSMatthew G. Knepley break; 33863a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 339339e3443SMatthew G. Knepley } 3409566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 341339e3443SMatthew G. Knepley } 3429566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 343e412dcbdSMatthew G. Knepley switch (numCoords) { 344e412dcbdSMatthew G. Knepley case 6: 3459edc3542SMatthew Knepley case 12: /* Localized triangle */ 3469566063dSJacob 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])); 347e412dcbdSMatthew G. Knepley break; 348e412dcbdSMatthew G. Knepley case 8: 3499edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 3509566063dSJacob 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])); 3519566063dSJacob 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])); 352e412dcbdSMatthew G. Knepley break; 35363a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 354e412dcbdSMatthew G. Knepley } 3559566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 356e412dcbdSMatthew G. Knepley } 3579566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 3589566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 3599566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 3609566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 361d1df6f1dSMatthew G. Knepley } 362d1df6f1dSMatthew G. Knepley if (Nf > 1) { 3639566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 3649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 3659566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 366d1df6f1dSMatthew G. Knepley } 367d1df6f1dSMatthew G. Knepley } 368e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 369e412dcbdSMatthew G. Knepley } 370e412dcbdSMatthew G. Knepley 3719371c9d4SSatish Balay static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) { 3726913077dSMatthew G. Knepley DM dm; 3736913077dSMatthew G. Knepley PetscDraw draw; 3746913077dSMatthew G. Knepley PetscInt dim; 3756913077dSMatthew G. Knepley PetscBool isnull; 3766913077dSMatthew G. Knepley 3776913077dSMatthew G. Knepley PetscFunctionBegin; 3789566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3799566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 3806913077dSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 3816913077dSMatthew G. Knepley 3829566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3846913077dSMatthew G. Knepley switch (dim) { 3859566063dSJacob Faibussowitsch case 1: PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); break; 3869566063dSJacob Faibussowitsch case 2: PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); break; 3875f80ce2aSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 3886913077dSMatthew G. Knepley } 3896913077dSMatthew G. Knepley PetscFunctionReturn(0); 3906913077dSMatthew G. Knepley } 3916913077dSMatthew G. Knepley 3929371c9d4SSatish Balay static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) { 393684b87d9SLisandro Dalcin DM dm; 394684b87d9SLisandro Dalcin Vec locv; 395684b87d9SLisandro Dalcin const char *name; 396684b87d9SLisandro Dalcin PetscSection section; 397684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 398e630c359SToby Isaac PetscInt numFields; 399684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 400684b87d9SLisandro Dalcin 401684b87d9SLisandro Dalcin PetscFunctionBegin; 4029566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4039566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 4049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 4059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 4069566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4079566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 4089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 409e630c359SToby Isaac if (!numFields) { 4109566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 4119566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 412e630c359SToby Isaac } else { 413e630c359SToby Isaac PetscInt f; 414e630c359SToby Isaac 415e630c359SToby Isaac for (f = 0; f < numFields; f++) { 4169566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 417e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 4189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 4199566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 420e630c359SToby Isaac } 4219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 422e630c359SToby Isaac } 423684b87d9SLisandro Dalcin PetscFunctionReturn(0); 424684b87d9SLisandro Dalcin } 425684b87d9SLisandro Dalcin 4269371c9d4SSatish Balay PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) { 427552f7358SJed Brown DM dm; 4285f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 429552f7358SJed Brown 430552f7358SJed Brown PetscFunctionBegin; 4319566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 43228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 4339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 4349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 4359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 4369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 4375f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 4385f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 439684b87d9SLisandro Dalcin PetscInt i, numFields; 440684b87d9SLisandro Dalcin PetscObject fe; 441ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 442684b87d9SLisandro Dalcin Vec locv = v; 443684b87d9SLisandro Dalcin const char *name; 444684b87d9SLisandro Dalcin PetscInt step; 445684b87d9SLisandro Dalcin PetscReal time; 446ef31f671SMatthew G. Knepley 4479566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 448684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 4499566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 4509371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 4519371c9d4SSatish Balay fem = PETSC_TRUE; 4529371c9d4SSatish Balay break; 4539371c9d4SSatish Balay } 454ef31f671SMatthew G. Knepley } 455684b87d9SLisandro Dalcin if (fem) { 456798534f6SMatthew G. Knepley PetscObject isZero; 457798534f6SMatthew G. Knepley 4589566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 4599566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 4609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 4619566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 4629566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 4639566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4649566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 4659566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 466ef31f671SMatthew G. Knepley } 467552f7358SJed Brown if (isvtk) { 4689566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 469b136c2c9SMatthew G. Knepley } else if (ishdf5) { 470b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 4719566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 472b136c2c9SMatthew G. Knepley #else 473b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 474b136c2c9SMatthew G. Knepley #endif 475f13a32a3SMatthew G. Knepley } else if (isdraw) { 4769566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 477684b87d9SLisandro Dalcin } else if (isglvis) { 4789566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 4799566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 4809566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 4815f34f2dcSJed Brown } else if (iscgns) { 4825f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 4835f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 4845f34f2dcSJed Brown #else 4855f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 4865f34f2dcSJed Brown #endif 487684b87d9SLisandro Dalcin } 488798534f6SMatthew G. Knepley if (fem) { 4899566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 4909566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 491798534f6SMatthew G. Knepley } 492552f7358SJed Brown } else { 493684b87d9SLisandro Dalcin PetscBool isseq; 494684b87d9SLisandro Dalcin 4959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 4969566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 4979566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 498552f7358SJed Brown } 499552f7358SJed Brown PetscFunctionReturn(0); 500552f7358SJed Brown } 501552f7358SJed Brown 5029371c9d4SSatish Balay PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) { 503552f7358SJed Brown DM dm; 5045f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 505552f7358SJed Brown 506552f7358SJed Brown PetscFunctionBegin; 5079566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 50828b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5135f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 5155f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 516552f7358SJed Brown Vec locv; 517798534f6SMatthew G. Knepley PetscObject isZero; 518552f7358SJed Brown const char *name; 519552f7358SJed Brown 5209566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5239566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 5249566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 5259566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 5269566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 5279566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 5289566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 5299566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 530b136c2c9SMatthew G. Knepley } else if (ishdf5) { 531b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5329566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 533b136c2c9SMatthew G. Knepley #else 534b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 535b136c2c9SMatthew G. Knepley #endif 5366823f3c5SBlaise Bourdin } else if (isexodusii) { 5376823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 5389566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 5396823f3c5SBlaise Bourdin #else 5406823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 5416823f3c5SBlaise Bourdin #endif 542552f7358SJed Brown } else { 543684b87d9SLisandro Dalcin PetscBool isseq; 544684b87d9SLisandro Dalcin 5459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 5469566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5479566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 548552f7358SJed Brown } 549552f7358SJed Brown PetscFunctionReturn(0); 550552f7358SJed Brown } 551552f7358SJed Brown 5529371c9d4SSatish Balay PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) { 553d930f514SMatthew G. Knepley DM dm; 554d930f514SMatthew G. Knepley MPI_Comm comm; 555d930f514SMatthew G. Knepley PetscViewerFormat format; 556d930f514SMatthew G. Knepley Vec v; 557d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 558d930f514SMatthew G. Knepley 559d930f514SMatthew G. Knepley PetscFunctionBegin; 5609566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 5619566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 56228b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5639566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 5649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 566d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 567a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 568a8ad634aSStefano Zampini /* this need a better fix */ 569a8ad634aSStefano Zampini if (dm->useNatural) { 570a8ad634aSStefano Zampini if (dm->sfNatural) { 571d930f514SMatthew G. Knepley const char *vecname; 572d930f514SMatthew G. Knepley PetscInt n, nroots; 573d930f514SMatthew G. Knepley 5749566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 5759566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 576d930f514SMatthew G. Knepley if (n == nroots) { 5779566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 5789566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 5799566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 5809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 5819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 582d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 583d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 584a8ad634aSStefano Zampini } else v = originalv; 585a8ad634aSStefano Zampini } else v = originalv; 586a8ad634aSStefano Zampini 587d930f514SMatthew G. Knepley if (ishdf5) { 588d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5899566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 590d930f514SMatthew G. Knepley #else 591d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 592d930f514SMatthew G. Knepley #endif 593d930f514SMatthew G. Knepley } else if (isvtk) { 594d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 595d930f514SMatthew G. Knepley } else { 596d930f514SMatthew G. Knepley PetscBool isseq; 597d930f514SMatthew G. Knepley 5989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 5999566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6009566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 601d930f514SMatthew G. Knepley } 6029566063dSJacob Faibussowitsch if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v)); 603d930f514SMatthew G. Knepley PetscFunctionReturn(0); 604d930f514SMatthew G. Knepley } 605d930f514SMatthew G. Knepley 6069371c9d4SSatish Balay PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) { 6072c40f234SMatthew G. Knepley DM dm; 6082c40f234SMatthew G. Knepley PetscBool ishdf5; 6092c40f234SMatthew G. Knepley 6102c40f234SMatthew G. Knepley PetscFunctionBegin; 6119566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 61228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6142c40f234SMatthew G. Knepley if (ishdf5) { 6152c40f234SMatthew G. Knepley DM dmBC; 6162c40f234SMatthew G. Knepley Vec gv; 6172c40f234SMatthew G. Knepley const char *name; 6182c40f234SMatthew G. Knepley 6199566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 6209566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 6219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 6239566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 6249566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 6259566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 6269566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 6271baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 6282c40f234SMatthew G. Knepley PetscFunctionReturn(0); 6292c40f234SMatthew G. Knepley } 6302c40f234SMatthew G. Knepley 6319371c9d4SSatish Balay PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) { 6322c40f234SMatthew G. Knepley DM dm; 6336823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 6342c40f234SMatthew G. Knepley 6352c40f234SMatthew G. Knepley PetscFunctionBegin; 6369566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63728b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6402c40f234SMatthew G. Knepley if (ishdf5) { 641878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6429566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 643b136c2c9SMatthew G. Knepley #else 644b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 645878b459fSMatthew G. Knepley #endif 6466823f3c5SBlaise Bourdin } else if (isexodusii) { 6476823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6489566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 6496823f3c5SBlaise Bourdin #else 6506823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6516823f3c5SBlaise Bourdin #endif 6521baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 653552f7358SJed Brown PetscFunctionReturn(0); 654552f7358SJed Brown } 655552f7358SJed Brown 6569371c9d4SSatish Balay PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) { 657d930f514SMatthew G. Knepley DM dm; 658d930f514SMatthew G. Knepley PetscViewerFormat format; 659d930f514SMatthew G. Knepley PetscBool ishdf5; 660d930f514SMatthew G. Knepley 661d930f514SMatthew G. Knepley PetscFunctionBegin; 6629566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 66328b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6649566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 666d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 667a8ad634aSStefano Zampini if (dm->useNatural) { 668d930f514SMatthew G. Knepley if (dm->sfNatural) { 669d930f514SMatthew G. Knepley if (ishdf5) { 670d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 671d930f514SMatthew G. Knepley Vec v; 672d930f514SMatthew G. Knepley const char *vecname; 673d930f514SMatthew G. Knepley 6749566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 6759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 6769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 6779566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 6789566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 6799566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 6809566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dm, &v)); 681d930f514SMatthew G. Knepley #else 682d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 683d930f514SMatthew G. Knepley #endif 684d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 685d930f514SMatthew G. Knepley } 6861baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 687d930f514SMatthew G. Knepley } 688d930f514SMatthew G. Knepley PetscFunctionReturn(0); 689d930f514SMatthew G. Knepley } 690d930f514SMatthew G. Knepley 6919371c9d4SSatish Balay PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) { 692731e8ddeSMatthew G. Knepley PetscSection coordSection; 693731e8ddeSMatthew G. Knepley Vec coordinates; 694ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 695731e8ddeSMatthew G. Knepley const char *name[4]; 696731e8ddeSMatthew G. Knepley const PetscScalar *a; 697731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 698731e8ddeSMatthew G. Knepley 699731e8ddeSMatthew G. Knepley PetscFunctionBegin; 7009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 7019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 7029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7039566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 7049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 7059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 7069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 7079566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 708731e8ddeSMatthew G. Knepley name[0] = "vertex"; 709731e8ddeSMatthew G. Knepley name[1] = "edge"; 710731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 711731e8ddeSMatthew G. Knepley name[dim] = "cell"; 712731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 713731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 714ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 715731e8ddeSMatthew G. Knepley 7169566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 71763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 7189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 720731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 721731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 722731e8ddeSMatthew G. Knepley 723731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 7249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 725731e8ddeSMatthew G. Knepley if (!dof) continue; 7269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 7279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 72863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 729731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 7309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 731731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 7329566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 7339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 734731e8ddeSMatthew G. Knepley } 7359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 736731e8ddeSMatthew G. Knepley } 7379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 738731e8ddeSMatthew G. Knepley } 7399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 741731e8ddeSMatthew G. Knepley } 7429566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 743731e8ddeSMatthew G. Knepley PetscFunctionReturn(0); 744731e8ddeSMatthew G. Knepley } 745731e8ddeSMatthew G. Knepley 7469371c9d4SSatish Balay typedef enum { 7479371c9d4SSatish Balay CS_CARTESIAN, 7489371c9d4SSatish Balay CS_POLAR, 7499371c9d4SSatish Balay CS_CYLINDRICAL, 7509371c9d4SSatish Balay CS_SPHERICAL 7519371c9d4SSatish Balay } CoordSystem; 75219ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 75319ad8254SMatthew G. Knepley 7549371c9d4SSatish Balay static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) { 75519ad8254SMatthew G. Knepley PetscInt i; 75619ad8254SMatthew G. Knepley 75719ad8254SMatthew G. Knepley PetscFunctionBegin; 75819ad8254SMatthew G. Knepley if (dim > 3) { 7599566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 76019ad8254SMatthew G. Knepley } else { 761bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 76219ad8254SMatthew G. Knepley 76319ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 76419ad8254SMatthew G. Knepley switch (cs) { 7659371c9d4SSatish Balay case CS_CARTESIAN: 7669371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 7679371c9d4SSatish Balay break; 76819ad8254SMatthew G. Knepley case CS_POLAR: 76963a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 77019ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 77119ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 77219ad8254SMatthew G. Knepley break; 77319ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 77463a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 77519ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 77619ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 77719ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 77819ad8254SMatthew G. Knepley break; 77919ad8254SMatthew G. Knepley case CS_SPHERICAL: 78063a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 78119ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 78219ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 78319ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 78419ad8254SMatthew G. Knepley break; 78519ad8254SMatthew G. Knepley } 7869566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 78719ad8254SMatthew G. Knepley } 78819ad8254SMatthew G. Knepley PetscFunctionReturn(0); 78919ad8254SMatthew G. Knepley } 79019ad8254SMatthew G. Knepley 7919371c9d4SSatish Balay static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) { 792552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 7936858538eSMatthew G. Knepley DM cdm, cdmCell; 7946858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 7956858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 796552f7358SJed Brown PetscViewerFormat format; 797552f7358SJed Brown 798552f7358SJed Brown PetscFunctionBegin; 7999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 8006858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8026858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 8036858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 8046858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 8059566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 806552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 807552f7358SJed Brown const char *name; 808f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 8099318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 810552f7358SJed Brown PetscMPIInt rank, size; 811552f7358SJed Brown 8129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 8149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 8159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8169566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 8179566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8189566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 81963a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 82063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 82163a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 82263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 8239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 82463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 825552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 826552f7358SJed Brown PetscInt dof, off, s; 827552f7358SJed Brown 8289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 83048a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 831552f7358SJed Brown } 8329566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 83363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 83463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 835552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 836552f7358SJed Brown PetscInt dof, off, c; 837552f7358SJed Brown 8389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 8399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 84048a46eb9SPierre 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])); 841552f7358SJed Brown } 8429566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8443d2e540fSStefano Zampini if (coordSection && coordinates) { 84519ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 8466858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 8476858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 84819ad8254SMatthew G. Knepley PetscMPIInt rank; 84919ad8254SMatthew G. Knepley const char *name; 85019ad8254SMatthew G. Knepley 8519566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 8529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 8539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 85463a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 8559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 8566858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 8576858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 8586858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 8596858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 8609566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 86163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 86263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 8639566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 86419ad8254SMatthew G. Knepley 8659566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 8666858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 8679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 8689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 86919ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 87019ad8254SMatthew G. Knepley PetscInt dof, off; 87119ad8254SMatthew G. Knepley 8726858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 8739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 8749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 8756858538eSMatthew G. Knepley if (dof) { 87663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 8779566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 8789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 87919ad8254SMatthew G. Knepley } 8806858538eSMatthew G. Knepley } 8816858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 8826858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 8836858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 8846858538eSMatthew G. Knepley if (dof) { 8856858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 8866858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 8876858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 8886858538eSMatthew G. Knepley } 8896858538eSMatthew G. Knepley } 8906858538eSMatthew G. Knepley } 8919566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8939566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 8946858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 8953d2e540fSStefano Zampini } 8969566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 8979566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 8989318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 8999318fe57SMatthew G. Knepley DMLabel label; 9009318fe57SMatthew G. Knepley PetscBool isdepth; 9019318fe57SMatthew G. Knepley const char *name; 9029318fe57SMatthew G. Knepley 9039566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 9049566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 9059318fe57SMatthew G. Knepley if (isdepth) continue; 9069566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 9079566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 9089318fe57SMatthew G. Knepley } 909552f7358SJed Brown if (size > 1) { 910552f7358SJed Brown PetscSF sf; 911552f7358SJed Brown 9129566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9139566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 914552f7358SJed Brown } 9159566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 916552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 9170588280cSMatthew G. Knepley const char *name, *color; 9180588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 9190588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 920fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 921552f7358SJed Brown PetscReal scale = 2.0; 92278081901SStefano Zampini PetscReal tikzscale = 1.0; 923b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 9240588280cSMatthew G. Knepley double tcoords[3]; 925552f7358SJed Brown PetscScalar *coords; 926b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 927552f7358SJed Brown PetscMPIInt rank, size; 9280588280cSMatthew G. Knepley char **names, **colors, **lcolors; 929b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 930fe1cc32dSStefano Zampini PetscBT wp = NULL; 931fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 932552f7358SJed Brown 9339566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9349566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9359566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 9360588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 9370588280cSMatthew G. Knepley numColors = 10; 9380588280cSMatthew G. Knepley numLColors = 10; 9399566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 9409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 9419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 9429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 943b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 944b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 945b7f6ffafSMatthew G. Knepley n = 4; 9469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 9471dca8a05SBarry 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); 9489566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 9491dca8a05SBarry 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); 9509566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 9510588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 9529566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 9530588280cSMatthew G. Knepley if (!useColors) { 9540588280cSMatthew G. Knepley numColors = 3; 9559566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 9560588280cSMatthew G. Knepley } 9579566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 9580588280cSMatthew G. Knepley if (!useColors) { 9590588280cSMatthew G. Knepley numLColors = 4; 9609566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 9610588280cSMatthew G. Knepley } 9629566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 963b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 9649566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 9651dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 966202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 9679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 968fe1cc32dSStefano Zampini 969fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 9709566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9739566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 974fe1cc32dSStefano Zampini if (lflg) { 975fe1cc32dSStefano Zampini DMLabel lbl; 976fe1cc32dSStefano Zampini 9779566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 978fe1cc32dSStefano Zampini if (lbl) { 979fe1cc32dSStefano Zampini PetscInt val, defval; 980fe1cc32dSStefano Zampini 9819566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 9829566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 983fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 984fe1cc32dSStefano Zampini PetscInt *closure = NULL; 985fe1cc32dSStefano Zampini PetscInt closureSize; 986fe1cc32dSStefano Zampini 9879566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 988fe1cc32dSStefano Zampini if (val == defval) continue; 989fe1cc32dSStefano Zampini 9909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 99148a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 9929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 993fe1cc32dSStefano Zampini } 994fe1cc32dSStefano Zampini } 995fe1cc32dSStefano Zampini } 996fe1cc32dSStefano Zampini 9979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 10009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 10010588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1002552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1003552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1004552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 10055f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 10060588280cSMatthew G. Knepley if (size > 1) { 10079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1008770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 100963a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 101063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1011770b213bSMatthew G Knepley } 10129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 10130588280cSMatthew G. Knepley } 1014b7f6ffafSMatthew G. Knepley if (drawHasse) { 1015b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1016b7f6ffafSMatthew G. Knepley 101763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 101863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 101963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 10209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 102163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 102263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 10239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 102463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 102563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 102663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 102763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 10289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1029b7f6ffafSMatthew G. Knepley } 10309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1031fe1cc32dSStefano Zampini 1032552f7358SJed Brown /* Plot vertices */ 10339566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1035552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1036552f7358SJed Brown PetscInt off, dof, d; 10370588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1038552f7358SJed Brown 1039fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 10409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 10419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 10429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 104363a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 10440588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10450588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1046c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 10470588280cSMatthew G. Knepley } 10480588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 10499371c9d4SSatish Balay if (dim == 3) { 10509371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 10519371c9d4SSatish Balay tcoords[1] = tcoords[2]; 10529371c9d4SSatish Balay tcoords[2] = -tmp; 10539371c9d4SSatish Balay } 1054552f7358SJed Brown for (d = 0; d < dof; ++d) { 10559566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1057552f7358SJed Brown } 1058b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1059b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 10600588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10610588280cSMatthew G. Knepley PetscInt val; 10629566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 10639371c9d4SSatish Balay if (val >= 0) { 10649371c9d4SSatish Balay color = lcolors[l % numLColors]; 10659371c9d4SSatish Balay isLabeled = PETSC_TRUE; 10669371c9d4SSatish Balay break; 10679371c9d4SSatish Balay } 10680588280cSMatthew G. Knepley } 1069b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 107063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1071b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 107263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 10731baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1074552f7358SJed Brown } 10759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 10769566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1077b7f6ffafSMatthew G. Knepley /* Plot edges */ 1078b7f6ffafSMatthew G. Knepley if (plotEdges) { 10799566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1081b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1082b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1083b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1084b7f6ffafSMatthew G. Knepley 1085b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 10869566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 108763a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 10889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 10899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 10909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 10919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 10929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1093b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1094b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1095b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1096b7f6ffafSMatthew G. Knepley } 1097b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 10989371c9d4SSatish Balay if (dim == 3) { 10999371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11009371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11019371c9d4SSatish Balay tcoords[2] = -tmp; 11029371c9d4SSatish Balay } 1103b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11049566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1106b7f6ffafSMatthew G. Knepley } 1107b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1108b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1109b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1110b7f6ffafSMatthew G. Knepley PetscInt val; 11119566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 11129371c9d4SSatish Balay if (val >= 0) { 11139371c9d4SSatish Balay color = lcolors[l % numLColors]; 11149371c9d4SSatish Balay break; 11159371c9d4SSatish Balay } 1116b7f6ffafSMatthew G. Knepley } 111763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1118b7f6ffafSMatthew G. Knepley } 11199566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 11209566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 11219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1122b7f6ffafSMatthew G. Knepley } 1123846a3e8bSMatthew G. Knepley /* Plot cells */ 1124b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1125846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1126846a3e8bSMatthew G. Knepley const PetscInt *cone; 1127846a3e8bSMatthew G. Knepley 1128fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1129846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1130846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1131846a3e8bSMatthew G. Knepley PetscInt val; 11329566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 11339371c9d4SSatish Balay if (val >= 0) { 11349371c9d4SSatish Balay color = lcolors[l % numLColors]; 11359371c9d4SSatish Balay break; 11369371c9d4SSatish Balay } 1137846a3e8bSMatthew G. Knepley } 11389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 113963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1140846a3e8bSMatthew G. Knepley } 1141846a3e8bSMatthew G. Knepley } else { 1142b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1143846a3e8bSMatthew G. Knepley 1144b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1145b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1146fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 11479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 11489371c9d4SSatish Balay if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1149b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1150b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1151b7f6ffafSMatthew G. Knepley 11529566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 11539566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1154b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1155b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1156b7f6ffafSMatthew G. Knepley 11579566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 115863a3b9bcSJacob 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)); 1159b7f6ffafSMatthew G. Knepley } 1160b7f6ffafSMatthew G. Knepley } else { 1161b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1162b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1163b7f6ffafSMatthew G. Knepley 11649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1165846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1166846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1167846a3e8bSMatthew G. Knepley 1168b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1169846a3e8bSMatthew G. Knepley } 11709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1171b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1172b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1173b7f6ffafSMatthew G. Knepley 1174b7f6ffafSMatthew G. Knepley if (v > 0) { 1175b7f6ffafSMatthew G. Knepley if (plotEdges) { 1176b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1177b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1178b7f6ffafSMatthew G. Knepley 11799371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 11809371c9d4SSatish Balay endpoints[1] = vertex; 11819566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 118263a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 118363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 11849566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 11851baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1186b7f6ffafSMatthew G. Knepley } 118763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1188b7f6ffafSMatthew G. Knepley } 11899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 11909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1191846a3e8bSMatthew G. Knepley } 1192846a3e8bSMatthew G. Knepley } 1193b7f6ffafSMatthew G. Knepley } 1194846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1195846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1196846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1197c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1198c713ec31SMatthew G. Knepley const PetscScalar *array; 1199c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1200c713ec31SMatthew G. Knepley PetscBool isDG; 1201846a3e8bSMatthew G. Knepley 1202fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1203c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1204c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1205c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 12069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1207c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1208c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1209c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1210846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1211846a3e8bSMatthew G. Knepley } 1212846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12139371c9d4SSatish Balay if (cdim == 3) { 12149371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12159371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12169371c9d4SSatish Balay tcoords[2] = -tmp; 12179371c9d4SSatish Balay } 1218ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1219846a3e8bSMatthew G. Knepley } 1220ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1221c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1222c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 12239566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1225846a3e8bSMatthew G. Knepley } 1226b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1227b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1228846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1229846a3e8bSMatthew G. Knepley PetscInt val; 12309566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 12319371c9d4SSatish Balay if (val >= 0) { 12329371c9d4SSatish Balay color = lcolors[l % numLColors]; 12339371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12349371c9d4SSatish Balay break; 12359371c9d4SSatish Balay } 1236846a3e8bSMatthew G. Knepley } 1237b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 123863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1239b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 124063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 12411baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1242846a3e8bSMatthew G. Knepley } 1243b7f6ffafSMatthew G. Knepley if (drawHasse) { 1244b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 12459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 12469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 12479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 12499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1250552f7358SJed Brown 1251b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 12529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 12539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 12549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 12569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1257b7f6ffafSMatthew G. Knepley 1258b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 12599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 12609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 12619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 12639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1264b7f6ffafSMatthew G. Knepley 1265b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1266b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1267b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1268b7f6ffafSMatthew G. Knepley 12699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 12709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 127148a46eb9SPierre 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)); 12720588280cSMatthew G. Knepley } 12730588280cSMatthew G. Knepley } 12749566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 12769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 127763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 12789566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 12799566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 12809566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 12819566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 12829566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 12830f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 12840f7d6e4aSStefano Zampini Vec cown, acown; 12850f7d6e4aSStefano Zampini VecScatter sct; 12860f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 12870f7d6e4aSStefano Zampini IS gid, acis; 12880f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 12890f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 12900f7d6e4aSStefano Zampini PetscScalar *array, nid; 12910f7d6e4aSStefano Zampini const PetscInt *idxs; 12920f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 12930f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 12940f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 12950f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 12960f7d6e4aSStefano Zampini 12979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1299b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 13009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 13010f7d6e4aSStefano Zampini #endif 13020f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 13039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 13049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 13050f7d6e4aSStefano Zampini d1 = 0; 13069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 13070f7d6e4aSStefano Zampini nid = d2; 13089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 13099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 13109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 13110f7d6e4aSStefano Zampini } else nid = 0.0; 13120f7d6e4aSStefano Zampini 13130f7d6e4aSStefano Zampini /* Get connectivity */ 13149566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 13159566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 13160f7d6e4aSStefano Zampini 13170f7d6e4aSStefano Zampini /* filter overlapped local cells */ 13189566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 13199566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 13209566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 13219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 13220f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 13230f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 13240f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 13250f7d6e4aSStefano Zampini } 13269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 132763a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 13289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13299566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 13300f7d6e4aSStefano Zampini 13310f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 13329566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 13339566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 13349566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 13359566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 13360f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 13379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 13389566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 13399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 13409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 13419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 13429566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 13439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 13440f7d6e4aSStefano Zampini 13450f7d6e4aSStefano Zampini /* compute edgeCut */ 13460f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 13479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 13489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 13499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 13509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13519566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 13520f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 13530f7d6e4aSStefano Zampini PetscInt totl; 13540f7d6e4aSStefano Zampini 13550f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 13569566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 13570f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 13580f7d6e4aSStefano Zampini if (work[i] < 0) { 13590f7d6e4aSStefano Zampini ect += 1; 13600f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 13610f7d6e4aSStefano Zampini } 13620f7d6e4aSStefano Zampini } 13630f7d6e4aSStefano Zampini } 13649566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 13659566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 13660f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 13670f7d6e4aSStefano Zampini lm[1] = -numVertices; 13681c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 136963a3b9bcSJacob 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])); 13700f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 13710f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 13720f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 13731c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 137463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1375b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 137663a3b9bcSJacob 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.)); 13770f7d6e4aSStefano Zampini #else 137863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 13790f7d6e4aSStefano Zampini #endif 13809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 13819566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 13829566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 13839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1384552f7358SJed Brown } else { 1385412e9a14SMatthew G. Knepley const char *name; 1386d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1387412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1388d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1389ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 13909318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1391412e9a14SMatthew G. Knepley MPI_Comm comm; 1392412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1393552f7358SJed Brown 13949566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 13959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 13969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 13979566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13989566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 13999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 140063a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 140163a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 140263a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 14039566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 14041c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 14059566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd)); 1406d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 14079566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 14089566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1409412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1410412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1411412e9a14SMatthew G. Knepley 14129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 14139566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1414412e9a14SMatthew G. Knepley ict = ct0; 14159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1416412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1417412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1418412e9a14SMatthew G. Knepley DMPolytopeType ct; 1419412e9a14SMatthew G. Knepley 14209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1421412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1422412e9a14SMatthew G. Knepley else ++Nc[1]; 1423412e9a14SMatthew G. Knepley } 1424ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 14259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 14269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 14279566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 142863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1429834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1430dd400576SPatrick Sanan if (rank == 0) { 143163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 143263a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 143363a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1434834065abSMatthew G. Knepley } 1435cbb7f117SMark Adams } 1436ca7bf7eeSMatthew G. Knepley } else { 1437ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1438ca7bf7eeSMatthew G. Knepley 14399371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 14409371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 14419566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 14429371c9d4SSatish Balay locMinMax[0] = Nc[1]; 14439371c9d4SSatish Balay locMinMax[1] = Nc[1]; 14449566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1445ca7bf7eeSMatthew G. Knepley if (d == depth) { 14469371c9d4SSatish Balay locMinMax[0] = gcNum; 14479371c9d4SSatish Balay locMinMax[1] = gcNum; 14489566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1449ca7bf7eeSMatthew G. Knepley } 145063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 14519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 14529566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 14539566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1454ca7bf7eeSMatthew G. Knepley } 14559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1456552f7358SJed Brown } 14579566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 14589318fe57SMatthew G. Knepley { 14599318fe57SMatthew G. Knepley const PetscReal *maxCell; 14609318fe57SMatthew G. Knepley const PetscReal *L; 14616858538eSMatthew G. Knepley PetscBool localized; 14629318fe57SMatthew G. Knepley 14634fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 14649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 14656858538eSMatthew G. Knepley if (L || localized) { 14666858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 14679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 14686858538eSMatthew G. Knepley if (L) { 14696858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 14709318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 14716858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 14726858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 14739318fe57SMatthew G. Knepley } 14746858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 14756858538eSMatthew G. Knepley } 14766858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 14779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14789318fe57SMatthew G. Knepley } 14799318fe57SMatthew G. Knepley } 14809566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 14819566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1482a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1483a57dd577SMatthew G Knepley DMLabel label; 1484a57dd577SMatthew G Knepley const char *name; 1485a57dd577SMatthew G Knepley IS valueIS; 1486a57dd577SMatthew G Knepley const PetscInt *values; 1487a57dd577SMatthew G Knepley PetscInt numValues, v; 1488a57dd577SMatthew G Knepley 14899566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 14909566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 14919566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 149263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 14939566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 14949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 14959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1496a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1497a57dd577SMatthew G Knepley PetscInt size; 1498a57dd577SMatthew G Knepley 14999566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 15009566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 150163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1502a57dd577SMatthew G Knepley } 15039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 15049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 15059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 15069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1507a57dd577SMatthew G Knepley } 1508c1cad2e7SMatthew G. Knepley { 1509c1cad2e7SMatthew G. Knepley char **labelNames; 1510c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1511c1cad2e7SMatthew G. Knepley PetscBool flg; 1512c1cad2e7SMatthew G. Knepley 15139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 15149566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1515c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1516c1cad2e7SMatthew G. Knepley DMLabel label; 1517c1cad2e7SMatthew G. Knepley 15189566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1519c1cad2e7SMatthew G. Knepley if (flg) { 15209566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 15219566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1522c1cad2e7SMatthew G. Knepley } 15239566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1524c1cad2e7SMatthew G. Knepley } 15259566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1526c1cad2e7SMatthew G. Knepley } 152734aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 152834aa8a36SMatthew G. Knepley if (dm->Nf) { 152934aa8a36SMatthew G. Knepley PetscInt f; 153034aa8a36SMatthew G. Knepley 153134aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 153234aa8a36SMatthew G. Knepley const char *name; 153334aa8a36SMatthew G. Knepley 15349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 15359566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 15369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15379566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 153834aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 15399566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 15409566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 154134aa8a36SMatthew G. Knepley } else { 15429566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 15439566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 154434aa8a36SMatthew G. Knepley } 15459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 154634aa8a36SMatthew G. Knepley } 154734aa8a36SMatthew G. Knepley } 15489566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 15498e7ff633SMatthew G. Knepley if (cdm) { 15509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15519566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 15529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 15538e7ff633SMatthew G. Knepley } 1554552f7358SJed Brown } 1555552f7358SJed Brown PetscFunctionReturn(0); 1556552f7358SJed Brown } 1557552f7358SJed Brown 15589371c9d4SSatish Balay static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) { 1559e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1560e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1561a12d352dSMatthew G. Knepley PetscInt cdim; 1562e5c487bfSMatthew G. Knepley 1563e5c487bfSMatthew G. Knepley PetscFunctionBegin; 15649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 15669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1567e5c487bfSMatthew G. Knepley switch (ct) { 1568a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1569a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1570a12d352dSMatthew G. Knepley switch (cdim) { 15719371c9d4SSatish Balay case 1: { 1572a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1573a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1574a12d352dSMatthew G. Knepley 15759566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 15769566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 15779566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 15789371c9d4SSatish Balay } break; 15799371c9d4SSatish Balay case 2: { 1580a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1581a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1582a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1583a12d352dSMatthew G. Knepley 15849566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15859566063dSJacob 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)); 15869566063dSJacob 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)); 15879371c9d4SSatish Balay } break; 158863a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1589a12d352dSMatthew G. Knepley } 1590a12d352dSMatthew G. Knepley break; 1591e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 15929371c9d4SSatish 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)); 15939566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15949566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15959566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1596e5c487bfSMatthew G. Knepley break; 1597e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 15989371c9d4SSatish 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)); 15999371c9d4SSatish 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)); 16009566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 16019566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 16029566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 16039566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1604e5c487bfSMatthew G. Knepley break; 160598921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1606e5c487bfSMatthew G. Knepley } 1607e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1608e5c487bfSMatthew G. Knepley } 1609e5c487bfSMatthew G. Knepley 16109371c9d4SSatish Balay static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) { 1611e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1612e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1613e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1614e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1615e5c487bfSMatthew G. Knepley 1616e5c487bfSMatthew G. Knepley PetscFunctionBegin; 16179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 16189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1619e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1620e5c487bfSMatthew G. Knepley switch (ct) { 16219371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 1622e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1623e5c487bfSMatthew G. Knepley 16249371c9d4SSatish Balay for (v = 0; v < 3; ++v) { 16259371c9d4SSatish Balay centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.; 16269371c9d4SSatish Balay centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.; 16279371c9d4SSatish Balay } 1628e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1629e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1630e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1631e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1632e5c487bfSMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv; 1633e5c487bfSMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv; 1634e5c487bfSMatthew G. Knepley } 16359566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1636e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 16379566063dSJacob 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)); 16389566063dSJacob 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)); 1639e5c487bfSMatthew G. Knepley } 1640e5c487bfSMatthew G. Knepley } 16419371c9d4SSatish Balay } break; 164298921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1643e5c487bfSMatthew G. Knepley } 1644e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1645e5c487bfSMatthew G. Knepley } 1646e5c487bfSMatthew G. Knepley 16479371c9d4SSatish Balay static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) { 1648e412dcbdSMatthew G. Knepley PetscDraw draw; 1649e412dcbdSMatthew G. Knepley DM cdm; 1650e412dcbdSMatthew G. Knepley PetscSection coordSection; 1651e412dcbdSMatthew G. Knepley Vec coordinates; 1652e412dcbdSMatthew G. Knepley const PetscScalar *coords; 165329494db1SLisandro Dalcin PetscReal xyl[2], xyr[2], bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1654e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1655e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1656e5c487bfSMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1657e412dcbdSMatthew G. Knepley 1658e412dcbdSMatthew G. Knepley PetscFunctionBegin; 16599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 166063a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 16619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 16629566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 16639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 16649566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 16659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 16669566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 16679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1668e412dcbdSMatthew G. Knepley 16699566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 16709566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 1671e412dcbdSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 16729566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1673e412dcbdSMatthew G. Knepley 16749566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 16759566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 1676e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 16779371c9d4SSatish Balay bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); 16789371c9d4SSatish Balay bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 16799371c9d4SSatish Balay bound[1] = PetscMin(bound[1], PetscRealPart(coords[c + 1])); 16809371c9d4SSatish Balay bound[3] = PetscMax(bound[3], PetscRealPart(coords[c + 1])); 1681e412dcbdSMatthew G. Knepley } 16829566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 16831c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[0], xyl, 2, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)dm))); 16841c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[2], xyr, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 16859566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 16869566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1687e412dcbdSMatthew G. Knepley 1688cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1689cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1690ba2698f1SMatthew G. Knepley PetscInt numCoords; 1691cf3064d3SMatthew G. Knepley 16929566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords)); 16931baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 16941baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 16959566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 1696cf3064d3SMatthew G. Knepley } 16979566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 16989566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 16999566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 17009566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 1701e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 1702e412dcbdSMatthew G. Knepley } 1703e412dcbdSMatthew G. Knepley 17041e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17051e50132fSMatthew G. Knepley #include <exodusII.h> 17066823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 17071e50132fSMatthew G. Knepley #endif 17081e50132fSMatthew G. Knepley 17099371c9d4SSatish Balay PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) { 17105f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1711002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1712552f7358SJed Brown 1713552f7358SJed Brown PetscFunctionBegin; 1714552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1715552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 17179566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 17189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 17199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 17209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 17219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 17225f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1723552f7358SJed Brown if (iascii) { 17248135c375SStefano Zampini PetscViewerFormat format; 17259566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 17261baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 17271baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1728c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1729c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 17309566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1731c6ccd67eSMatthew G. Knepley #else 1732c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1733552f7358SJed Brown #endif 1734e412dcbdSMatthew G. Knepley } else if (isvtk) { 17359566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1736e412dcbdSMatthew G. Knepley } else if (isdraw) { 17379566063dSJacob Faibussowitsch PetscCall(DMPlexView_Draw(dm, viewer)); 17388135c375SStefano Zampini } else if (isglvis) { 17399566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 17401e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17411e50132fSMatthew G. Knepley } else if (isexodus) { 17426823f3c5SBlaise Bourdin /* 17436823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 17446823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 17456823f3c5SBlaise Bourdin with ID 1, containig all cells. 17466823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 17476823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 17486823f3c5SBlaise Bourdin */ 17496823f3c5SBlaise Bourdin PetscInt numCS; 17509566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 17516823f3c5SBlaise Bourdin if (!numCS) { 17521e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 17539566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 17549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 17559566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 17566823f3c5SBlaise Bourdin } 17579566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 17581e50132fSMatthew G. Knepley #endif 17595f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 17605f34f2dcSJed Brown } else if (iscgns) { 17615f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 17625f34f2dcSJed Brown #endif 17631baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1764cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 17659566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1766cb3ba0daSMatthew G. Knepley if (flg) { 1767cb3ba0daSMatthew G. Knepley Vec ranks; 17689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 17699566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 17709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1771cb3ba0daSMatthew G. Knepley } 1772002a2709SMatthew G. Knepley /* Optionally view a label */ 17739566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1774002a2709SMatthew G. Knepley if (flg) { 1775002a2709SMatthew G. Knepley DMLabel label; 1776002a2709SMatthew G. Knepley Vec val; 1777002a2709SMatthew G. Knepley 17789566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 177928b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 17809566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 17819566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 17829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1783002a2709SMatthew G. Knepley } 1784552f7358SJed Brown PetscFunctionReturn(0); 1785552f7358SJed Brown } 1786552f7358SJed Brown 17877f96f51bSksagiyam /*@ 17887f96f51bSksagiyam DMPlexTopologyView - Saves a DMPlex topology into a file 17897f96f51bSksagiyam 17907f96f51bSksagiyam Collective on DM 17917f96f51bSksagiyam 17927f96f51bSksagiyam Input Parameters: 17937f96f51bSksagiyam + dm - The DM whose topology is to be saved 17947f96f51bSksagiyam - viewer - The PetscViewer for saving 17957f96f51bSksagiyam 17967f96f51bSksagiyam Level: advanced 17977f96f51bSksagiyam 1798db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()` 17997f96f51bSksagiyam @*/ 18009371c9d4SSatish Balay PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) { 18017f96f51bSksagiyam PetscBool ishdf5; 18027f96f51bSksagiyam 18037f96f51bSksagiyam PetscFunctionBegin; 18047f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 18057f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 18079566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 18087f96f51bSksagiyam if (ishdf5) { 18097f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 18107f96f51bSksagiyam PetscViewerFormat format; 18119566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 18127f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18137f96f51bSksagiyam IS globalPointNumbering; 18147f96f51bSksagiyam 18159566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18169566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 181898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 18197f96f51bSksagiyam #else 18207f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 18217f96f51bSksagiyam #endif 18227f96f51bSksagiyam } 18239566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 18247f96f51bSksagiyam PetscFunctionReturn(0); 18257f96f51bSksagiyam } 18267f96f51bSksagiyam 182777b8e257Sksagiyam /*@ 182877b8e257Sksagiyam DMPlexCoordinatesView - Saves DMPlex coordinates into a file 182977b8e257Sksagiyam 183077b8e257Sksagiyam Collective on DM 183177b8e257Sksagiyam 183277b8e257Sksagiyam Input Parameters: 183377b8e257Sksagiyam + dm - The DM whose coordinates are to be saved 183477b8e257Sksagiyam - viewer - The PetscViewer for saving 183577b8e257Sksagiyam 183677b8e257Sksagiyam Level: advanced 183777b8e257Sksagiyam 1838db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()` 183977b8e257Sksagiyam @*/ 18409371c9d4SSatish Balay PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) { 184177b8e257Sksagiyam PetscBool ishdf5; 184277b8e257Sksagiyam 184377b8e257Sksagiyam PetscFunctionBegin; 184477b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 184577b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 18479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 184877b8e257Sksagiyam if (ishdf5) { 184977b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 185077b8e257Sksagiyam PetscViewerFormat format; 18519566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 185277b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18539566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 1854*fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 185577b8e257Sksagiyam #else 185677b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 185777b8e257Sksagiyam #endif 185877b8e257Sksagiyam } 18599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 186077b8e257Sksagiyam PetscFunctionReturn(0); 186177b8e257Sksagiyam } 186277b8e257Sksagiyam 1863bd6565f1Sksagiyam /*@ 1864bd6565f1Sksagiyam DMPlexLabelsView - Saves DMPlex labels into a file 1865bd6565f1Sksagiyam 1866bd6565f1Sksagiyam Collective on DM 1867bd6565f1Sksagiyam 1868bd6565f1Sksagiyam Input Parameters: 1869bd6565f1Sksagiyam + dm - The DM whose labels are to be saved 1870bd6565f1Sksagiyam - viewer - The PetscViewer for saving 1871bd6565f1Sksagiyam 1872bd6565f1Sksagiyam Level: advanced 1873bd6565f1Sksagiyam 1874db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()` 1875bd6565f1Sksagiyam @*/ 18769371c9d4SSatish Balay PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) { 1877bd6565f1Sksagiyam PetscBool ishdf5; 1878bd6565f1Sksagiyam 1879bd6565f1Sksagiyam PetscFunctionBegin; 1880bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1881bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 18839566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 1884bd6565f1Sksagiyam if (ishdf5) { 1885bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 1886bd6565f1Sksagiyam IS globalPointNumbering; 1887bd6565f1Sksagiyam PetscViewerFormat format; 1888bd6565f1Sksagiyam 18899566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 1890bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18919566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18929566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 189498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1895bd6565f1Sksagiyam #else 1896bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1897bd6565f1Sksagiyam #endif 1898bd6565f1Sksagiyam } 18999566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 1900bd6565f1Sksagiyam PetscFunctionReturn(0); 1901bd6565f1Sksagiyam } 1902bd6565f1Sksagiyam 1903021affd3Sksagiyam /*@ 1904021affd3Sksagiyam DMPlexSectionView - Saves a section associated with a DMPlex 1905021affd3Sksagiyam 1906021affd3Sksagiyam Collective on DM 1907021affd3Sksagiyam 1908021affd3Sksagiyam Input Parameters: 1909021affd3Sksagiyam + dm - The DM that contains the topology on which the section to be saved is defined 1910021affd3Sksagiyam . viewer - The PetscViewer for saving 1911021affd3Sksagiyam - sectiondm - The DM that contains the section to be saved 1912021affd3Sksagiyam 1913021affd3Sksagiyam Level: advanced 1914021affd3Sksagiyam 1915021affd3Sksagiyam Notes: 1916021affd3Sksagiyam 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. 1917021affd3Sksagiyam 1918021affd3Sksagiyam 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. 1919021affd3Sksagiyam 1920db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()` 1921021affd3Sksagiyam @*/ 19229371c9d4SSatish Balay PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) { 1923021affd3Sksagiyam PetscBool ishdf5; 1924021affd3Sksagiyam 1925021affd3Sksagiyam PetscFunctionBegin; 1926021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1927021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1928021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 1931021affd3Sksagiyam if (ishdf5) { 1932021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 19339566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 1934021affd3Sksagiyam #else 1935021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1936021affd3Sksagiyam #endif 1937021affd3Sksagiyam } 19389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 1939021affd3Sksagiyam PetscFunctionReturn(0); 1940021affd3Sksagiyam } 1941021affd3Sksagiyam 19423e97647fSksagiyam /*@ 19433e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 19443e97647fSksagiyam 19453e97647fSksagiyam Collective on DM 19463e97647fSksagiyam 19473e97647fSksagiyam Input Parameters: 19483e97647fSksagiyam + dm - The DM that represents the topology 19493e97647fSksagiyam . viewer - The PetscViewer to save data with 19503e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined 19513e97647fSksagiyam - vec - The global vector to be saved 19523e97647fSksagiyam 19533e97647fSksagiyam Level: advanced 19543e97647fSksagiyam 19553e97647fSksagiyam Notes: 19563e97647fSksagiyam 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. 19573e97647fSksagiyam 19583e97647fSksagiyam Typical calling sequence 19593e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 19603e97647fSksagiyam $ DMSetType(dm, DMPLEX); 19613e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 19623e97647fSksagiyam $ DMClone(dm, §iondm); 19633e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 19643e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 19653e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 19663e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 19673e97647fSksagiyam $ PetscSectionSetUp(section); 19683e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 19693e97647fSksagiyam $ PetscSectionDestroy(§ion); 19703e97647fSksagiyam $ DMGetGlobalVector(sectiondm, &vec); 19713e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 19723e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 19733e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 19743e97647fSksagiyam $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 19753e97647fSksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 19763e97647fSksagiyam $ DMDestroy(§iondm); 19773e97647fSksagiyam $ DMDestroy(&dm); 19783e97647fSksagiyam 1979db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 19803e97647fSksagiyam @*/ 19819371c9d4SSatish Balay PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) { 19823e97647fSksagiyam PetscBool ishdf5; 19833e97647fSksagiyam 19843e97647fSksagiyam PetscFunctionBegin; 19853e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19863e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19873e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19883e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 19893e97647fSksagiyam /* Check consistency */ 19903e97647fSksagiyam { 19913e97647fSksagiyam PetscSection section; 19923e97647fSksagiyam PetscBool includesConstraints; 19933e97647fSksagiyam PetscInt m, m1; 19943e97647fSksagiyam 19959566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 19969566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 19979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 19989566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 19999566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 200063a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 20013e97647fSksagiyam } 20029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 20043e97647fSksagiyam if (ishdf5) { 20053e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 20069566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20073e97647fSksagiyam #else 20083e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20093e97647fSksagiyam #endif 20103e97647fSksagiyam } 20119566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 20123e97647fSksagiyam PetscFunctionReturn(0); 20133e97647fSksagiyam } 20143e97647fSksagiyam 20153e97647fSksagiyam /*@ 20163e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 20173e97647fSksagiyam 20183e97647fSksagiyam Collective on DM 20193e97647fSksagiyam 20203e97647fSksagiyam Input Parameters: 20213e97647fSksagiyam + dm - The DM that represents the topology 20223e97647fSksagiyam . viewer - The PetscViewer to save data with 20233e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 20243e97647fSksagiyam - vec - The local vector to be saved 20253e97647fSksagiyam 20263e97647fSksagiyam Level: advanced 20273e97647fSksagiyam 20283e97647fSksagiyam Notes: 20293e97647fSksagiyam 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. 20303e97647fSksagiyam 20313e97647fSksagiyam Typical calling sequence 20323e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 20333e97647fSksagiyam $ DMSetType(dm, DMPLEX); 20343e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 20353e97647fSksagiyam $ DMClone(dm, §iondm); 20363e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 20373e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 20383e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 20393e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 20403e97647fSksagiyam $ PetscSectionSetUp(section); 20413e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 20423e97647fSksagiyam $ DMGetLocalVector(sectiondm, &vec); 20433e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 20443e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 20453e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 20463e97647fSksagiyam $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 20473e97647fSksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 20483e97647fSksagiyam $ DMDestroy(§iondm); 20493e97647fSksagiyam $ DMDestroy(&dm); 20503e97647fSksagiyam 2051db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 20523e97647fSksagiyam @*/ 20539371c9d4SSatish Balay PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) { 20543e97647fSksagiyam PetscBool ishdf5; 20553e97647fSksagiyam 20563e97647fSksagiyam PetscFunctionBegin; 20573e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20583e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20593e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 20603e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 20613e97647fSksagiyam /* Check consistency */ 20623e97647fSksagiyam { 20633e97647fSksagiyam PetscSection section; 20643e97647fSksagiyam PetscBool includesConstraints; 20653e97647fSksagiyam PetscInt m, m1; 20663e97647fSksagiyam 20679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 20689566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 20699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 20709566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 20719566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 207263a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 20733e97647fSksagiyam } 20749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20759566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 20763e97647fSksagiyam if (ishdf5) { 20773e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 20789566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20793e97647fSksagiyam #else 20803e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20813e97647fSksagiyam #endif 20823e97647fSksagiyam } 20839566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 20843e97647fSksagiyam PetscFunctionReturn(0); 20853e97647fSksagiyam } 20863e97647fSksagiyam 20879371c9d4SSatish Balay PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) { 2088d4f5a9a0SVaclav Hapla PetscBool ishdf5; 20892c40f234SMatthew G. Knepley 20902c40f234SMatthew G. Knepley PetscFunctionBegin; 20912c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20922c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2094d4f5a9a0SVaclav Hapla if (ishdf5) { 20952c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 20969c48423bSVaclav Hapla PetscViewerFormat format; 20979566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20989c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 20999566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2100509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21019566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 210298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2103b458e8f1SJose E. Roman PetscFunctionReturn(0); 21042c40f234SMatthew G. Knepley #else 21052c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2106552f7358SJed Brown #endif 210798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2108552f7358SJed Brown } 2109552f7358SJed Brown 2110ea8e1828Sksagiyam /*@ 2111ea8e1828Sksagiyam DMPlexTopologyLoad - Loads a topology into a DMPlex 2112ea8e1828Sksagiyam 2113ea8e1828Sksagiyam Collective on DM 2114ea8e1828Sksagiyam 2115ea8e1828Sksagiyam Input Parameters: 2116ea8e1828Sksagiyam + dm - The DM into which the topology is loaded 2117ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology 2118ea8e1828Sksagiyam 2119dec9e869Sksagiyam Output Parameters: 2120f84dd6b4Sksagiyam . 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 2121dec9e869Sksagiyam 2122ea8e1828Sksagiyam Level: advanced 2123ea8e1828Sksagiyam 2124db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 2125ea8e1828Sksagiyam @*/ 21269371c9d4SSatish Balay PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) { 2127ea8e1828Sksagiyam PetscBool ishdf5; 2128ea8e1828Sksagiyam 2129ea8e1828Sksagiyam PetscFunctionBegin; 2130ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2131ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2132f84dd6b4Sksagiyam if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 21339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2135ea8e1828Sksagiyam if (ishdf5) { 2136ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2137ea8e1828Sksagiyam PetscViewerFormat format; 21389566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2139ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21409566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 214198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2142ea8e1828Sksagiyam #else 2143ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2144ea8e1828Sksagiyam #endif 2145ea8e1828Sksagiyam } 21469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2147ea8e1828Sksagiyam PetscFunctionReturn(0); 2148ea8e1828Sksagiyam } 2149ea8e1828Sksagiyam 21503e701f1cSksagiyam /*@ 21513e701f1cSksagiyam DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 21523e701f1cSksagiyam 21533e701f1cSksagiyam Collective on DM 21543e701f1cSksagiyam 21553e701f1cSksagiyam Input Parameters: 21563e701f1cSksagiyam + dm - The DM into which the coordinates are loaded 2157c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates 2158c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 21593e701f1cSksagiyam 21603e701f1cSksagiyam Level: advanced 21613e701f1cSksagiyam 2162db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 21633e701f1cSksagiyam @*/ 21649371c9d4SSatish Balay PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) { 21653e701f1cSksagiyam PetscBool ishdf5; 21663e701f1cSksagiyam 21673e701f1cSksagiyam PetscFunctionBegin; 21683e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21693e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2170c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 21719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21729566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 21733e701f1cSksagiyam if (ishdf5) { 21743e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 21753e701f1cSksagiyam PetscViewerFormat format; 21769566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 21773e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21789566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 217998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 21803e701f1cSksagiyam #else 21813e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21823e701f1cSksagiyam #endif 21833e701f1cSksagiyam } 21849566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 21853e701f1cSksagiyam PetscFunctionReturn(0); 21863e701f1cSksagiyam } 21873e701f1cSksagiyam 2188b08ad5deSksagiyam /*@ 2189b08ad5deSksagiyam DMPlexLabelsLoad - Loads labels into a DMPlex 2190b08ad5deSksagiyam 2191b08ad5deSksagiyam Collective on DM 2192b08ad5deSksagiyam 2193b08ad5deSksagiyam Input Parameters: 2194b08ad5deSksagiyam + dm - The DM into which the labels are loaded 2195e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels 2196e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2197b08ad5deSksagiyam 2198b08ad5deSksagiyam Level: advanced 2199b08ad5deSksagiyam 2200e6368b79SVaclav Hapla Notes: 2201e6368b79SVaclav Hapla The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs. 2202e6368b79SVaclav Hapla 2203db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 2204b08ad5deSksagiyam @*/ 22059371c9d4SSatish Balay PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) { 2206b08ad5deSksagiyam PetscBool ishdf5; 2207b08ad5deSksagiyam 2208b08ad5deSksagiyam PetscFunctionBegin; 2209b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2210b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2211e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22139566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2214b08ad5deSksagiyam if (ishdf5) { 2215b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2216b08ad5deSksagiyam PetscViewerFormat format; 2217b08ad5deSksagiyam 22189566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2219b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22209566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 222198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2222b08ad5deSksagiyam #else 2223b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2224b08ad5deSksagiyam #endif 2225b08ad5deSksagiyam } 22269566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2227b08ad5deSksagiyam PetscFunctionReturn(0); 2228b08ad5deSksagiyam } 2229b08ad5deSksagiyam 2230f84dd6b4Sksagiyam /*@ 2231f84dd6b4Sksagiyam DMPlexSectionLoad - Loads section into a DMPlex 2232f84dd6b4Sksagiyam 2233f84dd6b4Sksagiyam Collective on DM 2234f84dd6b4Sksagiyam 2235f84dd6b4Sksagiyam Input Parameters: 2236f84dd6b4Sksagiyam + dm - The DM that represents the topology 2237f84dd6b4Sksagiyam . viewer - The PetscViewer that represents the on-disk section (sectionA) 2238f84dd6b4Sksagiyam . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2239f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2240f84dd6b4Sksagiyam 2241f84dd6b4Sksagiyam Output Parameters 2242f84dd6b4Sksagiyam + 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) 2243f84dd6b4Sksagiyam - 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) 2244f84dd6b4Sksagiyam 2245f84dd6b4Sksagiyam Level: advanced 2246f84dd6b4Sksagiyam 2247f84dd6b4Sksagiyam Notes: 2248f84dd6b4Sksagiyam 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. 2249f84dd6b4Sksagiyam 2250f84dd6b4Sksagiyam 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. 2251f84dd6b4Sksagiyam 2252f84dd6b4Sksagiyam 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. 2253f84dd6b4Sksagiyam 2254f84dd6b4Sksagiyam Example using 2 processes: 2255f84dd6b4Sksagiyam $ NX (number of points on dm): 4 2256f84dd6b4Sksagiyam $ sectionA : the on-disk section 2257f84dd6b4Sksagiyam $ vecA : a vector associated with sectionA 2258f84dd6b4Sksagiyam $ sectionB : sectiondm's local section constructed in this function 2259f84dd6b4Sksagiyam $ vecB (local) : a vector associated with sectiondm's local section 2260f84dd6b4Sksagiyam $ vecB (global) : a vector associated with sectiondm's global section 2261f84dd6b4Sksagiyam $ 2262f84dd6b4Sksagiyam $ rank 0 rank 1 2263f84dd6b4Sksagiyam $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2264f84dd6b4Sksagiyam $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2265f84dd6b4Sksagiyam $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2266f84dd6b4Sksagiyam $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2267f84dd6b4Sksagiyam $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2268f84dd6b4Sksagiyam $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2269f84dd6b4Sksagiyam $ sectionB->atlasDof : 1 0 1 | 1 3 2270f84dd6b4Sksagiyam $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2271f84dd6b4Sksagiyam $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2272f84dd6b4Sksagiyam $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2273f84dd6b4Sksagiyam $ 2274f84dd6b4Sksagiyam $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2275f84dd6b4Sksagiyam 2276db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()` 2277f84dd6b4Sksagiyam @*/ 22789371c9d4SSatish Balay PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) { 2279f84dd6b4Sksagiyam PetscBool ishdf5; 2280f84dd6b4Sksagiyam 2281f84dd6b4Sksagiyam PetscFunctionBegin; 2282f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2283f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2284f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2285f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2286f84dd6b4Sksagiyam if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2287f84dd6b4Sksagiyam if (localDofSF) PetscValidPointer(localDofSF, 6); 22889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22899566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2290f84dd6b4Sksagiyam if (ishdf5) { 2291f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 22929566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2293f84dd6b4Sksagiyam #else 2294f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2295f84dd6b4Sksagiyam #endif 2296f84dd6b4Sksagiyam } 22979566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2298f84dd6b4Sksagiyam PetscFunctionReturn(0); 2299f84dd6b4Sksagiyam } 2300f84dd6b4Sksagiyam 23018be3dfe1Sksagiyam /*@ 23028be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 23038be3dfe1Sksagiyam 23048be3dfe1Sksagiyam Collective on DM 23058be3dfe1Sksagiyam 23068be3dfe1Sksagiyam Input Parameters: 23078be3dfe1Sksagiyam + dm - The DM that represents the topology 23088be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23098be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined 23108be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23118be3dfe1Sksagiyam - vec - The global vector to set values of 23128be3dfe1Sksagiyam 23138be3dfe1Sksagiyam Level: advanced 23148be3dfe1Sksagiyam 23158be3dfe1Sksagiyam Notes: 23168be3dfe1Sksagiyam 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. 23178be3dfe1Sksagiyam 23188be3dfe1Sksagiyam Typical calling sequence 23198be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23208be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23218be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23228be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23238be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23248be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23258be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 23268be3dfe1Sksagiyam $ DMGetGlobalVector(sectiondm, &vec); 23278be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23288be3dfe1Sksagiyam $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 23298be3dfe1Sksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 23308be3dfe1Sksagiyam $ PetscSFDestroy(&gsf); 23318be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 23328be3dfe1Sksagiyam $ DMDestroy(§iondm); 23338be3dfe1Sksagiyam $ DMDestroy(&dm); 23348be3dfe1Sksagiyam 2335db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()` 23368be3dfe1Sksagiyam @*/ 23379371c9d4SSatish Balay PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) { 23388be3dfe1Sksagiyam PetscBool ishdf5; 23398be3dfe1Sksagiyam 23408be3dfe1Sksagiyam PetscFunctionBegin; 23418be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23428be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23438be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 23448be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 23458be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 23468be3dfe1Sksagiyam /* Check consistency */ 23478be3dfe1Sksagiyam { 23488be3dfe1Sksagiyam PetscSection section; 23498be3dfe1Sksagiyam PetscBool includesConstraints; 23508be3dfe1Sksagiyam PetscInt m, m1; 23518be3dfe1Sksagiyam 23529566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 23539566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 23549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 23559566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 23569566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 235763a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 23588be3dfe1Sksagiyam } 23599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23609566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 23618be3dfe1Sksagiyam if (ishdf5) { 23628be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 23639566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 23648be3dfe1Sksagiyam #else 23658be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23668be3dfe1Sksagiyam #endif 23678be3dfe1Sksagiyam } 23689566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 23698be3dfe1Sksagiyam PetscFunctionReturn(0); 23708be3dfe1Sksagiyam } 23718be3dfe1Sksagiyam 23728be3dfe1Sksagiyam /*@ 23738be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 23748be3dfe1Sksagiyam 23758be3dfe1Sksagiyam Collective on DM 23768be3dfe1Sksagiyam 23778be3dfe1Sksagiyam Input Parameters: 23788be3dfe1Sksagiyam + dm - The DM that represents the topology 23798be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23808be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined 23818be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23828be3dfe1Sksagiyam - vec - The local vector to set values of 23838be3dfe1Sksagiyam 23848be3dfe1Sksagiyam Level: advanced 23858be3dfe1Sksagiyam 23868be3dfe1Sksagiyam Notes: 23878be3dfe1Sksagiyam 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. 23888be3dfe1Sksagiyam 23898be3dfe1Sksagiyam Typical calling sequence 23908be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23918be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23928be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23938be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23948be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23958be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23968be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 23978be3dfe1Sksagiyam $ DMGetLocalVector(sectiondm, &vec); 23988be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23998be3dfe1Sksagiyam $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 24008be3dfe1Sksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 24018be3dfe1Sksagiyam $ PetscSFDestroy(&lsf); 24028be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 24038be3dfe1Sksagiyam $ DMDestroy(§iondm); 24048be3dfe1Sksagiyam $ DMDestroy(&dm); 24058be3dfe1Sksagiyam 2406db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()` 24078be3dfe1Sksagiyam @*/ 24089371c9d4SSatish Balay PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) { 24098be3dfe1Sksagiyam PetscBool ishdf5; 24108be3dfe1Sksagiyam 24118be3dfe1Sksagiyam PetscFunctionBegin; 24128be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24138be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24148be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24158be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24168be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24178be3dfe1Sksagiyam /* Check consistency */ 24188be3dfe1Sksagiyam { 24198be3dfe1Sksagiyam PetscSection section; 24208be3dfe1Sksagiyam PetscBool includesConstraints; 24218be3dfe1Sksagiyam PetscInt m, m1; 24228be3dfe1Sksagiyam 24239566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 24249566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 24259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24269566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 24279566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 242863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 24298be3dfe1Sksagiyam } 24309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 24328be3dfe1Sksagiyam if (ishdf5) { 24338be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 24349566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 24358be3dfe1Sksagiyam #else 24368be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24378be3dfe1Sksagiyam #endif 24388be3dfe1Sksagiyam } 24399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 24408be3dfe1Sksagiyam PetscFunctionReturn(0); 24418be3dfe1Sksagiyam } 24428be3dfe1Sksagiyam 24439371c9d4SSatish Balay PetscErrorCode DMDestroy_Plex(DM dm) { 2444552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2445552f7358SJed Brown 2446552f7358SJed Brown PetscFunctionBegin; 24479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 24489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 24499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 24509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 24512e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", NULL)); 24522e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 24532e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 24542e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 24552e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 24566bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 24576bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2458c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2459c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 24600d644c17SKarl Rupp if (--mesh->refct > 0) PetscFunctionReturn(0); 24619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 24629566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 24639566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 24649566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 24659566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 24669566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 24679566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->facesTmp)); 24689566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 24699566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 24709566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 24711d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 24729566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 24739566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 24749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 24759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 24769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 24779566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 24789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 24799566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 24809566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 24819566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 24829566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 24839566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 24849566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 24859566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 24869566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 24879566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2488552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 24899566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 2490552f7358SJed Brown PetscFunctionReturn(0); 2491552f7358SJed Brown } 2492552f7358SJed Brown 24939371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) { 24948d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2495acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 24969fca9976SJed Brown PetscInt localSize, localStart = 0; 2497837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2498b412c318SBarry Smith MatType mtype; 24991428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2500552f7358SJed Brown 2501552f7358SJed Brown PetscFunctionBegin; 25029566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2503b412c318SBarry Smith mtype = dm->mattype; 25049566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 25059566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 25069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 25079fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 25089566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 25099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 25109566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 25119566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 25129566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2513acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 25149566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 25159566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 25169566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 25179566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 25189566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 25199566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 25209566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 25219566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2522552f7358SJed Brown if (!isShell) { 2523837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 25249fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2525fad22124SMatthew G Knepley PetscInt pStart, pEnd, p, dof, cdof; 2526552f7358SJed Brown 25279566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 25289fca9976SJed Brown 25299fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 25309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2531e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 25329fca9976SJed Brown PetscInt bdof, offset; 2533a9d99c84SMatthew G. Knepley 25349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 25359fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 25369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 25379371c9d4SSatish Balay for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof; 25381d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 25391d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 25401d17a0a3SMatthew G. Knepley if (dof) { 25419371c9d4SSatish Balay if (bs < 0) { 25429371c9d4SSatish Balay bs = bdof; 25439371c9d4SSatish Balay } else if (bs != bdof) { 25449371c9d4SSatish Balay bs = 1; 25459371c9d4SSatish Balay } 2546552f7358SJed Brown } 25472a28c762SMatthew G Knepley } 25482a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2549e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2550e432b41dSStefano Zampini bsLocal[1] = bs; 25519566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2552e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2553e432b41dSStefano Zampini else bs = bsMinMax[0]; 25546fd5c86aSStefano Zampini bs = PetscMax(1, bs); 25559566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 25560682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 25579566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 25589566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 25590682b8bbSJed Brown } else { 25609566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 25619566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 25629566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2563552f7358SJed Brown } 25649fca9976SJed Brown { // Consolidate blocks 25659fca9976SJed Brown PetscInt nblocks = 0; 25669fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 25679fca9976SJed Brown if (pblocks[i] == 0) continue; 25689fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2569ad540459SPierre 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]); 25709fca9976SJed Brown } 25719fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 25729fca9976SJed Brown } 25739fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2574aa0f6e3cSJed Brown } 25759566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 2576552f7358SJed Brown PetscFunctionReturn(0); 2577552f7358SJed Brown } 2578552f7358SJed Brown 25797cd05799SMatthew G. Knepley /*@ 2580a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2581be36d101SStefano Zampini 2582be36d101SStefano Zampini Not collective 2583be36d101SStefano Zampini 2584be36d101SStefano Zampini Input Parameter: 2585be36d101SStefano Zampini . mesh - The DMPlex 2586be36d101SStefano Zampini 2587be36d101SStefano Zampini Output Parameters: 2588be36d101SStefano Zampini . subsection - The subdomain section 2589be36d101SStefano Zampini 2590be36d101SStefano Zampini Level: developer 2591be36d101SStefano Zampini 2592be36d101SStefano Zampini .seealso: 25937cd05799SMatthew G. Knepley @*/ 25949371c9d4SSatish Balay PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) { 2595be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2596be36d101SStefano Zampini 2597be36d101SStefano Zampini PetscFunctionBegin; 2598be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2599be36d101SStefano Zampini if (!mesh->subdomainSection) { 2600be36d101SStefano Zampini PetscSection section; 2601be36d101SStefano Zampini PetscSF sf; 2602be36d101SStefano Zampini 26039566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 26049566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 26059566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 26069566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2607be36d101SStefano Zampini } 2608be36d101SStefano Zampini *subsection = mesh->subdomainSection; 2609be36d101SStefano Zampini PetscFunctionReturn(0); 2610be36d101SStefano Zampini } 2611be36d101SStefano Zampini 2612552f7358SJed Brown /*@ 2613552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2614552f7358SJed Brown 2615552f7358SJed Brown Not collective 2616552f7358SJed Brown 2617552f7358SJed Brown Input Parameter: 2618552f7358SJed Brown . mesh - The DMPlex 2619552f7358SJed Brown 2620552f7358SJed Brown Output Parameters: 2621552f7358SJed Brown + pStart - The first mesh point 2622552f7358SJed Brown - pEnd - The upper bound for mesh points 2623552f7358SJed Brown 2624552f7358SJed Brown Level: beginner 2625552f7358SJed Brown 2626db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()` 2627552f7358SJed Brown @*/ 26289371c9d4SSatish Balay PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) { 2629552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2630552f7358SJed Brown 2631552f7358SJed Brown PetscFunctionBegin; 2632552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 2634552f7358SJed Brown PetscFunctionReturn(0); 2635552f7358SJed Brown } 2636552f7358SJed Brown 2637552f7358SJed Brown /*@ 2638552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2639552f7358SJed Brown 2640552f7358SJed Brown Not collective 2641552f7358SJed Brown 2642552f7358SJed Brown Input Parameters: 2643552f7358SJed Brown + mesh - The DMPlex 2644552f7358SJed Brown . pStart - The first mesh point 2645552f7358SJed Brown - pEnd - The upper bound for mesh points 2646552f7358SJed Brown 2647552f7358SJed Brown Output Parameters: 2648552f7358SJed Brown 2649552f7358SJed Brown Level: beginner 2650552f7358SJed Brown 2651db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()` 2652552f7358SJed Brown @*/ 26539371c9d4SSatish Balay PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) { 2654552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2655552f7358SJed Brown 2656552f7358SJed Brown PetscFunctionBegin; 2657552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 26599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 2660552f7358SJed Brown PetscFunctionReturn(0); 2661552f7358SJed Brown } 2662552f7358SJed Brown 2663552f7358SJed Brown /*@ 2664eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2665552f7358SJed Brown 2666552f7358SJed Brown Not collective 2667552f7358SJed Brown 2668552f7358SJed Brown Input Parameters: 2669552f7358SJed Brown + mesh - The DMPlex 2670eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2671552f7358SJed Brown 2672552f7358SJed Brown Output Parameter: 2673552f7358SJed Brown . size - The cone size for point p 2674552f7358SJed Brown 2675552f7358SJed Brown Level: beginner 2676552f7358SJed Brown 2677db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2678552f7358SJed Brown @*/ 26799371c9d4SSatish Balay PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) { 2680552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2681552f7358SJed Brown 2682552f7358SJed Brown PetscFunctionBegin; 2683552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2684dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 26859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 2686552f7358SJed Brown PetscFunctionReturn(0); 2687552f7358SJed Brown } 2688552f7358SJed Brown 2689552f7358SJed Brown /*@ 2690eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2691552f7358SJed Brown 2692552f7358SJed Brown Not collective 2693552f7358SJed Brown 2694552f7358SJed Brown Input Parameters: 2695552f7358SJed Brown + mesh - The DMPlex 2696eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2697552f7358SJed Brown - size - The cone size for point p 2698552f7358SJed Brown 2699552f7358SJed Brown Output Parameter: 2700552f7358SJed Brown 2701552f7358SJed Brown Note: 2702552f7358SJed Brown This should be called after DMPlexSetChart(). 2703552f7358SJed Brown 2704552f7358SJed Brown Level: beginner 2705552f7358SJed Brown 2706db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2707552f7358SJed Brown @*/ 27089371c9d4SSatish Balay PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) { 2709552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2710552f7358SJed Brown 2711552f7358SJed Brown PetscFunctionBegin; 2712552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 2714552f7358SJed Brown PetscFunctionReturn(0); 2715552f7358SJed Brown } 2716552f7358SJed Brown 2717f5a469b9SMatthew G. Knepley /*@ 2718eaf898f9SPatrick Sanan DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2719f5a469b9SMatthew G. Knepley 2720f5a469b9SMatthew G. Knepley Not collective 2721f5a469b9SMatthew G. Knepley 2722f5a469b9SMatthew G. Knepley Input Parameters: 2723f5a469b9SMatthew G. Knepley + mesh - The DMPlex 2724eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2725f5a469b9SMatthew G. Knepley - size - The additional cone size for point p 2726f5a469b9SMatthew G. Knepley 2727f5a469b9SMatthew G. Knepley Output Parameter: 2728f5a469b9SMatthew G. Knepley 2729f5a469b9SMatthew G. Knepley Note: 2730f5a469b9SMatthew G. Knepley This should be called after DMPlexSetChart(). 2731f5a469b9SMatthew G. Knepley 2732f5a469b9SMatthew G. Knepley Level: beginner 2733f5a469b9SMatthew G. Knepley 2734db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2735f5a469b9SMatthew G. Knepley @*/ 27369371c9d4SSatish Balay PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) { 2737f5a469b9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2738f5a469b9SMatthew G. Knepley PetscFunctionBegin; 2739f5a469b9SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27409566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->coneSection, p, size)); 2741f5a469b9SMatthew G. Knepley PetscFunctionReturn(0); 2742f5a469b9SMatthew G. Knepley } 2743f5a469b9SMatthew G. Knepley 2744552f7358SJed Brown /*@C 2745eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2746552f7358SJed Brown 2747552f7358SJed Brown Not collective 2748552f7358SJed Brown 2749552f7358SJed Brown Input Parameters: 2750833c876bSVaclav Hapla + dm - The DMPlex 2751eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2752552f7358SJed Brown 2753552f7358SJed Brown Output Parameter: 2754552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 2755552f7358SJed Brown 2756552f7358SJed Brown Level: beginner 2757552f7358SJed Brown 27583813dfbdSMatthew G Knepley Fortran Notes: 27593813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 27603813dfbdSMatthew G Knepley include petsc.h90 in your code. 2761922102d1SVaclav Hapla You must also call DMPlexRestoreCone() after you finish using the returned array. 2762922102d1SVaclav Hapla DMPlexRestoreCone() is not needed/available in C. 27633813dfbdSMatthew G Knepley 2764db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()` 2765552f7358SJed Brown @*/ 27669371c9d4SSatish Balay PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) { 2767552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2768552f7358SJed Brown PetscInt off; 2769552f7358SJed Brown 2770552f7358SJed Brown PetscFunctionBegin; 2771552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2772552f7358SJed Brown PetscValidPointer(cone, 3); 27739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 2774552f7358SJed Brown *cone = &mesh->cones[off]; 2775552f7358SJed Brown PetscFunctionReturn(0); 2776552f7358SJed Brown } 2777552f7358SJed Brown 27780ce7577fSVaclav Hapla /*@C 27790ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 27800ce7577fSVaclav Hapla 27810ce7577fSVaclav Hapla Not collective 27820ce7577fSVaclav Hapla 27830ce7577fSVaclav Hapla Input Parameters: 27840ce7577fSVaclav Hapla + dm - The DMPlex 27850ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 27860ce7577fSVaclav Hapla 2787d8d19677SJose E. Roman Output Parameters: 27880ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones 27890ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p 27900ce7577fSVaclav Hapla 27910ce7577fSVaclav Hapla Level: intermediate 27920ce7577fSVaclav Hapla 2793db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()` 27940ce7577fSVaclav Hapla @*/ 27959371c9d4SSatish Balay PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) { 27960ce7577fSVaclav Hapla PetscSection cs, newcs; 27970ce7577fSVaclav Hapla PetscInt *cones; 27980ce7577fSVaclav Hapla PetscInt *newarr = NULL; 27990ce7577fSVaclav Hapla PetscInt n; 28000ce7577fSVaclav Hapla 28010ce7577fSVaclav Hapla PetscFunctionBegin; 28029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 28039566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 28049566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 28050ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 28060ce7577fSVaclav Hapla if (pCones) { 28079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 28089566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 28090ce7577fSVaclav Hapla } 28100ce7577fSVaclav Hapla PetscFunctionReturn(0); 28110ce7577fSVaclav Hapla } 28120ce7577fSVaclav Hapla 2813af9eab45SVaclav Hapla /*@ 2814af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2815d4636a37SVaclav Hapla 2816d4636a37SVaclav Hapla Not collective 2817d4636a37SVaclav Hapla 2818d4636a37SVaclav Hapla Input Parameters: 2819d4636a37SVaclav Hapla + dm - The DMPlex 2820af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2821d4636a37SVaclav Hapla 2822d4636a37SVaclav Hapla Output Parameter: 2823af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 2824d4636a37SVaclav Hapla 2825d4636a37SVaclav Hapla Level: advanced 2826d4636a37SVaclav Hapla 2827af9eab45SVaclav Hapla Notes: 2828af9eab45SVaclav Hapla Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2829af9eab45SVaclav Hapla There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2830af9eab45SVaclav Hapla 2831db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()` 2832d4636a37SVaclav Hapla @*/ 28339371c9d4SSatish Balay PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) { 2834af9eab45SVaclav Hapla IS *expandedPointsAll; 2835af9eab45SVaclav Hapla PetscInt depth; 2836d4636a37SVaclav Hapla 2837d4636a37SVaclav Hapla PetscFunctionBegin; 2838af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2839af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2840af9eab45SVaclav Hapla PetscValidPointer(expandedPoints, 3); 28419566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2842af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 28439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 28449566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2845af9eab45SVaclav Hapla PetscFunctionReturn(0); 2846af9eab45SVaclav Hapla } 2847af9eab45SVaclav Hapla 2848af9eab45SVaclav Hapla /*@ 2849af9eab45SVaclav 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). 2850af9eab45SVaclav Hapla 2851af9eab45SVaclav Hapla Not collective 2852af9eab45SVaclav Hapla 2853af9eab45SVaclav Hapla Input Parameters: 2854af9eab45SVaclav Hapla + dm - The DMPlex 2855af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2856af9eab45SVaclav Hapla 2857d8d19677SJose E. Roman Output Parameters: 2858af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2859af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 2860af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2861af9eab45SVaclav Hapla 2862af9eab45SVaclav Hapla Level: advanced 2863af9eab45SVaclav Hapla 2864af9eab45SVaclav Hapla Notes: 2865af9eab45SVaclav Hapla Like DMPlexGetConeTuple() but recursive. 2866af9eab45SVaclav Hapla 2867af9eab45SVaclav 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. 2868af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2869af9eab45SVaclav Hapla 2870af9eab45SVaclav Hapla 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: 2871af9eab45SVaclav Hapla (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2872af9eab45SVaclav Hapla (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2873af9eab45SVaclav Hapla 2874db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2875af9eab45SVaclav Hapla @*/ 28769371c9d4SSatish Balay PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) { 2877af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 2878af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 2879af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 2880af9eab45SVaclav Hapla IS *expandedPoints_; 2881af9eab45SVaclav Hapla PetscSection *sections_; 2882af9eab45SVaclav Hapla 2883af9eab45SVaclav Hapla PetscFunctionBegin; 2884af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2885af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2886af9eab45SVaclav Hapla if (depth) PetscValidIntPointer(depth, 3); 2887af9eab45SVaclav Hapla if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2888af9eab45SVaclav Hapla if (sections) PetscValidPointer(sections, 5); 28899566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 28909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 28919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 28929566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 28939566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 2894af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 2895af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 28969566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 28979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 2898af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 28999566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 2900af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 29019566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 29029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 2903af9eab45SVaclav Hapla } else { 29049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 2905af9eab45SVaclav Hapla } 2906af9eab45SVaclav Hapla } 29079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 29089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 29099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 2910af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 29119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 29129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 2913af9eab45SVaclav Hapla if (cn > 1) { 29149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 29159566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 2916af9eab45SVaclav Hapla } else { 2917af9eab45SVaclav Hapla newarr[co] = arr[i]; 2918af9eab45SVaclav Hapla } 2919af9eab45SVaclav Hapla } 29209566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 2921af9eab45SVaclav Hapla arr = newarr; 2922af9eab45SVaclav Hapla n = newn; 2923af9eab45SVaclav Hapla } 29249566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 2925af9eab45SVaclav Hapla *depth = depth_; 2926af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 2927af9eab45SVaclav Hapla else { 29289566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 29299566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 2930af9eab45SVaclav Hapla } 2931af9eab45SVaclav Hapla if (sections) *sections = sections_; 2932af9eab45SVaclav Hapla else { 29339566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 29349566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 2935af9eab45SVaclav Hapla } 2936af9eab45SVaclav Hapla PetscFunctionReturn(0); 2937af9eab45SVaclav Hapla } 2938af9eab45SVaclav Hapla 2939af9eab45SVaclav Hapla /*@ 2940af9eab45SVaclav Hapla DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2941af9eab45SVaclav Hapla 2942af9eab45SVaclav Hapla Not collective 2943af9eab45SVaclav Hapla 2944af9eab45SVaclav Hapla Input Parameters: 2945af9eab45SVaclav Hapla + dm - The DMPlex 2946af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2947af9eab45SVaclav Hapla 2948d8d19677SJose E. Roman Output Parameters: 2949af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2950af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 2951af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2952af9eab45SVaclav Hapla 2953af9eab45SVaclav Hapla Level: advanced 2954af9eab45SVaclav Hapla 2955af9eab45SVaclav Hapla Notes: 2956af9eab45SVaclav Hapla See DMPlexGetConeRecursive() for details. 2957af9eab45SVaclav Hapla 2958db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2959af9eab45SVaclav Hapla @*/ 29609371c9d4SSatish Balay PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) { 2961af9eab45SVaclav Hapla PetscInt d, depth_; 2962af9eab45SVaclav Hapla 2963af9eab45SVaclav Hapla PetscFunctionBegin; 29649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29651dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2966af9eab45SVaclav Hapla if (depth) *depth = 0; 2967af9eab45SVaclav Hapla if (expandedPoints) { 29689566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 29699566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 2970af9eab45SVaclav Hapla } 2971af9eab45SVaclav Hapla if (sections) { 29729566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 29739566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 2974af9eab45SVaclav Hapla } 2975d4636a37SVaclav Hapla PetscFunctionReturn(0); 2976d4636a37SVaclav Hapla } 2977d4636a37SVaclav Hapla 2978552f7358SJed Brown /*@ 297992371b87SBarry 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 2980552f7358SJed Brown 2981552f7358SJed Brown Not collective 2982552f7358SJed Brown 2983552f7358SJed Brown Input Parameters: 2984552f7358SJed Brown + mesh - The DMPlex 2985eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2986552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 2987552f7358SJed Brown 2988552f7358SJed Brown Output Parameter: 2989552f7358SJed Brown 2990552f7358SJed Brown Note: 2991552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2992552f7358SJed Brown 2993552f7358SJed Brown Level: beginner 2994552f7358SJed Brown 2995db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 2996552f7358SJed Brown @*/ 29979371c9d4SSatish Balay PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) { 2998552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2999552f7358SJed Brown PetscInt pStart, pEnd; 3000552f7358SJed Brown PetscInt dof, off, c; 3001552f7358SJed Brown 3002552f7358SJed Brown PetscFunctionBegin; 3003552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 30059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3006dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(cone, 3); 30079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 300863a3b9bcSJacob 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); 3009552f7358SJed Brown for (c = 0; c < dof; ++c) { 301063a3b9bcSJacob 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); 3011552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3012552f7358SJed Brown } 3013552f7358SJed Brown PetscFunctionReturn(0); 3014552f7358SJed Brown } 3015552f7358SJed Brown 3016552f7358SJed Brown /*@C 3017eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3018552f7358SJed Brown 3019552f7358SJed Brown Not collective 3020552f7358SJed Brown 3021552f7358SJed Brown Input Parameters: 3022552f7358SJed Brown + mesh - The DMPlex 3023eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3024552f7358SJed Brown 3025552f7358SJed Brown Output Parameter: 3026552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 3027b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3028552f7358SJed Brown 3029552f7358SJed Brown Level: beginner 3030552f7358SJed Brown 3031b5a892a1SMatthew G. Knepley Notes: 3032b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3033b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3034b5a892a1SMatthew G. Knepley of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 3035b5a892a1SMatthew G. Knepley with the identity. 3036b5a892a1SMatthew G. Knepley 30373813dfbdSMatthew G Knepley Fortran Notes: 30383813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 30393813dfbdSMatthew G Knepley include petsc.h90 in your code. 30403b12b3d8SVaclav Hapla You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 3041922102d1SVaclav Hapla DMPlexRestoreConeOrientation() is not needed/available in C. 30423813dfbdSMatthew G Knepley 3043db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3044552f7358SJed Brown @*/ 30459371c9d4SSatish Balay PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) { 3046552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3047552f7358SJed Brown PetscInt off; 3048552f7358SJed Brown 3049552f7358SJed Brown PetscFunctionBegin; 3050552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 305176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3052552f7358SJed Brown PetscInt dof; 30539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3054552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 3055552f7358SJed Brown } 30569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30570d644c17SKarl Rupp 3058552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 3059552f7358SJed Brown PetscFunctionReturn(0); 3060552f7358SJed Brown } 3061552f7358SJed Brown 3062552f7358SJed Brown /*@ 3063eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3064552f7358SJed Brown 3065552f7358SJed Brown Not collective 3066552f7358SJed Brown 3067552f7358SJed Brown Input Parameters: 3068552f7358SJed Brown + mesh - The DMPlex 3069eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3070b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3071552f7358SJed Brown Output Parameter: 3072552f7358SJed Brown 3073b5a892a1SMatthew G. Knepley Notes: 3074552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3075552f7358SJed Brown 3076b5a892a1SMatthew G. Knepley The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3077b5a892a1SMatthew G. Knepley 3078552f7358SJed Brown Level: beginner 3079552f7358SJed Brown 3080db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3081552f7358SJed Brown @*/ 30829371c9d4SSatish Balay PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) { 3083552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3084552f7358SJed Brown PetscInt pStart, pEnd; 3085552f7358SJed Brown PetscInt dof, off, c; 3086552f7358SJed Brown 3087552f7358SJed Brown PetscFunctionBegin; 3088552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 30909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3091dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(coneOrientation, 3); 30929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 309363a3b9bcSJacob 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); 3094552f7358SJed Brown for (c = 0; c < dof; ++c) { 3095552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3096552f7358SJed Brown 30979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 30981dca8a05SBarry 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); 3099552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3100552f7358SJed Brown } 3101552f7358SJed Brown PetscFunctionReturn(0); 3102552f7358SJed Brown } 3103552f7358SJed Brown 31047cd05799SMatthew G. Knepley /*@ 3105eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 31067cd05799SMatthew G. Knepley 31077cd05799SMatthew G. Knepley Not collective 31087cd05799SMatthew G. Knepley 31097cd05799SMatthew G. Knepley Input Parameters: 31107cd05799SMatthew G. Knepley + mesh - The DMPlex 3111eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31127cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31137cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 31147cd05799SMatthew G. Knepley 31157cd05799SMatthew G. Knepley Level: beginner 31167cd05799SMatthew G. Knepley 3117db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31187cd05799SMatthew G. Knepley @*/ 31199371c9d4SSatish Balay PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) { 3120552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3121552f7358SJed Brown PetscInt pStart, pEnd; 3122552f7358SJed Brown PetscInt dof, off; 3123552f7358SJed Brown 3124552f7358SJed Brown PetscFunctionBegin; 3125552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 312763a3b9bcSJacob 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); 312863a3b9bcSJacob 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); 31299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 313163a3b9bcSJacob 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); 3132552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 3133552f7358SJed Brown PetscFunctionReturn(0); 3134552f7358SJed Brown } 3135552f7358SJed Brown 31367cd05799SMatthew G. Knepley /*@ 3137eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 31387cd05799SMatthew G. Knepley 31397cd05799SMatthew G. Knepley Not collective 31407cd05799SMatthew G. Knepley 31417cd05799SMatthew G. Knepley Input Parameters: 31427cd05799SMatthew G. Knepley + mesh - The DMPlex 3143eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31447cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31457cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 31467cd05799SMatthew G. Knepley 31477cd05799SMatthew G. Knepley Level: beginner 31487cd05799SMatthew G. Knepley 3149b5a892a1SMatthew G. Knepley Notes: 3150b5a892a1SMatthew G. Knepley The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3151b5a892a1SMatthew G. Knepley 3152db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31537cd05799SMatthew G. Knepley @*/ 31549371c9d4SSatish Balay PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) { 315577c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 315677c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 315777c88f5bSMatthew G Knepley PetscInt dof, off; 315877c88f5bSMatthew G Knepley 315977c88f5bSMatthew G Knepley PetscFunctionBegin; 316077c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 316263a3b9bcSJacob 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); 31639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 316563a3b9bcSJacob 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); 316677c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 316777c88f5bSMatthew G Knepley PetscFunctionReturn(0); 316877c88f5bSMatthew G Knepley } 316977c88f5bSMatthew G Knepley 3170552f7358SJed Brown /*@ 3171eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3172552f7358SJed Brown 3173552f7358SJed Brown Not collective 3174552f7358SJed Brown 3175552f7358SJed Brown Input Parameters: 3176552f7358SJed Brown + mesh - The DMPlex 3177eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3178552f7358SJed Brown 3179552f7358SJed Brown Output Parameter: 3180552f7358SJed Brown . size - The support size for point p 3181552f7358SJed Brown 3182552f7358SJed Brown Level: beginner 3183552f7358SJed Brown 3184db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3185552f7358SJed Brown @*/ 31869371c9d4SSatish Balay PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) { 3187552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3188552f7358SJed Brown 3189552f7358SJed Brown PetscFunctionBegin; 3190552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3191dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 31929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 3193552f7358SJed Brown PetscFunctionReturn(0); 3194552f7358SJed Brown } 3195552f7358SJed Brown 3196552f7358SJed Brown /*@ 3197eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3198552f7358SJed Brown 3199552f7358SJed Brown Not collective 3200552f7358SJed Brown 3201552f7358SJed Brown Input Parameters: 3202552f7358SJed Brown + mesh - The DMPlex 3203eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3204552f7358SJed Brown - size - The support size for point p 3205552f7358SJed Brown 3206552f7358SJed Brown Output Parameter: 3207552f7358SJed Brown 3208552f7358SJed Brown Note: 3209552f7358SJed Brown This should be called after DMPlexSetChart(). 3210552f7358SJed Brown 3211552f7358SJed Brown Level: beginner 3212552f7358SJed Brown 3213db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3214552f7358SJed Brown @*/ 32159371c9d4SSatish Balay PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) { 3216552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3217552f7358SJed Brown 3218552f7358SJed Brown PetscFunctionBegin; 3219552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 3221552f7358SJed Brown PetscFunctionReturn(0); 3222552f7358SJed Brown } 3223552f7358SJed Brown 3224552f7358SJed Brown /*@C 3225eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3226552f7358SJed Brown 3227552f7358SJed Brown Not collective 3228552f7358SJed Brown 3229552f7358SJed Brown Input Parameters: 3230552f7358SJed Brown + mesh - The DMPlex 3231eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3232552f7358SJed Brown 3233552f7358SJed Brown Output Parameter: 3234552f7358SJed Brown . support - An array of points which are on the out-edges for point p 3235552f7358SJed Brown 3236552f7358SJed Brown Level: beginner 3237552f7358SJed Brown 32383813dfbdSMatthew G Knepley Fortran Notes: 32393813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 32403813dfbdSMatthew G Knepley include petsc.h90 in your code. 32413b12b3d8SVaclav Hapla You must also call DMPlexRestoreSupport() after you finish using the returned array. 3242922102d1SVaclav Hapla DMPlexRestoreSupport() is not needed/available in C. 32433813dfbdSMatthew G Knepley 3244db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3245552f7358SJed Brown @*/ 32469371c9d4SSatish Balay PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) { 3247552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3248552f7358SJed Brown PetscInt off; 3249552f7358SJed Brown 3250552f7358SJed Brown PetscFunctionBegin; 3251552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3252552f7358SJed Brown PetscValidPointer(support, 3); 32539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3254552f7358SJed Brown *support = &mesh->supports[off]; 3255552f7358SJed Brown PetscFunctionReturn(0); 3256552f7358SJed Brown } 3257552f7358SJed Brown 3258552f7358SJed Brown /*@ 325992371b87SBarry 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 3260552f7358SJed Brown 3261552f7358SJed Brown Not collective 3262552f7358SJed Brown 3263552f7358SJed Brown Input Parameters: 3264552f7358SJed Brown + mesh - The DMPlex 3265eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 326692371b87SBarry Smith - support - An array of points which are on the out-edges for point p 3267552f7358SJed Brown 3268552f7358SJed Brown Output Parameter: 3269552f7358SJed Brown 3270552f7358SJed Brown Note: 3271552f7358SJed Brown This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3272552f7358SJed Brown 3273552f7358SJed Brown Level: beginner 3274552f7358SJed Brown 3275db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3276552f7358SJed Brown @*/ 32779371c9d4SSatish Balay PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) { 3278552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3279552f7358SJed Brown PetscInt pStart, pEnd; 3280552f7358SJed Brown PetscInt dof, off, c; 3281552f7358SJed Brown 3282552f7358SJed Brown PetscFunctionBegin; 3283552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 32859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 3286dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(support, 3); 32879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 328863a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3289552f7358SJed Brown for (c = 0; c < dof; ++c) { 329063a3b9bcSJacob Faibussowitsch PetscCheck(!(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); 3291552f7358SJed Brown mesh->supports[off + c] = support[c]; 3292552f7358SJed Brown } 3293552f7358SJed Brown PetscFunctionReturn(0); 3294552f7358SJed Brown } 3295552f7358SJed Brown 32967cd05799SMatthew G. Knepley /*@ 3297eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 32987cd05799SMatthew G. Knepley 32997cd05799SMatthew G. Knepley Not collective 33007cd05799SMatthew G. Knepley 33017cd05799SMatthew G. Knepley Input Parameters: 33027cd05799SMatthew G. Knepley + mesh - The DMPlex 3303eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 33047cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 33057cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 33067cd05799SMatthew G. Knepley 33077cd05799SMatthew G. Knepley Level: beginner 33087cd05799SMatthew G. Knepley 3309db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 33107cd05799SMatthew G. Knepley @*/ 33119371c9d4SSatish Balay PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) { 3312552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3313552f7358SJed Brown PetscInt pStart, pEnd; 3314552f7358SJed Brown PetscInt dof, off; 3315552f7358SJed Brown 3316552f7358SJed Brown PetscFunctionBegin; 3317552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 33209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 332163a3b9bcSJacob 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); 332263a3b9bcSJacob 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); 332363a3b9bcSJacob 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); 3324552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 3325552f7358SJed Brown PetscFunctionReturn(0); 3326552f7358SJed Brown } 3327552f7358SJed Brown 3328b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 33299371c9d4SSatish Balay PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) { 3330b5a892a1SMatthew G. Knepley switch (ct) { 3331b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3332b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3333b5a892a1SMatthew G. Knepley break; 3334b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3335b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3336b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3337b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3338b5a892a1SMatthew G. Knepley break; 3339b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3340b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3341b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3342b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3343b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3344b5a892a1SMatthew G. Knepley break; 3345b5a892a1SMatthew G. Knepley default: return o; 3346b5a892a1SMatthew G. Knepley } 3347b5a892a1SMatthew G. Knepley return o; 3348b5a892a1SMatthew G. Knepley } 3349b5a892a1SMatthew G. Knepley 3350b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 33519371c9d4SSatish Balay PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) { 3352b5a892a1SMatthew G. Knepley switch (ct) { 3353b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3354b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3355b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3356b5a892a1SMatthew G. Knepley break; 3357b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3358b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3359b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3360b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3361b5a892a1SMatthew G. Knepley break; 3362b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3363b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3364b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3365b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3366b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3367b5a892a1SMatthew G. Knepley break; 3368b5a892a1SMatthew G. Knepley default: return o; 3369b5a892a1SMatthew G. Knepley } 3370b5a892a1SMatthew G. Knepley return o; 3371b5a892a1SMatthew G. Knepley } 3372b5a892a1SMatthew G. Knepley 3373b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 33749371c9d4SSatish Balay PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) { 3375b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3376b5a892a1SMatthew G. Knepley 3377b5a892a1SMatthew G. Knepley PetscFunctionBegin; 33789566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3379b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3380b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3381b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3382b5a892a1SMatthew G. Knepley 33839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 33849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 33859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3386b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3387b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3388b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3389b5a892a1SMatthew G. Knepley 33909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3391b5a892a1SMatthew G. Knepley switch (ct) { 3392b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 33939566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 33949566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3395b5a892a1SMatthew G. Knepley break; 3396b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 33979566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 33989566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 33999566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3400b5a892a1SMatthew G. Knepley break; 3401b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 34029566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 34039566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34049566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 34059566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3406b5a892a1SMatthew G. Knepley break; 3407b5a892a1SMatthew G. Knepley default: break; 3408b5a892a1SMatthew G. Knepley } 3409b5a892a1SMatthew G. Knepley } 3410b5a892a1SMatthew G. Knepley } 3411b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3412b5a892a1SMatthew G. Knepley } 3413b5a892a1SMatthew G. Knepley 34149371c9d4SSatish Balay static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) { 3415b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3416b5a892a1SMatthew G. Knepley PetscInt *closure; 3417b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3418b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3419b5a892a1SMatthew G. Knepley 3420b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3421b5a892a1SMatthew G. Knepley if (ornt) { 34229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3423b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3424b5a892a1SMatthew G. Knepley } 3425b5a892a1SMatthew G. Knepley if (*points) { 3426b5a892a1SMatthew G. Knepley closure = *points; 3427b5a892a1SMatthew G. Knepley } else { 3428b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 34299566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 34309566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3431b5a892a1SMatthew G. Knepley } 3432b5a892a1SMatthew G. Knepley if (useCone) { 34339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &tmpSize)); 34349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &tmp)); 34359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO)); 3436b5a892a1SMatthew G. Knepley } else { 34379566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize)); 34389566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &tmp)); 3439b5a892a1SMatthew G. Knepley } 3440b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3441b5a892a1SMatthew G. Knepley closure[off++] = p; 3442b5a892a1SMatthew G. Knepley closure[off++] = 0; 3443b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3444b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3445b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3446b5a892a1SMatthew G. Knepley } 3447b5a892a1SMatthew G. Knepley } else { 34485f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3449b5a892a1SMatthew G. Knepley 3450b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3451b5a892a1SMatthew G. Knepley closure[off++] = p; 3452b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3453b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3454b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3455b5a892a1SMatthew G. Knepley 34569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3457b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3458b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3459b5a892a1SMatthew G. Knepley } 3460b5a892a1SMatthew G. Knepley } 3461b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3462b5a892a1SMatthew G. Knepley if (points) *points = closure; 3463b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3464b5a892a1SMatthew G. Knepley } 3465b5a892a1SMatthew G. Knepley 3466b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 34679371c9d4SSatish Balay static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) { 3468b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3469b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3470b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3471b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3472b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3473b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3474b5a892a1SMatthew G. Knepley 3475b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 34769566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 34779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 34789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 34799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &ornt)); 34809566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3481b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3482b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3483b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 34849371c9d4SSatish Balay if (*points) { 34859371c9d4SSatish Balay pts = *points; 34869371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3487b5a892a1SMatthew G. Knepley c = 0; 3488b5a892a1SMatthew G. Knepley pts[c++] = point; 3489b5a892a1SMatthew G. Knepley pts[c++] = o; 34909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 34919566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 34929371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 34939371c9d4SSatish Balay pts[c++] = closure[cl]; 34949371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 34959371c9d4SSatish Balay } 34969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 34979371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 34989371c9d4SSatish Balay pts[c++] = closure[cl]; 34999371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 35009371c9d4SSatish Balay } 35019566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3502b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 35039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3504b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3505b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3506b5a892a1SMatthew G. Knepley } 3507b5a892a1SMatthew G. Knepley if (dim >= 3) { 3508b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3509b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3510b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3511b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3512b5a892a1SMatthew G. Knepley 35139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3514b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 35159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize)); 35169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, fpoint, &fcone)); 35179566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt)); 3518b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3519b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3520b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3521b5a892a1SMatthew G. Knepley 35229371c9d4SSatish Balay for (i = 0; i < c; i += 2) 35239371c9d4SSatish Balay if (pts[i] == cp) break; 3524b5a892a1SMatthew G. Knepley if (i == c) { 35259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3526b5a892a1SMatthew G. Knepley pts[c++] = cp; 3527b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3528b5a892a1SMatthew G. Knepley } 3529b5a892a1SMatthew G. Knepley } 3530b5a892a1SMatthew G. Knepley } 3531b5a892a1SMatthew G. Knepley } 3532b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3533b5a892a1SMatthew G. Knepley *points = pts; 3534b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3535b5a892a1SMatthew G. Knepley } 3536b5a892a1SMatthew G. Knepley 35379371c9d4SSatish Balay PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) { 3538b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3539b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3540b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3541b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3542b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3543b5a892a1SMatthew G. Knepley 3544b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 35459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3546b5a892a1SMatthew G. Knepley if (depth == 1) { 35479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 3548b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3549b5a892a1SMatthew G. Knepley } 35509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3551b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3552b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 35539566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 3554b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3555b5a892a1SMatthew G. Knepley } 35569566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3557b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3558b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3559b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 35609566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 35619371c9d4SSatish Balay if (*points) { 35629371c9d4SSatish Balay closure = *points; 35639371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3564b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3565b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3566b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3567b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3568b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3569b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3570b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3571b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3572b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3573b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 3574b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3575b5a892a1SMatthew G. Knepley const PetscInt *tmp, *tmpO; 3576b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3577b5a892a1SMatthew G. Knepley 3578b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3579b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2; 358063a3b9bcSJacob 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); 3581b5a892a1SMatthew G. Knepley } 3582b5a892a1SMatthew G. Knepley if (useCone) { 35839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &tmpSize)); 35849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &tmp)); 35859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO)); 3586b5a892a1SMatthew G. Knepley } else { 35879566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize)); 35889566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &tmp)); 3589b5a892a1SMatthew G. Knepley tmpO = NULL; 3590b5a892a1SMatthew G. Knepley } 3591b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3592b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 3593b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 3594b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 35959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3596b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3597b5a892a1SMatthew G. Knepley PetscInt c; 3598b5a892a1SMatthew G. Knepley 3599b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3600b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3601b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3602b5a892a1SMatthew G. Knepley } 3603b5a892a1SMatthew G. Knepley if (c == closureSize) { 3604b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3605b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3606b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3607b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3608b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3609b5a892a1SMatthew G. Knepley } 3610b5a892a1SMatthew G. Knepley } 3611b5a892a1SMatthew G. Knepley } 36129566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 3613b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 3614b5a892a1SMatthew G. Knepley if (points) *points = closure; 3615b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3616b5a892a1SMatthew G. Knepley } 3617b5a892a1SMatthew G. Knepley 3618552f7358SJed Brown /*@C 3619eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3620552f7358SJed Brown 3621552f7358SJed Brown Not collective 3622552f7358SJed Brown 3623552f7358SJed Brown Input Parameters: 3624b5a892a1SMatthew G. Knepley + dm - The DMPlex 3625b5a892a1SMatthew G. Knepley . p - The mesh point 36266b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star 3627552f7358SJed Brown 36286b867d5aSJose E. Roman Input/Output Parameter: 36296b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 36306b867d5aSJose E. Roman if NULL on input, internal storage will be returned, otherwise the provided array is used 36316b867d5aSJose E. Roman 36326b867d5aSJose E. Roman Output Parameter: 36336b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3634552f7358SJed Brown 3635552f7358SJed Brown Note: 36360298fd71SBarry Smith If using internal storage (points is NULL on input), each call overwrites the last output. 3637552f7358SJed Brown 36389f22da38SBarry Smith Fortran Note: 36393813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36403813dfbdSMatthew G Knepley 3641552f7358SJed Brown Level: beginner 3642552f7358SJed Brown 3643db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3644552f7358SJed Brown @*/ 36459371c9d4SSatish Balay PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) { 3646b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3647552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3648b5a892a1SMatthew G. Knepley if (numPoints) PetscValidIntPointer(numPoints, 4); 3649b5a892a1SMatthew G. Knepley if (points) PetscValidPointer(points, 5); 36509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 36519bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 36529bf0dad6SMatthew G. Knepley } 36539bf0dad6SMatthew G. Knepley 3654552f7358SJed Brown /*@C 3655eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3656552f7358SJed Brown 3657552f7358SJed Brown Not collective 3658552f7358SJed Brown 3659552f7358SJed Brown Input Parameters: 3660b5a892a1SMatthew G. Knepley + dm - The DMPlex 3661b5a892a1SMatthew G. Knepley . p - The mesh point 3662b5a892a1SMatthew G. Knepley . useCone - PETSC_TRUE for the closure, otherwise return the star 3663b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3664b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3665552f7358SJed Brown 3666552f7358SJed Brown Note: 36670298fd71SBarry Smith If not using internal storage (points is not NULL on input), this call is unnecessary 3668552f7358SJed Brown 3669552f7358SJed Brown Level: beginner 3670552f7358SJed Brown 3671db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3672552f7358SJed Brown @*/ 36739371c9d4SSatish Balay PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) { 3674b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3675552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36764ff43b2cSJed Brown if (numPoints) *numPoints = 0; 36779566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 3678552f7358SJed Brown PetscFunctionReturn(0); 3679552f7358SJed Brown } 3680552f7358SJed Brown 3681552f7358SJed Brown /*@ 3682eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3683552f7358SJed Brown 3684552f7358SJed Brown Not collective 3685552f7358SJed Brown 3686552f7358SJed Brown Input Parameter: 3687552f7358SJed Brown . mesh - The DMPlex 3688552f7358SJed Brown 3689552f7358SJed Brown Output Parameters: 3690552f7358SJed Brown + maxConeSize - The maximum number of in-edges 3691552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 3692552f7358SJed Brown 3693552f7358SJed Brown Level: beginner 3694552f7358SJed Brown 3695db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3696552f7358SJed Brown @*/ 36979371c9d4SSatish Balay PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) { 3698552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3699552f7358SJed Brown 3700552f7358SJed Brown PetscFunctionBegin; 3701552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37021baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 37031baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 3704552f7358SJed Brown PetscFunctionReturn(0); 3705552f7358SJed Brown } 3706552f7358SJed Brown 37079371c9d4SSatish Balay PetscErrorCode DMSetUp_Plex(DM dm) { 3708552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 37096302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 3710552f7358SJed Brown 3711552f7358SJed Brown PetscFunctionBegin; 3712552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 37149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 37159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 37169566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 37179566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)dm, size * 2 * sizeof(PetscInt))); 37186302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 37196302a7fbSVaclav Hapla if (maxSupportSize) { 37209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 37219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 37229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 37239566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)dm, size * sizeof(PetscInt))); 3724552f7358SJed Brown } 3725552f7358SJed Brown PetscFunctionReturn(0); 3726552f7358SJed Brown } 3727552f7358SJed Brown 37289371c9d4SSatish Balay PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) { 3729552f7358SJed Brown PetscFunctionBegin; 37309566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 37319566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 3732ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 3733736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 373495602cf2SAlexis Marboeuf PetscSF sfNatural; 3735f94b4a02SBlaise Bourdin 37363dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 37379566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 373895602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 3739c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 3740f94b4a02SBlaise Bourdin } 3741552f7358SJed Brown PetscFunctionReturn(0); 3742552f7358SJed Brown } 3743552f7358SJed Brown 37449371c9d4SSatish Balay PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) { 37453dcd263cSBlaise Bourdin PetscInt i = 0; 37462adcc780SMatthew G. Knepley 37472adcc780SMatthew G. Knepley PetscFunctionBegin; 37489566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 37499566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 3750c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 37513dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 37523dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 375395602cf2SAlexis Marboeuf PetscSF sfNatural; 37543dcd263cSBlaise Bourdin 37553dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 37569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 3757c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 375895602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 3759c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 37603dcd263cSBlaise Bourdin break; 37613dcd263cSBlaise Bourdin } 37623dcd263cSBlaise Bourdin } 37632adcc780SMatthew G. Knepley PetscFunctionReturn(0); 37642adcc780SMatthew G. Knepley } 37652adcc780SMatthew G. Knepley 3766552f7358SJed Brown /*@ 3767eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3768552f7358SJed Brown 3769552f7358SJed Brown Not collective 3770552f7358SJed Brown 3771552f7358SJed Brown Input Parameter: 3772552f7358SJed Brown . mesh - The DMPlex 3773552f7358SJed Brown 3774552f7358SJed Brown Output Parameter: 3775552f7358SJed Brown 3776552f7358SJed Brown Note: 3777552f7358SJed Brown This should be called after all calls to DMPlexSetCone() 3778552f7358SJed Brown 3779552f7358SJed Brown Level: beginner 3780552f7358SJed Brown 3781db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 3782552f7358SJed Brown @*/ 37839371c9d4SSatish Balay PetscErrorCode DMPlexSymmetrize(DM dm) { 3784552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3785552f7358SJed Brown PetscInt *offsets; 3786552f7358SJed Brown PetscInt supportSize; 3787552f7358SJed Brown PetscInt pStart, pEnd, p; 3788552f7358SJed Brown 3789552f7358SJed Brown PetscFunctionBegin; 3790552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 379128b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 37929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 3793552f7358SJed Brown /* Calculate support sizes */ 37949566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3795552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3796552f7358SJed Brown PetscInt dof, off, c; 3797552f7358SJed Brown 37989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 37999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 380048a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 3801552f7358SJed Brown } 38029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 3803552f7358SJed Brown /* Calculate supports */ 38049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 38059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 38069566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 3807552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3808552f7358SJed Brown PetscInt dof, off, c; 3809552f7358SJed Brown 38109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3812552f7358SJed Brown for (c = off; c < off + dof; ++c) { 3813552f7358SJed Brown const PetscInt q = mesh->cones[c]; 3814552f7358SJed Brown PetscInt offS; 3815552f7358SJed Brown 38169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 38170d644c17SKarl Rupp 3818552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 3819552f7358SJed Brown ++offsets[q]; 3820552f7358SJed Brown } 3821552f7358SJed Brown } 38229566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 38239566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 3824552f7358SJed Brown PetscFunctionReturn(0); 3825552f7358SJed Brown } 3826552f7358SJed Brown 38279371c9d4SSatish Balay static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) { 3828277ea44aSLisandro Dalcin IS stratumIS; 3829277ea44aSLisandro Dalcin 3830277ea44aSLisandro Dalcin PetscFunctionBegin; 3831277ea44aSLisandro Dalcin if (pStart >= pEnd) PetscFunctionReturn(0); 383276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3833277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 3834277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 38359566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 3836277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 38379566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 38389371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 38399371c9d4SSatish Balay overlap = PETSC_TRUE; 38409371c9d4SSatish Balay break; 38419371c9d4SSatish Balay } 3842277ea44aSLisandro Dalcin } 384363a3b9bcSJacob 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); 3844277ea44aSLisandro Dalcin } 38459566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 38469566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 38479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 3848277ea44aSLisandro Dalcin PetscFunctionReturn(0); 3849277ea44aSLisandro Dalcin } 3850277ea44aSLisandro Dalcin 3851552f7358SJed Brown /*@ 3852a8d69d7bSBarry Smith DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 38536dd80730SBarry Smith can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3854552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3855552f7358SJed Brown the DAG. 3856552f7358SJed Brown 3857bf4602e4SToby Isaac Collective on dm 3858552f7358SJed Brown 3859552f7358SJed Brown Input Parameter: 3860552f7358SJed Brown . mesh - The DMPlex 3861552f7358SJed Brown 3862552f7358SJed Brown Output Parameter: 3863552f7358SJed Brown 3864552f7358SJed Brown Notes: 3865b1bb481bSMatthew Knepley Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3866b1bb481bSMatthew 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 3867b1bb481bSMatthew Knepley until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3868c58f1c22SToby Isaac manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3869150b719bSJed Brown via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3870552f7358SJed Brown 3871b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3872b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3873b1bb481bSMatthew 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 3874b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 3875b1bb481bSMatthew Knepley $ cone(c0) = {e0, v2} 3876b1bb481bSMatthew Knepley $ cone(e0) = {v0, v1} 3877b1bb481bSMatthew Knepley If DMPlexStratify() is run on this mesh, it will give depths 3878b1bb481bSMatthew Knepley $ depth 0 = {v0, v1, v2} 3879b1bb481bSMatthew Knepley $ depth 1 = {e0, c0} 3880b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3881b1bb481bSMatthew Knepley 3882150b719bSJed Brown DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3883552f7358SJed Brown 3884552f7358SJed Brown Level: beginner 3885552f7358SJed Brown 3886db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 3887552f7358SJed Brown @*/ 38889371c9d4SSatish Balay PetscErrorCode DMPlexStratify(DM dm) { 3889df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 3890aa50250dSMatthew G. Knepley DMLabel label; 3891552f7358SJed Brown PetscInt pStart, pEnd, p; 3892552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 3893552f7358SJed Brown 3894552f7358SJed Brown PetscFunctionBegin; 3895552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38969566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 3897277ea44aSLisandro Dalcin 3898277ea44aSLisandro Dalcin /* Create depth label */ 38999566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 39009566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 39019566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 3902277ea44aSLisandro Dalcin 3903277ea44aSLisandro Dalcin { 3904552f7358SJed Brown /* Initialize roots and count leaves */ 3905277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3906277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3907552f7358SJed Brown PetscInt coneSize, supportSize; 3908552f7358SJed Brown 3909277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39119566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3912552f7358SJed Brown if (!coneSize && supportSize) { 3913277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3914277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3915552f7358SJed Brown ++numRoots; 3916552f7358SJed Brown } else if (!supportSize && coneSize) { 3917552f7358SJed Brown ++numLeaves; 3918552f7358SJed Brown } else if (!supportSize && !coneSize) { 3919552f7358SJed Brown /* Isolated points */ 3920277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3921277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3922552f7358SJed Brown } 3923552f7358SJed Brown } 39249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 3925277ea44aSLisandro Dalcin } 3926277ea44aSLisandro Dalcin 3927552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 3928277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3929277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3930552f7358SJed Brown PetscInt coneSize, supportSize; 3931552f7358SJed Brown 3932277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3935552f7358SJed Brown if (!supportSize && coneSize) { 3936277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3937277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3938552f7358SJed Brown } 3939552f7358SJed Brown } 39409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 3941552f7358SJed Brown } else { 3942277ea44aSLisandro Dalcin PetscInt level = 0; 3943277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 3944552f7358SJed Brown 39459566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3946277ea44aSLisandro Dalcin while (qEnd > qStart) { 3947277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3948277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 394974ef644bSMatthew G. Knepley 3950277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 395174ef644bSMatthew G. Knepley const PetscInt *support; 395274ef644bSMatthew G. Knepley PetscInt supportSize, s; 395374ef644bSMatthew G. Knepley 39549566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 39559566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &support)); 395674ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 3957277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 3958277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 3959552f7358SJed Brown } 3960552f7358SJed Brown } 39619566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &level)); 39629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 39639566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 396474ef644bSMatthew G. Knepley } 396574ef644bSMatthew G. Knepley } 3966bf4602e4SToby Isaac { /* just in case there is an empty process */ 3967bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 3968bf4602e4SToby Isaac 39699566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 39709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 397148a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 3972bf4602e4SToby Isaac } 39739566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 39749566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 3975552f7358SJed Brown PetscFunctionReturn(0); 3976552f7358SJed Brown } 3977552f7358SJed Brown 39789371c9d4SSatish Balay PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) { 3979412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3980412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 3981ba2698f1SMatthew G. Knepley 3982412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 39839566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 39849566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 39859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 3986ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 3987ba2698f1SMatthew G. Knepley if (depth <= 1) { 3988ba2698f1SMatthew G. Knepley switch (pdepth) { 3989ba2698f1SMatthew G. Knepley case 0: ct = DM_POLYTOPE_POINT; break; 3990ba2698f1SMatthew G. Knepley case 1: 3991ba2698f1SMatthew G. Knepley switch (coneSize) { 3992ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT; break; 3993ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE; break; 3994ba2698f1SMatthew G. Knepley case 4: 3995ba2698f1SMatthew G. Knepley switch (dim) { 3996ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_QUADRILATERAL; break; 3997ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TETRAHEDRON; break; 3998ba2698f1SMatthew G. Knepley default: break; 3999ba2698f1SMatthew G. Knepley } 4000ba2698f1SMatthew G. Knepley break; 4001da9060c4SMatthew G. Knepley case 5: ct = DM_POLYTOPE_PYRAMID; break; 4002ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR; break; 4003ba2698f1SMatthew G. Knepley case 8: ct = DM_POLYTOPE_HEXAHEDRON; break; 4004ba2698f1SMatthew G. Knepley default: break; 4005ba2698f1SMatthew G. Knepley } 4006ba2698f1SMatthew G. Knepley } 4007ba2698f1SMatthew G. Knepley } else { 4008ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4009ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4010ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4011ba2698f1SMatthew G. Knepley switch (dim) { 4012ba2698f1SMatthew G. Knepley case 1: 4013ba2698f1SMatthew G. Knepley switch (coneSize) { 4014ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT; break; 4015ba2698f1SMatthew G. Knepley default: break; 4016ba2698f1SMatthew G. Knepley } 4017ba2698f1SMatthew G. Knepley break; 4018ba2698f1SMatthew G. Knepley case 2: 4019ba2698f1SMatthew G. Knepley switch (coneSize) { 4020ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE; break; 4021ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL; break; 4022ba2698f1SMatthew G. Knepley default: break; 4023ba2698f1SMatthew G. Knepley } 4024ba2698f1SMatthew G. Knepley break; 4025ba2698f1SMatthew G. Knepley case 3: 4026ba2698f1SMatthew G. Knepley switch (coneSize) { 4027ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_TETRAHEDRON; break; 40289371c9d4SSatish Balay case 5: { 4029da9060c4SMatthew G. Knepley const PetscInt *cone; 4030da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4031da9060c4SMatthew G. Knepley 40329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 40339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4034da9060c4SMatthew G. Knepley switch (faceConeSize) { 4035da9060c4SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR; break; 4036da9060c4SMatthew G. Knepley case 4: ct = DM_POLYTOPE_PYRAMID; break; 4037da9060c4SMatthew G. Knepley } 40389371c9d4SSatish Balay } break; 4039ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_HEXAHEDRON; break; 4040ba2698f1SMatthew G. Knepley default: break; 4041ba2698f1SMatthew G. Knepley } 4042ba2698f1SMatthew G. Knepley break; 4043ba2698f1SMatthew G. Knepley default: break; 4044ba2698f1SMatthew G. Knepley } 4045ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4046ba2698f1SMatthew G. Knepley switch (coneSize) { 4047ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT; break; 4048ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE; break; 4049ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL; break; 4050ba2698f1SMatthew G. Knepley default: break; 4051ba2698f1SMatthew G. Knepley } 4052ba2698f1SMatthew G. Knepley } 4053ba2698f1SMatthew G. Knepley } 4054412e9a14SMatthew G. Knepley *pt = ct; 4055412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4056ba2698f1SMatthew G. Knepley } 4057412e9a14SMatthew G. Knepley 4058412e9a14SMatthew G. Knepley /*@ 4059412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4060412e9a14SMatthew G. Knepley 4061412e9a14SMatthew G. Knepley Collective on dm 4062412e9a14SMatthew G. Knepley 4063412e9a14SMatthew G. Knepley Input Parameter: 4064412e9a14SMatthew G. Knepley . mesh - The DMPlex 4065412e9a14SMatthew G. Knepley 4066412e9a14SMatthew G. Knepley DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4067412e9a14SMatthew G. Knepley 4068412e9a14SMatthew G. Knepley Level: developer 4069412e9a14SMatthew G. Knepley 4070412e9a14SMatthew G. Knepley Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4071412e9a14SMatthew G. Knepley internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4072412e9a14SMatthew G. Knepley automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4073412e9a14SMatthew G. Knepley 4074db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4075412e9a14SMatthew G. Knepley @*/ 40769371c9d4SSatish Balay PetscErrorCode DMPlexComputeCellTypes(DM dm) { 4077412e9a14SMatthew G. Knepley DM_Plex *mesh; 4078412e9a14SMatthew G. Knepley DMLabel ctLabel; 4079412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4080412e9a14SMatthew G. Knepley 4081412e9a14SMatthew G. Knepley PetscFunctionBegin; 4082412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4083412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 40849566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 40859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 40869566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4087412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4088327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4089412e9a14SMatthew G. Knepley PetscInt pdepth; 4090412e9a14SMatthew G. Knepley 40919566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 40929566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 409363a3b9bcSJacob Faibussowitsch PetscCheck(ct != DM_POLYTOPE_UNKNOWN, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 40949566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 4095412e9a14SMatthew G. Knepley } 40969566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 40979566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 4098ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4099ba2698f1SMatthew G. Knepley } 4100ba2698f1SMatthew G. Knepley 4101552f7358SJed Brown /*@C 4102552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4103552f7358SJed Brown 4104552f7358SJed Brown Not Collective 4105552f7358SJed Brown 4106552f7358SJed Brown Input Parameters: 4107552f7358SJed Brown + dm - The DMPlex object 4108552f7358SJed Brown . numPoints - The number of input points for the join 4109552f7358SJed Brown - points - The input points 4110552f7358SJed Brown 4111552f7358SJed Brown Output Parameters: 4112552f7358SJed Brown + numCoveredPoints - The number of points in the join 4113552f7358SJed Brown - coveredPoints - The points in the join 4114552f7358SJed Brown 4115552f7358SJed Brown Level: intermediate 4116552f7358SJed Brown 4117552f7358SJed Brown Note: Currently, this is restricted to a single level join 4118552f7358SJed Brown 41193813dfbdSMatthew G Knepley Fortran Notes: 41203813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 41213813dfbdSMatthew G Knepley include petsc.h90 in your code. 41223813dfbdSMatthew G Knepley 41233813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 41243813dfbdSMatthew G Knepley 4125db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4126552f7358SJed Brown @*/ 41279371c9d4SSatish Balay PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) { 4128552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4129552f7358SJed Brown PetscInt *join[2]; 4130552f7358SJed Brown PetscInt joinSize, i = 0; 4131552f7358SJed Brown PetscInt dof, off, p, c, m; 41326302a7fbSVaclav Hapla PetscInt maxSupportSize; 4133552f7358SJed Brown 4134552f7358SJed Brown PetscFunctionBegin; 4135552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 413648bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 413748bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 413848bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 41396302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41406302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 41416302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4142552f7358SJed Brown /* Copy in support of first point */ 41439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 41449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4145ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4146552f7358SJed Brown /* Check each successive support */ 4147552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4148552f7358SJed Brown PetscInt newJoinSize = 0; 4149552f7358SJed Brown 41509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 41519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4152552f7358SJed Brown for (c = 0; c < dof; ++c) { 4153552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4154552f7358SJed Brown 4155552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4156552f7358SJed Brown if (point == join[i][m]) { 4157552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4158552f7358SJed Brown break; 4159552f7358SJed Brown } 4160552f7358SJed Brown } 4161552f7358SJed Brown } 4162552f7358SJed Brown joinSize = newJoinSize; 4163552f7358SJed Brown i = 1 - i; 4164552f7358SJed Brown } 4165552f7358SJed Brown *numCoveredPoints = joinSize; 4166552f7358SJed Brown *coveredPoints = join[i]; 41676302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 4168552f7358SJed Brown PetscFunctionReturn(0); 4169552f7358SJed Brown } 4170552f7358SJed Brown 4171552f7358SJed Brown /*@C 4172552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4173552f7358SJed Brown 4174552f7358SJed Brown Not Collective 4175552f7358SJed Brown 4176552f7358SJed Brown Input Parameters: 4177552f7358SJed Brown + dm - The DMPlex object 4178552f7358SJed Brown . numPoints - The number of input points for the join 4179552f7358SJed Brown - points - The input points 4180552f7358SJed Brown 4181552f7358SJed Brown Output Parameters: 4182552f7358SJed Brown + numCoveredPoints - The number of points in the join 4183552f7358SJed Brown - coveredPoints - The points in the join 4184552f7358SJed Brown 41853813dfbdSMatthew G Knepley Fortran Notes: 41863813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 41873813dfbdSMatthew G Knepley include petsc.h90 in your code. 41883813dfbdSMatthew G Knepley 41893813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 41903813dfbdSMatthew G Knepley 4191552f7358SJed Brown Level: intermediate 4192552f7358SJed Brown 4193db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4194552f7358SJed Brown @*/ 41959371c9d4SSatish Balay PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) { 4196552f7358SJed Brown PetscFunctionBegin; 4197552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4198d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points, 3); 4199d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4); 4200d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 42019566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4202d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4203552f7358SJed Brown PetscFunctionReturn(0); 4204552f7358SJed Brown } 4205552f7358SJed Brown 4206552f7358SJed Brown /*@C 4207552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4208552f7358SJed Brown 4209552f7358SJed Brown Not Collective 4210552f7358SJed Brown 4211552f7358SJed Brown Input Parameters: 4212552f7358SJed Brown + dm - The DMPlex object 4213552f7358SJed Brown . numPoints - The number of input points for the join 4214552f7358SJed Brown - points - The input points 4215552f7358SJed Brown 4216552f7358SJed Brown Output Parameters: 4217552f7358SJed Brown + numCoveredPoints - The number of points in the join 4218552f7358SJed Brown - coveredPoints - The points in the join 4219552f7358SJed Brown 42203813dfbdSMatthew G Knepley Fortran Notes: 42213813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42223813dfbdSMatthew G Knepley include petsc.h90 in your code. 42233813dfbdSMatthew G Knepley 42243813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42253813dfbdSMatthew G Knepley 4226552f7358SJed Brown Level: intermediate 4227552f7358SJed Brown 4228db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4229552f7358SJed Brown @*/ 42309371c9d4SSatish Balay PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) { 4231552f7358SJed Brown PetscInt *offsets, **closures; 4232552f7358SJed Brown PetscInt *join[2]; 4233552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 423424c766afSToby Isaac PetscInt p, d, c, m, ms; 4235552f7358SJed Brown 4236552f7358SJed Brown PetscFunctionBegin; 4237552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 423848bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 423948bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 424048bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 4241552f7358SJed Brown 42429566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 42439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 42449566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 42456302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 424624c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 42479566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 42489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4249552f7358SJed Brown 4250552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4251552f7358SJed Brown PetscInt closureSize; 4252552f7358SJed Brown 42539566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 42540d644c17SKarl Rupp 4255552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4256552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4257552f7358SJed Brown PetscInt pStart, pEnd, i; 4258552f7358SJed Brown 42599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4260552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4261552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4262552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4263552f7358SJed Brown break; 4264552f7358SJed Brown } 4265552f7358SJed Brown } 4266552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4267552f7358SJed Brown } 426863a3b9bcSJacob 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); 4269552f7358SJed Brown } 4270552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4271552f7358SJed Brown PetscInt dof; 4272552f7358SJed Brown 4273552f7358SJed Brown /* Copy in support of first point */ 4274552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4275ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4276552f7358SJed Brown /* Check each successive cone */ 4277552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4278552f7358SJed Brown PetscInt newJoinSize = 0; 4279552f7358SJed Brown 4280552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4281552f7358SJed Brown for (c = 0; c < dof; ++c) { 4282552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4283552f7358SJed Brown 4284552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4285552f7358SJed Brown if (point == join[i][m]) { 4286552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4287552f7358SJed Brown break; 4288552f7358SJed Brown } 4289552f7358SJed Brown } 4290552f7358SJed Brown } 4291552f7358SJed Brown joinSize = newJoinSize; 4292552f7358SJed Brown i = 1 - i; 4293552f7358SJed Brown } 4294552f7358SJed Brown if (joinSize) break; 4295552f7358SJed Brown } 4296552f7358SJed Brown *numCoveredPoints = joinSize; 4297552f7358SJed Brown *coveredPoints = join[i]; 429848a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 42999566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 43009566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 43016302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 4302552f7358SJed Brown PetscFunctionReturn(0); 4303552f7358SJed Brown } 4304552f7358SJed Brown 4305552f7358SJed Brown /*@C 4306552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4307552f7358SJed Brown 4308552f7358SJed Brown Not Collective 4309552f7358SJed Brown 4310552f7358SJed Brown Input Parameters: 4311552f7358SJed Brown + dm - The DMPlex object 4312552f7358SJed Brown . numPoints - The number of input points for the meet 4313552f7358SJed Brown - points - The input points 4314552f7358SJed Brown 4315552f7358SJed Brown Output Parameters: 4316552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4317552f7358SJed Brown - coveredPoints - The points in the meet 4318552f7358SJed Brown 4319552f7358SJed Brown Level: intermediate 4320552f7358SJed Brown 4321552f7358SJed Brown Note: Currently, this is restricted to a single level meet 4322552f7358SJed Brown 43233813dfbdSMatthew G Knepley Fortran Notes: 43243813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 43253813dfbdSMatthew G Knepley include petsc.h90 in your code. 43263813dfbdSMatthew G Knepley 43273813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 43283813dfbdSMatthew G Knepley 4329db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4330552f7358SJed Brown @*/ 43319371c9d4SSatish Balay PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) { 4332552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4333552f7358SJed Brown PetscInt *meet[2]; 4334552f7358SJed Brown PetscInt meetSize, i = 0; 4335552f7358SJed Brown PetscInt dof, off, p, c, m; 43366302a7fbSVaclav Hapla PetscInt maxConeSize; 4337552f7358SJed Brown 4338552f7358SJed Brown PetscFunctionBegin; 4339552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4340dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4341dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveringPoints, 4); 4342064a246eSJacob Faibussowitsch PetscValidPointer(coveringPoints, 5); 43436302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 43446302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 43456302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4346552f7358SJed Brown /* Copy in cone of first point */ 43479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 43489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4349ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4350552f7358SJed Brown /* Check each successive cone */ 4351552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4352552f7358SJed Brown PetscInt newMeetSize = 0; 4353552f7358SJed Brown 43549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 43559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4356552f7358SJed Brown for (c = 0; c < dof; ++c) { 4357552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4358552f7358SJed Brown 4359552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4360552f7358SJed Brown if (point == meet[i][m]) { 4361552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4362552f7358SJed Brown break; 4363552f7358SJed Brown } 4364552f7358SJed Brown } 4365552f7358SJed Brown } 4366552f7358SJed Brown meetSize = newMeetSize; 4367552f7358SJed Brown i = 1 - i; 4368552f7358SJed Brown } 4369552f7358SJed Brown *numCoveringPoints = meetSize; 4370552f7358SJed Brown *coveringPoints = meet[i]; 43716302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 4372552f7358SJed Brown PetscFunctionReturn(0); 4373552f7358SJed Brown } 4374552f7358SJed Brown 4375552f7358SJed Brown /*@C 4376552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4377552f7358SJed Brown 4378552f7358SJed Brown Not Collective 4379552f7358SJed Brown 4380552f7358SJed Brown Input Parameters: 4381552f7358SJed Brown + dm - The DMPlex object 4382552f7358SJed Brown . numPoints - The number of input points for the meet 4383552f7358SJed Brown - points - The input points 4384552f7358SJed Brown 4385552f7358SJed Brown Output Parameters: 4386552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4387552f7358SJed Brown - coveredPoints - The points in the meet 4388552f7358SJed Brown 4389552f7358SJed Brown Level: intermediate 4390552f7358SJed Brown 43913813dfbdSMatthew G Knepley Fortran Notes: 43923813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 43933813dfbdSMatthew G Knepley include petsc.h90 in your code. 43943813dfbdSMatthew G Knepley 43953813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 43963813dfbdSMatthew G Knepley 4397db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4398552f7358SJed Brown @*/ 43999371c9d4SSatish Balay PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) { 4400552f7358SJed Brown PetscFunctionBegin; 4401552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4402d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points, 3); 4403d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4); 4404d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 44059566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4406d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4407552f7358SJed Brown PetscFunctionReturn(0); 4408552f7358SJed Brown } 4409552f7358SJed Brown 4410552f7358SJed Brown /*@C 4411552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4412552f7358SJed Brown 4413552f7358SJed Brown Not Collective 4414552f7358SJed Brown 4415552f7358SJed Brown Input Parameters: 4416552f7358SJed Brown + dm - The DMPlex object 4417552f7358SJed Brown . numPoints - The number of input points for the meet 4418552f7358SJed Brown - points - The input points 4419552f7358SJed Brown 4420552f7358SJed Brown Output Parameters: 4421552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4422552f7358SJed Brown - coveredPoints - The points in the meet 4423552f7358SJed Brown 4424552f7358SJed Brown Level: intermediate 4425552f7358SJed Brown 44263813dfbdSMatthew G Knepley Fortran Notes: 44273813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44283813dfbdSMatthew G Knepley include petsc.h90 in your code. 44293813dfbdSMatthew G Knepley 44303813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44313813dfbdSMatthew G Knepley 4432db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4433552f7358SJed Brown @*/ 44349371c9d4SSatish Balay PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) { 4435552f7358SJed Brown PetscInt *offsets, **closures; 4436552f7358SJed Brown PetscInt *meet[2]; 4437552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 443824c766afSToby Isaac PetscInt p, h, c, m, mc; 4439552f7358SJed Brown 4440552f7358SJed Brown PetscFunctionBegin; 4441552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4442dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4443dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveredPoints, 4); 4444064a246eSJacob Faibussowitsch PetscValidPointer(coveredPoints, 5); 4445552f7358SJed Brown 44469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 44479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 44489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 44496302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 445024c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 44519566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 44529566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4453552f7358SJed Brown 4454552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4455552f7358SJed Brown PetscInt closureSize; 4456552f7358SJed Brown 44579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 44580d644c17SKarl Rupp 4459552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4460552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4461552f7358SJed Brown PetscInt pStart, pEnd, i; 4462552f7358SJed Brown 44639566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4464552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4465552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4466552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4467552f7358SJed Brown break; 4468552f7358SJed Brown } 4469552f7358SJed Brown } 4470552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4471552f7358SJed Brown } 447263a3b9bcSJacob 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); 4473552f7358SJed Brown } 4474552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4475552f7358SJed Brown PetscInt dof; 4476552f7358SJed Brown 4477552f7358SJed Brown /* Copy in cone of first point */ 4478552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 4479ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 4480552f7358SJed Brown /* Check each successive cone */ 4481552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4482552f7358SJed Brown PetscInt newMeetSize = 0; 4483552f7358SJed Brown 4484552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 4485552f7358SJed Brown for (c = 0; c < dof; ++c) { 4486552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 4487552f7358SJed Brown 4488552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4489552f7358SJed Brown if (point == meet[i][m]) { 4490552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4491552f7358SJed Brown break; 4492552f7358SJed Brown } 4493552f7358SJed Brown } 4494552f7358SJed Brown } 4495552f7358SJed Brown meetSize = newMeetSize; 4496552f7358SJed Brown i = 1 - i; 4497552f7358SJed Brown } 4498552f7358SJed Brown if (meetSize) break; 4499552f7358SJed Brown } 4500552f7358SJed Brown *numCoveredPoints = meetSize; 4501552f7358SJed Brown *coveredPoints = meet[i]; 450248a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 45039566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 45049566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 45056302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 4506552f7358SJed Brown PetscFunctionReturn(0); 4507552f7358SJed Brown } 4508552f7358SJed Brown 45094e3744c5SMatthew G. Knepley /*@C 45104e3744c5SMatthew G. Knepley DMPlexEqual - Determine if two DMs have the same topology 45114e3744c5SMatthew G. Knepley 45124e3744c5SMatthew G. Knepley Not Collective 45134e3744c5SMatthew G. Knepley 45144e3744c5SMatthew G. Knepley Input Parameters: 45154e3744c5SMatthew G. Knepley + dmA - A DMPlex object 45164e3744c5SMatthew G. Knepley - dmB - A DMPlex object 45174e3744c5SMatthew G. Knepley 45184e3744c5SMatthew G. Knepley Output Parameters: 45194e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical 45204e3744c5SMatthew G. Knepley 45214e3744c5SMatthew G. Knepley Level: intermediate 45224e3744c5SMatthew G. Knepley 45234e3744c5SMatthew G. Knepley Notes: 45244e3744c5SMatthew G. Knepley We are not solving graph isomorphism, so we do not permutation. 45254e3744c5SMatthew G. Knepley 4526db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 45274e3744c5SMatthew G. Knepley @*/ 45289371c9d4SSatish Balay PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) { 45294e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 45304e3744c5SMatthew G. Knepley 45314e3744c5SMatthew G. Knepley PetscFunctionBegin; 45324e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 45334e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4534dadcf809SJacob Faibussowitsch PetscValidBoolPointer(equal, 3); 45354e3744c5SMatthew G. Knepley 45364e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 45379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 45389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 45394e3744c5SMatthew G. Knepley if (depth != depthB) PetscFunctionReturn(0); 45409566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 45419566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 45424e3744c5SMatthew G. Knepley if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 45434e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 45444e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 45454e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 45464e3744c5SMatthew G. Knepley 45479566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 45489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 45499566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 45509566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 45519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 45529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 45534e3744c5SMatthew G. Knepley if (coneSize != coneSizeB) PetscFunctionReturn(0); 45544e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 45554e3744c5SMatthew G. Knepley if (cone[c] != coneB[c]) PetscFunctionReturn(0); 45564e3744c5SMatthew G. Knepley if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 45574e3744c5SMatthew G. Knepley } 45589566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 45599566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 45609566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 45619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 45624e3744c5SMatthew G. Knepley if (supportSize != supportSizeB) PetscFunctionReturn(0); 45634e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 45644e3744c5SMatthew G. Knepley if (support[s] != supportB[s]) PetscFunctionReturn(0); 45654e3744c5SMatthew G. Knepley } 45664e3744c5SMatthew G. Knepley } 45674e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 45684e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 45694e3744c5SMatthew G. Knepley } 45704e3744c5SMatthew G. Knepley 45717cd05799SMatthew G. Knepley /*@C 45727cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 45737cd05799SMatthew G. Knepley 45747cd05799SMatthew G. Knepley Not Collective 45757cd05799SMatthew G. Knepley 45767cd05799SMatthew G. Knepley Input Parameters: 45777cd05799SMatthew G. Knepley + dm - The DMPlex 45787cd05799SMatthew G. Knepley . cellDim - The cell dimension 45797cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 45807cd05799SMatthew G. Knepley 45817cd05799SMatthew G. Knepley Output Parameters: 45827cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 45837cd05799SMatthew G. Knepley 45847cd05799SMatthew G. Knepley Level: developer 45857cd05799SMatthew G. Knepley 45867cd05799SMatthew G. Knepley Notes: 45877cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 45887cd05799SMatthew G. Knepley 4589db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 45907cd05799SMatthew G. Knepley @*/ 45919371c9d4SSatish Balay PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) { 459282f516ccSBarry Smith MPI_Comm comm; 4593552f7358SJed Brown 4594552f7358SJed Brown PetscFunctionBegin; 45959566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4596dadcf809SJacob Faibussowitsch PetscValidIntPointer(numFaceVertices, 4); 4597552f7358SJed Brown switch (cellDim) { 45989371c9d4SSatish Balay case 0: *numFaceVertices = 0; break; 45999371c9d4SSatish Balay case 1: *numFaceVertices = 1; break; 4600552f7358SJed Brown case 2: 4601552f7358SJed Brown switch (numCorners) { 460219436ca2SJed Brown case 3: /* triangle */ 460319436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4604552f7358SJed Brown break; 460519436ca2SJed Brown case 4: /* quadrilateral */ 460619436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4607552f7358SJed Brown break; 460819436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 460919436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4610552f7358SJed Brown break; 461119436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 461219436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4613552f7358SJed Brown break; 46149371c9d4SSatish Balay default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4615552f7358SJed Brown } 4616552f7358SJed Brown break; 4617552f7358SJed Brown case 3: 4618552f7358SJed Brown switch (numCorners) { 461919436ca2SJed Brown case 4: /* tetradehdron */ 462019436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 4621552f7358SJed Brown break; 462219436ca2SJed Brown case 6: /* tet cohesive cells */ 462319436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4624552f7358SJed Brown break; 462519436ca2SJed Brown case 8: /* hexahedron */ 462619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4627552f7358SJed Brown break; 462819436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 462919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4630552f7358SJed Brown break; 463119436ca2SJed Brown case 10: /* quadratic tetrahedron */ 463219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4633552f7358SJed Brown break; 463419436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 463519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4636552f7358SJed Brown break; 463719436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 463819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4639552f7358SJed Brown break; 464019436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 464119436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 4642552f7358SJed Brown break; 46439371c9d4SSatish Balay default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4644552f7358SJed Brown } 4645552f7358SJed Brown break; 46469371c9d4SSatish Balay default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 4647552f7358SJed Brown } 4648552f7358SJed Brown PetscFunctionReturn(0); 4649552f7358SJed Brown } 4650552f7358SJed Brown 4651552f7358SJed Brown /*@ 4652aa50250dSMatthew G. Knepley DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4653552f7358SJed Brown 4654552f7358SJed Brown Not Collective 4655552f7358SJed Brown 4656aa50250dSMatthew G. Knepley Input Parameter: 4657552f7358SJed Brown . dm - The DMPlex object 4658552f7358SJed Brown 4659aa50250dSMatthew G. Knepley Output Parameter: 4660aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth 4661552f7358SJed Brown 4662552f7358SJed Brown Level: developer 4663552f7358SJed Brown 4664db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 4665aa50250dSMatthew G. Knepley @*/ 46669371c9d4SSatish Balay PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) { 4667aa50250dSMatthew G. Knepley PetscFunctionBegin; 4668aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4669aa50250dSMatthew G. Knepley PetscValidPointer(depthLabel, 2); 4670c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 4671aa50250dSMatthew G. Knepley PetscFunctionReturn(0); 4672aa50250dSMatthew G. Knepley } 4673aa50250dSMatthew G. Knepley 4674aa50250dSMatthew G. Knepley /*@ 4675aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 4676aa50250dSMatthew G. Knepley 4677aa50250dSMatthew G. Knepley Not Collective 4678aa50250dSMatthew G. Knepley 4679aa50250dSMatthew G. Knepley Input Parameter: 4680aa50250dSMatthew G. Knepley . dm - The DMPlex object 4681aa50250dSMatthew G. Knepley 4682aa50250dSMatthew G. Knepley Output Parameter: 4683aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 4684aa50250dSMatthew G. Knepley 4685aa50250dSMatthew G. Knepley Level: developer 4686552f7358SJed Brown 4687b1bb481bSMatthew Knepley Notes: 4688b1bb481bSMatthew Knepley This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4689dc287ab2SVaclav Hapla The point depth is described more in detail in DMPlexGetDepthStratum(). 4690dc287ab2SVaclav Hapla An empty mesh gives -1. 4691b1bb481bSMatthew Knepley 4692db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 4693552f7358SJed Brown @*/ 46949371c9d4SSatish Balay PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) { 4695aa50250dSMatthew G. Knepley DMLabel label; 4696aa50250dSMatthew G. Knepley PetscInt d = 0; 4697552f7358SJed Brown 4698552f7358SJed Brown PetscFunctionBegin; 4699552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4700dadcf809SJacob Faibussowitsch PetscValidIntPointer(depth, 2); 47019566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 47029566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 4703552f7358SJed Brown *depth = d - 1; 4704552f7358SJed Brown PetscFunctionReturn(0); 4705552f7358SJed Brown } 4706552f7358SJed Brown 4707552f7358SJed Brown /*@ 4708552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4709552f7358SJed Brown 4710552f7358SJed Brown Not Collective 4711552f7358SJed Brown 4712552f7358SJed Brown Input Parameters: 4713552f7358SJed Brown + dm - The DMPlex object 4714570fa34dSVaclav Hapla - depth - The requested depth 4715552f7358SJed Brown 4716552f7358SJed Brown Output Parameters: 4717552f7358SJed Brown + start - The first point at this depth 4718552f7358SJed Brown - end - One beyond the last point at this depth 4719552f7358SJed Brown 4720647867b2SJed Brown Notes: 4721647867b2SJed Brown Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4722647867b2SJed Brown often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4723647867b2SJed Brown higher dimension, e.g., "edges". 4724647867b2SJed Brown 4725552f7358SJed Brown Level: developer 4726552f7358SJed Brown 4727db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 4728552f7358SJed Brown @*/ 47299371c9d4SSatish Balay PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) { 4730aa50250dSMatthew G. Knepley DMLabel label; 473163d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 4732552f7358SJed Brown 4733552f7358SJed Brown PetscFunctionBegin; 4734552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47359371c9d4SSatish Balay if (start) { 47369371c9d4SSatish Balay PetscValidIntPointer(start, 3); 47379371c9d4SSatish Balay *start = 0; 47389371c9d4SSatish Balay } 47399371c9d4SSatish Balay if (end) { 47409371c9d4SSatish Balay PetscValidIntPointer(end, 4); 47419371c9d4SSatish Balay *end = 0; 47429371c9d4SSatish Balay } 47439566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 47440d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4745570fa34dSVaclav Hapla if (depth < 0) { 474663d1a920SMatthew G. Knepley if (start) *start = pStart; 474763d1a920SMatthew G. Knepley if (end) *end = pEnd; 474863d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4749552f7358SJed Brown } 47509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 475128b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4752570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 4753552f7358SJed Brown PetscFunctionReturn(0); 4754552f7358SJed Brown } 4755552f7358SJed Brown 4756552f7358SJed Brown /*@ 4757552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4758552f7358SJed Brown 4759552f7358SJed Brown Not Collective 4760552f7358SJed Brown 4761552f7358SJed Brown Input Parameters: 4762552f7358SJed Brown + dm - The DMPlex object 4763570fa34dSVaclav Hapla - height - The requested height 4764552f7358SJed Brown 4765552f7358SJed Brown Output Parameters: 4766552f7358SJed Brown + start - The first point at this height 4767552f7358SJed Brown - end - One beyond the last point at this height 4768552f7358SJed Brown 4769647867b2SJed Brown Notes: 4770647867b2SJed Brown Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4771647867b2SJed Brown points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4772647867b2SJed Brown stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4773647867b2SJed Brown 4774552f7358SJed Brown Level: developer 4775552f7358SJed Brown 4776db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4777552f7358SJed Brown @*/ 47789371c9d4SSatish Balay PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) { 4779aa50250dSMatthew G. Knepley DMLabel label; 478063d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 4781552f7358SJed Brown 4782552f7358SJed Brown PetscFunctionBegin; 4783552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47849371c9d4SSatish Balay if (start) { 47859371c9d4SSatish Balay PetscValidIntPointer(start, 3); 47869371c9d4SSatish Balay *start = 0; 47879371c9d4SSatish Balay } 47889371c9d4SSatish Balay if (end) { 47899371c9d4SSatish Balay PetscValidIntPointer(end, 4); 47909371c9d4SSatish Balay *end = 0; 47919371c9d4SSatish Balay } 47929566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 47930d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4794570fa34dSVaclav Hapla if (height < 0) { 479563d1a920SMatthew G. Knepley if (start) *start = pStart; 479663d1a920SMatthew G. Knepley if (end) *end = pEnd; 479763d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4798552f7358SJed Brown } 47999566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 480028b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 48019566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 4802570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth - 1 - height, start, end)); 4803552f7358SJed Brown PetscFunctionReturn(0); 4804552f7358SJed Brown } 4805552f7358SJed Brown 4806ba2698f1SMatthew G. Knepley /*@ 4807ba2698f1SMatthew G. Knepley DMPlexGetPointDepth - Get the depth of a given point 4808ba2698f1SMatthew G. Knepley 4809ba2698f1SMatthew G. Knepley Not Collective 4810ba2698f1SMatthew G. Knepley 4811d8d19677SJose E. Roman Input Parameters: 4812ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4813ba2698f1SMatthew G. Knepley - point - The point 4814ba2698f1SMatthew G. Knepley 4815ba2698f1SMatthew G. Knepley Output Parameter: 4816ba2698f1SMatthew G. Knepley . depth - The depth of the point 4817ba2698f1SMatthew G. Knepley 4818ba2698f1SMatthew G. Knepley Level: intermediate 4819ba2698f1SMatthew G. Knepley 4820db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4821ba2698f1SMatthew G. Knepley @*/ 48229371c9d4SSatish Balay PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) { 4823ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4824ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 482540a2aa30SMatthew G. Knepley PetscValidIntPointer(depth, 3); 48269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 4827ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4828ba2698f1SMatthew G. Knepley } 4829ba2698f1SMatthew G. Knepley 4830ba2698f1SMatthew G. Knepley /*@ 48310c0a32dcSVaclav Hapla DMPlexGetPointHeight - Get the height of a given point 48320c0a32dcSVaclav Hapla 48330c0a32dcSVaclav Hapla Not Collective 48340c0a32dcSVaclav Hapla 4835d8d19677SJose E. Roman Input Parameters: 48360c0a32dcSVaclav Hapla + dm - The DMPlex object 48370c0a32dcSVaclav Hapla - point - The point 48380c0a32dcSVaclav Hapla 48390c0a32dcSVaclav Hapla Output Parameter: 48400c0a32dcSVaclav Hapla . height - The height of the point 48410c0a32dcSVaclav Hapla 48420c0a32dcSVaclav Hapla Level: intermediate 48430c0a32dcSVaclav Hapla 4844db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 48450c0a32dcSVaclav Hapla @*/ 48469371c9d4SSatish Balay PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) { 48470c0a32dcSVaclav Hapla PetscInt n, pDepth; 48480c0a32dcSVaclav Hapla 48490c0a32dcSVaclav Hapla PetscFunctionBegin; 48500c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48510c0a32dcSVaclav Hapla PetscValidIntPointer(height, 3); 48529566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 48539566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 48540c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 48550c0a32dcSVaclav Hapla PetscFunctionReturn(0); 48560c0a32dcSVaclav Hapla } 48570c0a32dcSVaclav Hapla 48580c0a32dcSVaclav Hapla /*@ 4859ba2698f1SMatthew G. Knepley DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4860ba2698f1SMatthew G. Knepley 4861ba2698f1SMatthew G. Knepley Not Collective 4862ba2698f1SMatthew G. Knepley 4863ba2698f1SMatthew G. Knepley Input Parameter: 4864ba2698f1SMatthew G. Knepley . dm - The DMPlex object 4865ba2698f1SMatthew G. Knepley 4866ba2698f1SMatthew G. Knepley Output Parameter: 4867ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type 4868ba2698f1SMatthew G. Knepley 4869412e9a14SMatthew G. Knepley Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4870412e9a14SMatthew G. Knepley DMCreateLabel(dm, "celltype") beforehand. 4871412e9a14SMatthew G. Knepley 4872ba2698f1SMatthew G. Knepley Level: developer 4873ba2698f1SMatthew G. Knepley 4874db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 4875ba2698f1SMatthew G. Knepley @*/ 48769371c9d4SSatish Balay PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) { 4877ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4878ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4879ba2698f1SMatthew G. Knepley PetscValidPointer(celltypeLabel, 2); 48809566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 4881ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 4882ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4883ba2698f1SMatthew G. Knepley } 4884ba2698f1SMatthew G. Knepley 4885ba2698f1SMatthew G. Knepley /*@ 4886ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 4887ba2698f1SMatthew G. Knepley 4888ba2698f1SMatthew G. Knepley Not Collective 4889ba2698f1SMatthew G. Knepley 4890d8d19677SJose E. Roman Input Parameters: 4891ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4892ba2698f1SMatthew G. Knepley - cell - The cell 4893ba2698f1SMatthew G. Knepley 4894ba2698f1SMatthew G. Knepley Output Parameter: 4895ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 4896ba2698f1SMatthew G. Knepley 4897ba2698f1SMatthew G. Knepley Level: intermediate 4898ba2698f1SMatthew G. Knepley 4899db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 4900ba2698f1SMatthew G. Knepley @*/ 49019371c9d4SSatish Balay PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) { 4902ba2698f1SMatthew G. Knepley DMLabel label; 4903ba2698f1SMatthew G. Knepley PetscInt ct; 4904ba2698f1SMatthew G. Knepley 4905ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4906ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4907ba2698f1SMatthew G. Knepley PetscValidPointer(celltype, 3); 49089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 49099566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 491063a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 4911ba2698f1SMatthew G. Knepley *celltype = (DMPolytopeType)ct; 4912ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4913ba2698f1SMatthew G. Knepley } 4914ba2698f1SMatthew G. Knepley 4915412e9a14SMatthew G. Knepley /*@ 4916412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 4917412e9a14SMatthew G. Knepley 4918412e9a14SMatthew G. Knepley Not Collective 4919412e9a14SMatthew G. Knepley 4920412e9a14SMatthew G. Knepley Input Parameters: 4921412e9a14SMatthew G. Knepley + dm - The DMPlex object 4922412e9a14SMatthew G. Knepley . cell - The cell 4923412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 4924412e9a14SMatthew G. Knepley 4925412e9a14SMatthew G. Knepley Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4926412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 4927412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 4928412e9a14SMatthew G. Knepley DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4929412e9a14SMatthew G. Knepley 4930412e9a14SMatthew G. Knepley Level: advanced 4931412e9a14SMatthew G. Knepley 4932db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 4933412e9a14SMatthew G. Knepley @*/ 49349371c9d4SSatish Balay PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) { 4935412e9a14SMatthew G. Knepley DMLabel label; 4936412e9a14SMatthew G. Knepley 4937412e9a14SMatthew G. Knepley PetscFunctionBegin; 4938412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 49409566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 4941412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4942412e9a14SMatthew G. Knepley } 4943412e9a14SMatthew G. Knepley 49449371c9d4SSatish Balay PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) { 4945efe440bfSMatthew G. Knepley PetscSection section, s; 4946efe440bfSMatthew G. Knepley Mat m; 49473e922f36SToby Isaac PetscInt maxHeight; 4948552f7358SJed Brown 4949552f7358SJed Brown PetscFunctionBegin; 49509566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 49519566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 49529566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 49539566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 49549566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 49559566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 49569566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 49579566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 49589566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 49599566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 49609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 49618f4c458bSMatthew G. Knepley 49629566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 49639566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 4964552f7358SJed Brown PetscFunctionReturn(0); 4965552f7358SJed Brown } 4966552f7358SJed Brown 49679371c9d4SSatish Balay PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) { 49686858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 49696858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 4970f19dbd58SToby Isaac 4971f19dbd58SToby Isaac PetscFunctionBegin; 4972f19dbd58SToby Isaac *field = NULL; 49739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 49749566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 49756858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 49766858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 4977f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 49786858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 49796858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 4980f19dbd58SToby Isaac } 4981f19dbd58SToby Isaac PetscFunctionReturn(0); 4982f19dbd58SToby Isaac } 4983f19dbd58SToby Isaac 49847cd05799SMatthew G. Knepley /*@C 49857cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 49867cd05799SMatthew G. Knepley 49877cd05799SMatthew G. Knepley Not Collective 49887cd05799SMatthew G. Knepley 49897cd05799SMatthew G. Knepley Input Parameters: 49907cd05799SMatthew G. Knepley . dm - The DMPlex object 49917cd05799SMatthew G. Knepley 49927cd05799SMatthew G. Knepley Output Parameter: 49937cd05799SMatthew G. Knepley . section - The PetscSection object 49947cd05799SMatthew G. Knepley 49957cd05799SMatthew G. Knepley Level: developer 49967cd05799SMatthew G. Knepley 4997db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()` 49987cd05799SMatthew G. Knepley @*/ 49999371c9d4SSatish Balay PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) { 5000552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5001552f7358SJed Brown 5002552f7358SJed Brown PetscFunctionBegin; 5003552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5004552f7358SJed Brown if (section) *section = mesh->coneSection; 5005552f7358SJed Brown PetscFunctionReturn(0); 5006552f7358SJed Brown } 5007552f7358SJed Brown 50087cd05799SMatthew G. Knepley /*@C 50097cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 50107cd05799SMatthew G. Knepley 50117cd05799SMatthew G. Knepley Not Collective 50127cd05799SMatthew G. Knepley 50137cd05799SMatthew G. Knepley Input Parameters: 50147cd05799SMatthew G. Knepley . dm - The DMPlex object 50157cd05799SMatthew G. Knepley 50167cd05799SMatthew G. Knepley Output Parameter: 50177cd05799SMatthew G. Knepley . section - The PetscSection object 50187cd05799SMatthew G. Knepley 50197cd05799SMatthew G. Knepley Level: developer 50207cd05799SMatthew G. Knepley 5021db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 50227cd05799SMatthew G. Knepley @*/ 50239371c9d4SSatish Balay PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) { 50248cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 50258cb4d582SMatthew G. Knepley 50268cb4d582SMatthew G. Knepley PetscFunctionBegin; 50278cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50288cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 50298cb4d582SMatthew G. Knepley PetscFunctionReturn(0); 50308cb4d582SMatthew G. Knepley } 50318cb4d582SMatthew G. Knepley 50327cd05799SMatthew G. Knepley /*@C 50337cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 50347cd05799SMatthew G. Knepley 50357cd05799SMatthew G. Knepley Not Collective 50367cd05799SMatthew G. Knepley 50377cd05799SMatthew G. Knepley Input Parameters: 50387cd05799SMatthew G. Knepley . dm - The DMPlex object 50397cd05799SMatthew G. Knepley 50407cd05799SMatthew G. Knepley Output Parameter: 50417cd05799SMatthew G. Knepley . cones - The cone for each point 50427cd05799SMatthew G. Knepley 50437cd05799SMatthew G. Knepley Level: developer 50447cd05799SMatthew G. Knepley 5045db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 50467cd05799SMatthew G. Knepley @*/ 50479371c9d4SSatish Balay PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) { 5048552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5049552f7358SJed Brown 5050552f7358SJed Brown PetscFunctionBegin; 5051552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5052552f7358SJed Brown if (cones) *cones = mesh->cones; 5053552f7358SJed Brown PetscFunctionReturn(0); 5054552f7358SJed Brown } 5055552f7358SJed Brown 50567cd05799SMatthew G. Knepley /*@C 50577cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 50587cd05799SMatthew G. Knepley 50597cd05799SMatthew G. Knepley Not Collective 50607cd05799SMatthew G. Knepley 50617cd05799SMatthew G. Knepley Input Parameters: 50627cd05799SMatthew G. Knepley . dm - The DMPlex object 50637cd05799SMatthew G. Knepley 50647cd05799SMatthew G. Knepley Output Parameter: 5065b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 50667cd05799SMatthew G. Knepley 50677cd05799SMatthew G. Knepley Level: developer 50687cd05799SMatthew G. Knepley 5069b5a892a1SMatthew G. Knepley Notes: 5070b5a892a1SMatthew G. Knepley The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5071b5a892a1SMatthew G. Knepley 5072b5a892a1SMatthew G. Knepley The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5073b5a892a1SMatthew G. Knepley 5074db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()` 50757cd05799SMatthew G. Knepley @*/ 50769371c9d4SSatish Balay PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) { 5077552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5078552f7358SJed Brown 5079552f7358SJed Brown PetscFunctionBegin; 5080552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5081552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5082552f7358SJed Brown PetscFunctionReturn(0); 5083552f7358SJed Brown } 5084552f7358SJed Brown 5085552f7358SJed Brown /******************************** FEM Support **********************************/ 5086552f7358SJed Brown 50879e8305c2SJed Brown /* 50889e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 50899e8305c2SJed Brown representing a line in the section. 50909e8305c2SJed Brown */ 50919371c9d4SSatish Balay static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section, PetscInt field, PetscInt line, PetscBool vertexchart, PetscInt *Nc, PetscInt *k) { 50929e8305c2SJed Brown PetscFunctionBeginHot; 50939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5094a433471fSStefano Zampini if (line < 0) { 5095a433471fSStefano Zampini *k = 0; 5096a433471fSStefano Zampini *Nc = 0; 5097a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 50989e8305c2SJed Brown *k = 1; 50999e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 51009e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 51019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 51029e8305c2SJed Brown *k = *k / *Nc + 1; 51039e8305c2SJed Brown } 51049e8305c2SJed Brown PetscFunctionReturn(0); 51059e8305c2SJed Brown } 51069e8305c2SJed Brown 5107a4355906SMatthew Knepley /*@ 5108bc1eb3faSJed Brown 5109bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5110bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 51111bb6d2a8SBarry Smith section provided (or the section of the DM). 5112a4355906SMatthew Knepley 5113a4355906SMatthew Knepley Input Parameters: 5114a4355906SMatthew Knepley + dm - The DM 5115a4355906SMatthew Knepley . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5116a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section 5117a4355906SMatthew Knepley 5118a4355906SMatthew Knepley Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5119a4355906SMatthew Knepley degree of the basis. 5120a4355906SMatthew Knepley 5121bc1eb3faSJed Brown Example: 5122bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5123bc1eb3faSJed Brown .vb 5124bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5125bc1eb3faSJed Brown 5126bc1eb3faSJed Brown v4 -- e6 -- v3 5127bc1eb3faSJed Brown | | 5128bc1eb3faSJed Brown e7 c0 e8 5129bc1eb3faSJed Brown | | 5130bc1eb3faSJed Brown v1 -- e5 -- v2 5131bc1eb3faSJed Brown .ve 5132bc1eb3faSJed Brown 5133bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5134bc1eb3faSJed Brown dofs in the order of points, e.g., 5135bc1eb3faSJed Brown .vb 5136bc1eb3faSJed Brown c0 -> [0,1,2,3] 5137bc1eb3faSJed Brown v1 -> [4] 5138bc1eb3faSJed Brown ... 5139bc1eb3faSJed Brown e5 -> [8, 9] 5140bc1eb3faSJed Brown .ve 5141bc1eb3faSJed Brown 5142bc1eb3faSJed Brown which corresponds to the dofs 5143bc1eb3faSJed Brown .vb 5144bc1eb3faSJed Brown 6 10 11 7 5145bc1eb3faSJed Brown 13 2 3 15 5146bc1eb3faSJed Brown 12 0 1 14 5147bc1eb3faSJed Brown 4 8 9 5 5148bc1eb3faSJed Brown .ve 5149bc1eb3faSJed Brown 5150bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5151bc1eb3faSJed Brown .vb 5152bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5153bc1eb3faSJed Brown .ve 5154bc1eb3faSJed Brown 5155bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5156bc1eb3faSJed Brown .vb 5157bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5158bc1eb3faSJed Brown .ve 5159bc1eb3faSJed Brown 5160a4355906SMatthew Knepley Level: developer 5161a4355906SMatthew Knepley 5162db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5163a4355906SMatthew Knepley @*/ 51649371c9d4SSatish Balay PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) { 51657391a63aSMatthew G. Knepley DMLabel label; 5166bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 51679e8305c2SJed Brown PetscBool vertexchart; 51683194fc30SMatthew G. Knepley 51693194fc30SMatthew G. Knepley PetscFunctionBegin; 51709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5171a433471fSStefano Zampini if (dim < 1) PetscFunctionReturn(0); 5172a433471fSStefano Zampini if (point < 0) { 5173a433471fSStefano Zampini PetscInt sStart, sEnd; 5174a433471fSStefano Zampini 51759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5176a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5177a433471fSStefano Zampini } 51789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 51799566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 51809566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 51819371c9d4SSatish Balay if (depth == 1) { 51829371c9d4SSatish Balay eStart = point; 51839371c9d4SSatish Balay } else if (depth == dim) { 51847391a63aSMatthew G. Knepley const PetscInt *cone; 51857391a63aSMatthew G. Knepley 51869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5187d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5188d4e6627bSStefano Zampini else if (dim == 3) { 5189d4e6627bSStefano Zampini const PetscInt *cone2; 51909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5191d4e6627bSStefano Zampini eStart = cone2[0]; 519263a3b9bcSJacob 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); 519363a3b9bcSJacob 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); 51949e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 51959e8305c2SJed Brown PetscInt pStart, pEnd, cStart, cEnd; 51969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd)); 51979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &cStart, &cEnd)); 5198796d0a68SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5199796d0a68SJed Brown else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5200796d0a68SJed Brown else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 52019e8305c2SJed Brown } 52029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5203bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5204bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5205bb197d40SJed Brown PetscInt *perm; 5206bb197d40SJed Brown 52073194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 52089566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 5209bb197d40SJed Brown size += PetscPowInt(k + 1, d) * Nc; 52103194fc30SMatthew G. Knepley } 52119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 52123194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5213bb197d40SJed Brown switch (d) { 5214babf31e0SJed Brown case 1: 52159566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 5216babf31e0SJed Brown /* 5217babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5218babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5219babf31e0SJed Brown */ 5220babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 52219371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 52229371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5223babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5224babf31e0SJed Brown foffset = offset; 5225babf31e0SJed Brown break; 522689eabcffSMatthew G. Knepley case 2: 52273194fc30SMatthew 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} */ 52289566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 52293194fc30SMatthew G. Knepley /* The SEM order is 52303194fc30SMatthew G. Knepley 52313194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 523289eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 52333194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 52343194fc30SMatthew G. Knepley */ 52353194fc30SMatthew G. Knepley { 52363194fc30SMatthew G. Knepley const PetscInt of = 0; 52373194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 52383194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 52393194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 52403194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 52413194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 52423194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 52433194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 52443194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 52453194fc30SMatthew G. Knepley PetscInt o; 52463194fc30SMatthew G. Knepley 52473194fc30SMatthew G. Knepley /* bottom */ 52483194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 52499371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 52509371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 52513194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 52523194fc30SMatthew G. Knepley /* middle */ 52533194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 52543194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 52559371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 52569371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 52573194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 52583194fc30SMatthew G. Knepley } 52593194fc30SMatthew G. Knepley /* top */ 52603194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 52619371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 52629371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 52633194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 52643194fc30SMatthew G. Knepley foffset = offset; 52653194fc30SMatthew G. Knepley } 526689eabcffSMatthew G. Knepley break; 526789eabcffSMatthew G. Knepley case 3: 526889eabcffSMatthew G. Knepley /* The original hex closure is 526989eabcffSMatthew G. Knepley 527089eabcffSMatthew G. Knepley {c, 527189eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 527289eabcffSMatthew 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, 527389eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 527489eabcffSMatthew G. Knepley */ 52759566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k)); 527689eabcffSMatthew G. Knepley /* The SEM order is 527789eabcffSMatthew G. Knepley Bottom Slice 527889eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 527989eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 528089eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 528189eabcffSMatthew G. Knepley 528289eabcffSMatthew G. Knepley Middle Slice (j) 528389eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 528489eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 528589eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 528689eabcffSMatthew G. Knepley 528789eabcffSMatthew G. Knepley Top Slice 528889eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 528989eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 529089eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 529189eabcffSMatthew G. Knepley */ 529289eabcffSMatthew G. Knepley { 529389eabcffSMatthew G. Knepley const PetscInt oc = 0; 529489eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 529589eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 529689eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 529789eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 529889eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 529989eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 530089eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 530189eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 530289eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 530389eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 530489eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 530589eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 530689eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 530789eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 530889eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 530989eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 531089eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 531189eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 531289eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 531389eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 531489eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 531589eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 531689eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 531789eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 531889eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 531989eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 532089eabcffSMatthew G. Knepley PetscInt o, n; 532189eabcffSMatthew G. Knepley 532289eabcffSMatthew G. Knepley /* Bottom Slice */ 532389eabcffSMatthew G. Knepley /* bottom */ 532489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 53259371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 53269371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 532789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 532889eabcffSMatthew G. Knepley /* middle */ 532989eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 533089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 53319371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 53329371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 53339371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 53349371c9d4SSatish Balay } 533589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 53363194fc30SMatthew G. Knepley } 533789eabcffSMatthew G. Knepley /* top */ 533889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 53399371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 53409371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 534189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 534289eabcffSMatthew G. Knepley 534389eabcffSMatthew G. Knepley /* Middle Slice */ 534489eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 534589eabcffSMatthew G. Knepley /* bottom */ 534689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 53479371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 53489371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 534989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 535089eabcffSMatthew G. Knepley /* middle */ 535189eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 535289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 53539371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 53549371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 535589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 535689eabcffSMatthew G. Knepley } 535789eabcffSMatthew G. Knepley /* top */ 535889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 53599371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 53609371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 536189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 536289eabcffSMatthew G. Knepley } 536389eabcffSMatthew G. Knepley 536489eabcffSMatthew G. Knepley /* Top Slice */ 536589eabcffSMatthew G. Knepley /* bottom */ 536689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 53679371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 53689371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 536989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 537089eabcffSMatthew G. Knepley /* middle */ 537189eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 537289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 53739371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 53749371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 537589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 537689eabcffSMatthew G. Knepley } 537789eabcffSMatthew G. Knepley /* top */ 537889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 53799371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 53809371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 538189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 538289eabcffSMatthew G. Knepley 538389eabcffSMatthew G. Knepley foffset = offset; 538489eabcffSMatthew G. Knepley } 538589eabcffSMatthew G. Knepley break; 538663a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 538789eabcffSMatthew G. Knepley } 538889eabcffSMatthew G. Knepley } 538963a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 53903194fc30SMatthew G. Knepley /* Check permutation */ 53913194fc30SMatthew G. Knepley { 53923194fc30SMatthew G. Knepley PetscInt *check; 53933194fc30SMatthew G. Knepley 53949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 53951dca8a05SBarry Smith for (i = 0; i < size; ++i) { 53961dca8a05SBarry Smith check[i] = -1; 53971dca8a05SBarry 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]); 53981dca8a05SBarry Smith } 53993194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 54001dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 54019566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 54023194fc30SMatthew G. Knepley } 54039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 5404a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5405a05c9aa3SJed Brown PetscInt *loc_perm; 54069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 5407a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 5408a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5409a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 5410a05c9aa3SJed Brown } 54119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 5412a05c9aa3SJed Brown } 5413bb197d40SJed Brown } 54143194fc30SMatthew G. Knepley PetscFunctionReturn(0); 54153194fc30SMatthew G. Knepley } 54163194fc30SMatthew G. Knepley 54179371c9d4SSatish Balay PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) { 5418e071409bSToby Isaac PetscDS prob; 5419e071409bSToby Isaac PetscInt depth, Nf, h; 5420e071409bSToby Isaac DMLabel label; 5421e071409bSToby Isaac 5422e071409bSToby Isaac PetscFunctionBeginHot; 54239566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 5424e071409bSToby Isaac Nf = prob->Nf; 5425e071409bSToby Isaac label = dm->depthLabel; 5426e071409bSToby Isaac *dspace = NULL; 5427e071409bSToby Isaac if (field < Nf) { 5428e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5429e071409bSToby Isaac 5430e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5431e071409bSToby Isaac PetscDualSpace dsp; 5432e071409bSToby Isaac 54339566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 54349566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 54359566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 5436e071409bSToby Isaac h = depth - 1 - h; 5437e071409bSToby Isaac if (h) { 54389566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 5439e071409bSToby Isaac } else { 5440e071409bSToby Isaac *dspace = dsp; 5441e071409bSToby Isaac } 5442e071409bSToby Isaac } 5443e071409bSToby Isaac } 5444e071409bSToby Isaac PetscFunctionReturn(0); 5445e071409bSToby Isaac } 5446e071409bSToby Isaac 54479371c9d4SSatish Balay static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) { 544828351e22SJed Brown PetscScalar *array; 544928351e22SJed Brown const PetscScalar *vArray; 5450d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 54511a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5452552f7358SJed Brown 54531b406b76SMatthew G. Knepley PetscFunctionBeginHot; 54549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 54559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 54569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 54579566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 54583f7cbbe7SMatthew G. Knepley if (!values || !*values) { 54599df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 54609df71ca4SMatthew G. Knepley PetscInt dof; 5461d9917b9dSMatthew G. Knepley 54629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 54639df71ca4SMatthew G. Knepley size += dof; 54649df71ca4SMatthew G. Knepley } 54659df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 54669df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 54672a3aaacfSMatthew G. Knepley PetscInt dof; 54685a1bb5cfSMatthew G. Knepley 54695a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 54709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 54715a1bb5cfSMatthew G. Knepley size += dof; 54725a1bb5cfSMatthew G. Knepley } 54733f7cbbe7SMatthew G. Knepley if (!values) { 54743f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 54753f7cbbe7SMatthew G. Knepley PetscFunctionReturn(0); 54763f7cbbe7SMatthew G. Knepley } 54779566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 5478982e9ed1SMatthew G. Knepley } else { 5479982e9ed1SMatthew G. Knepley array = *values; 5480982e9ed1SMatthew G. Knepley } 54819df71ca4SMatthew G. Knepley size = 0; 548228351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 54839df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 54849df71ca4SMatthew G. Knepley PetscInt dof, off, d; 548528351e22SJed Brown const PetscScalar *varr; 5486d9917b9dSMatthew G. Knepley 54879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 54889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 54899df71ca4SMatthew G. Knepley varr = &vArray[off]; 5490ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 54919df71ca4SMatthew G. Knepley size += dof; 54929df71ca4SMatthew G. Knepley } 54939df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 54949df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 54959df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 54965a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 549728351e22SJed Brown const PetscScalar *varr; 54985a1bb5cfSMatthew G. Knepley 549952ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 55025a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 55035a1bb5cfSMatthew G. Knepley if (o >= 0) { 5504ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 55055a1bb5cfSMatthew G. Knepley } else { 5506ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 55075a1bb5cfSMatthew G. Knepley } 55089df71ca4SMatthew G. Knepley size += dof; 55095a1bb5cfSMatthew G. Knepley } 551028351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 55119df71ca4SMatthew G. Knepley if (!*values) { 55125a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 55135a1bb5cfSMatthew G. Knepley *values = array; 55149df71ca4SMatthew G. Knepley } else { 551563a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 55168c312ff3SMatthew G. Knepley *csize = size; 55179df71ca4SMatthew G. Knepley } 55185a1bb5cfSMatthew G. Knepley PetscFunctionReturn(0); 55195a1bb5cfSMatthew G. Knepley } 5520d9917b9dSMatthew G. Knepley 552127f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 55229371c9d4SSatish Balay static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) { 552327f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 552427f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 552527f02ce8SMatthew G. Knepley 55269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 552727f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 552827f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 552927f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 553027f02ce8SMatthew G. Knepley points[q * 2] = r; 553127f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 553227f02ce8SMatthew G. Knepley ++q; 553327f02ce8SMatthew G. Knepley } 553427f02ce8SMatthew G. Knepley } 553527f02ce8SMatthew G. Knepley *numPoints = q; 553627f02ce8SMatthew G. Knepley return 0; 553727f02ce8SMatthew G. Knepley } 553827f02ce8SMatthew G. Knepley 553997529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 55409371c9d4SSatish Balay PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) { 554127f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 5542923c78e0SToby Isaac PetscInt np, *pts = NULL; 5543923c78e0SToby Isaac 5544923c78e0SToby Isaac PetscFunctionBeginHot; 55459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 554627f02ce8SMatthew G. Knepley if (*clPoints) { 5547923c78e0SToby Isaac PetscInt dof, off; 5548923c78e0SToby Isaac 55499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 55509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 55519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 5552923c78e0SToby Isaac np = dof / 2; 5553923c78e0SToby Isaac pts = (PetscInt *)&cla[off]; 555427f02ce8SMatthew G. Knepley } else { 55559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts)); 55569566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 5557923c78e0SToby Isaac } 5558923c78e0SToby Isaac *numPoints = np; 5559923c78e0SToby Isaac *points = pts; 5560923c78e0SToby Isaac *clp = cla; 5561923c78e0SToby Isaac PetscFunctionReturn(0); 5562923c78e0SToby Isaac } 5563923c78e0SToby Isaac 55649371c9d4SSatish Balay PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) { 5565923c78e0SToby Isaac PetscFunctionBeginHot; 5566923c78e0SToby Isaac if (!*clPoints) { 55679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 5568923c78e0SToby Isaac } else { 55699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 5570923c78e0SToby Isaac } 5571923c78e0SToby Isaac *numPoints = 0; 5572923c78e0SToby Isaac *points = NULL; 5573923c78e0SToby Isaac *clSec = NULL; 5574923c78e0SToby Isaac *clPoints = NULL; 5575923c78e0SToby Isaac *clp = NULL; 5576923c78e0SToby Isaac PetscFunctionReturn(0); 5577923c78e0SToby Isaac } 5578923c78e0SToby Isaac 55799371c9d4SSatish Balay static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) { 55801a271a75SMatthew G. Knepley PetscInt offset = 0, p; 558197e99dd9SToby Isaac const PetscInt **perms = NULL; 558297e99dd9SToby Isaac const PetscScalar **flips = NULL; 55831a271a75SMatthew G. Knepley 55841a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5585fe02ba77SJed Brown *size = 0; 55869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 558797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 558897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 558997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 559097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 55911a271a75SMatthew G. Knepley PetscInt dof, off, d; 55921a271a75SMatthew G. Knepley const PetscScalar *varr; 55931a271a75SMatthew G. Knepley 55949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 55961a271a75SMatthew G. Knepley varr = &vArray[off]; 559797e99dd9SToby Isaac if (clperm) { 559897e99dd9SToby Isaac if (perm) { 559997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 56001a271a75SMatthew G. Knepley } else { 560197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 560297e99dd9SToby Isaac } 560397e99dd9SToby Isaac if (flip) { 560497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 560597e99dd9SToby Isaac } 560697e99dd9SToby Isaac } else { 560797e99dd9SToby Isaac if (perm) { 560897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 560997e99dd9SToby Isaac } else { 561097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 561197e99dd9SToby Isaac } 561297e99dd9SToby Isaac if (flip) { 561397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 56141a271a75SMatthew G. Knepley } 56151a271a75SMatthew G. Knepley } 561697e99dd9SToby Isaac offset += dof; 561797e99dd9SToby Isaac } 56189566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 56191a271a75SMatthew G. Knepley *size = offset; 56201a271a75SMatthew G. Knepley PetscFunctionReturn(0); 56211a271a75SMatthew G. Knepley } 56221a271a75SMatthew G. Knepley 56239371c9d4SSatish Balay 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[]) { 56241a271a75SMatthew G. Knepley PetscInt offset = 0, f; 56251a271a75SMatthew G. Knepley 56261a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5627fe02ba77SJed Brown *size = 0; 56281a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 562997e99dd9SToby Isaac PetscInt p; 563097e99dd9SToby Isaac const PetscInt **perms = NULL; 563197e99dd9SToby Isaac const PetscScalar **flips = NULL; 56321a271a75SMatthew G. Knepley 56339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 563497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 563597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 563697e99dd9SToby Isaac PetscInt fdof, foff, b; 56371a271a75SMatthew G. Knepley const PetscScalar *varr; 563897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 563997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 56401a271a75SMatthew G. Knepley 56419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 56429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 56431a271a75SMatthew G. Knepley varr = &vArray[foff]; 564497e99dd9SToby Isaac if (clperm) { 56459371c9d4SSatish Balay if (perm) { 5646ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 56471a271a75SMatthew G. Knepley } else { 5648ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 56499371c9d4SSatish Balay } 56509371c9d4SSatish Balay if (flip) { 5651ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 56529371c9d4SSatish Balay } 56539371c9d4SSatish Balay } else { 56549371c9d4SSatish Balay if (perm) { 5655ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 56569371c9d4SSatish Balay } else { 5657ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 56589371c9d4SSatish Balay } 56599371c9d4SSatish Balay if (flip) { 5660ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 56619371c9d4SSatish Balay } 56621a271a75SMatthew G. Knepley } 566397e99dd9SToby Isaac offset += fdof; 56641a271a75SMatthew G. Knepley } 56659566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 56661a271a75SMatthew G. Knepley } 56671a271a75SMatthew G. Knepley *size = offset; 56681a271a75SMatthew G. Knepley PetscFunctionReturn(0); 56691a271a75SMatthew G. Knepley } 56701a271a75SMatthew G. Knepley 5671552f7358SJed Brown /*@C 5672552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5673552f7358SJed Brown 5674552f7358SJed Brown Not collective 5675552f7358SJed Brown 5676552f7358SJed Brown Input Parameters: 5677552f7358SJed Brown + dm - The DM 5678552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section 5679552f7358SJed Brown . v - The local vector 56806b867d5aSJose E. Roman - point - The point in the DM 5681552f7358SJed Brown 56826b867d5aSJose E. Roman Input/Output Parameters: 56836b867d5aSJose E. Roman + csize - The size of the input values array, or NULL; on output the number of values in the closure 56846b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically; 56856b867d5aSJose E. Roman if the user provided NULL, it is a borrowed array and should not be freed 568622c1ee49SMatthew G. Knepley 568722c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 568822c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 568922c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation. 569022c1ee49SMatthew G. Knepley $ 569122c1ee49SMatthew G. Knepley $ A typical use could be 569222c1ee49SMatthew G. Knepley $ 569322c1ee49SMatthew G. Knepley $ values = NULL; 56949566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 569522c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 569622c1ee49SMatthew G. Knepley $ <Compute on closure> 569722c1ee49SMatthew G. Knepley $ } 56989566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 569922c1ee49SMatthew G. Knepley $ 570022c1ee49SMatthew G. Knepley $ or 570122c1ee49SMatthew G. Knepley $ 570222c1ee49SMatthew G. Knepley $ PetscMalloc1(clMaxSize, &values); 570322c1ee49SMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) { 570422c1ee49SMatthew G. Knepley $ clSize = clMaxSize; 57059566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 570622c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 570722c1ee49SMatthew G. Knepley $ <Compute on closure> 570822c1ee49SMatthew G. Knepley $ } 570922c1ee49SMatthew G. Knepley $ } 571022c1ee49SMatthew G. Knepley $ PetscFree(values); 5711552f7358SJed Brown 5712552f7358SJed Brown Fortran Notes: 5713552f7358SJed Brown Since it returns an array, this routine is only available in Fortran 90, and you must 5714552f7358SJed Brown include petsc.h90 in your code. 5715552f7358SJed Brown 5716552f7358SJed Brown The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5717552f7358SJed Brown 5718552f7358SJed Brown Level: intermediate 5719552f7358SJed Brown 5720db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5721552f7358SJed Brown @*/ 57229371c9d4SSatish Balay PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) { 5723552f7358SJed Brown PetscSection clSection; 5724d9917b9dSMatthew G. Knepley IS clPoints; 5725552f7358SJed Brown PetscInt *points = NULL; 5726c459fbc1SJed Brown const PetscInt *clp, *perm; 5727c459fbc1SJed Brown PetscInt depth, numFields, numPoints, asize; 5728552f7358SJed Brown 5729d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 5730552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 57319566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 57321a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 57331a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 57349566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 57359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5736552f7358SJed Brown if (depth == 1 && numFields < 2) { 57379566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5738552f7358SJed Brown PetscFunctionReturn(0); 5739552f7358SJed Brown } 57401a271a75SMatthew G. Knepley /* Get points */ 57419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 5742c459fbc1SJed Brown /* Get sizes */ 5743c459fbc1SJed Brown asize = 0; 5744c459fbc1SJed Brown for (PetscInt p = 0; p < numPoints * 2; p += 2) { 5745c459fbc1SJed Brown PetscInt dof; 57469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 57471a271a75SMatthew G. Knepley asize += dof; 5748552f7358SJed Brown } 5749c459fbc1SJed Brown if (values) { 5750c459fbc1SJed Brown const PetscScalar *vArray; 5751c459fbc1SJed Brown PetscInt size; 5752c459fbc1SJed Brown 5753c459fbc1SJed Brown if (*values) { 575463a3b9bcSJacob 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); 57559566063dSJacob Faibussowitsch } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 57569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 57579566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 57581a271a75SMatthew G. Knepley /* Get values */ 57599566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 57609566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 576163a3b9bcSJacob Faibussowitsch PetscCheck(asize == size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size); 57621a271a75SMatthew G. Knepley /* Cleanup array */ 57639566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5764d0f6b257SMatthew G. Knepley } 5765c459fbc1SJed Brown if (csize) *csize = asize; 5766c459fbc1SJed Brown /* Cleanup points */ 57679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 5768552f7358SJed Brown PetscFunctionReturn(0); 5769552f7358SJed Brown } 5770552f7358SJed Brown 57719371c9d4SSatish Balay PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) { 5772e5c487bfSMatthew G. Knepley DMLabel depthLabel; 5773e5c487bfSMatthew G. Knepley PetscSection clSection; 5774e5c487bfSMatthew G. Knepley IS clPoints; 5775e5c487bfSMatthew G. Knepley PetscScalar *array; 5776e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 5777e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 5778c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 5779c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5780e5c487bfSMatthew G. Knepley 5781e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 5782e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 57839566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 5784e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5785e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 57869566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 57879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 57889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5789e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 57909566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5791e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5792e5c487bfSMatthew G. Knepley } 5793e5c487bfSMatthew G. Knepley /* Get points */ 57949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 5795c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 5796c459fbc1SJed Brown PetscInt dof; 57979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 5798c459fbc1SJed Brown clsize += dof; 5799c459fbc1SJed Brown } 58009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 5801e5c487bfSMatthew G. Knepley /* Filter points */ 5802e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 5803e5c487bfSMatthew G. Knepley PetscInt dep; 5804e5c487bfSMatthew G. Knepley 58059566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 5806e5c487bfSMatthew G. Knepley if (dep != depth) continue; 5807e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 5808e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 5809e5c487bfSMatthew G. Knepley ++Np; 5810e5c487bfSMatthew G. Knepley } 5811e5c487bfSMatthew G. Knepley /* Get array */ 5812e5c487bfSMatthew G. Knepley if (!values || !*values) { 5813e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 5814e5c487bfSMatthew G. Knepley 5815e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 58169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 5817e5c487bfSMatthew G. Knepley asize += dof; 5818e5c487bfSMatthew G. Knepley } 5819e5c487bfSMatthew G. Knepley if (!values) { 58209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 5821e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 5822e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5823e5c487bfSMatthew G. Knepley } 58249566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 5825e5c487bfSMatthew G. Knepley } else { 5826e5c487bfSMatthew G. Knepley array = *values; 5827e5c487bfSMatthew G. Knepley } 58289566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 5829e5c487bfSMatthew G. Knepley /* Get values */ 58309566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 58319566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 5832e5c487bfSMatthew G. Knepley /* Cleanup points */ 58339566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 5834e5c487bfSMatthew G. Knepley /* Cleanup array */ 58359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5836e5c487bfSMatthew G. Knepley if (!*values) { 5837e5c487bfSMatthew G. Knepley if (csize) *csize = size; 5838e5c487bfSMatthew G. Knepley *values = array; 5839e5c487bfSMatthew G. Knepley } else { 584063a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 5841e5c487bfSMatthew G. Knepley *csize = size; 5842e5c487bfSMatthew G. Knepley } 5843e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5844e5c487bfSMatthew G. Knepley } 5845e5c487bfSMatthew G. Knepley 5846552f7358SJed Brown /*@C 5847552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5848552f7358SJed Brown 5849552f7358SJed Brown Not collective 5850552f7358SJed Brown 5851552f7358SJed Brown Input Parameters: 5852552f7358SJed Brown + dm - The DM 58530298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section 5854552f7358SJed Brown . v - The local vector 5855eaf898f9SPatrick Sanan . point - The point in the DM 58560298fd71SBarry Smith . csize - The number of values in the closure, or NULL 5857552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 5858552f7358SJed Brown 585922c1ee49SMatthew G. Knepley Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 586022c1ee49SMatthew G. Knepley 58613813dfbdSMatthew G Knepley Fortran Notes: 58623813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 58633813dfbdSMatthew G Knepley include petsc.h90 in your code. 58643813dfbdSMatthew G Knepley 58653813dfbdSMatthew G Knepley The csize argument is not present in the Fortran 90 binding since it is internal to the array. 58663813dfbdSMatthew G Knepley 5867552f7358SJed Brown Level: intermediate 5868552f7358SJed Brown 5869db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5870552f7358SJed Brown @*/ 58719371c9d4SSatish Balay PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) { 5872552f7358SJed Brown PetscInt size = 0; 5873552f7358SJed Brown 5874552f7358SJed Brown PetscFunctionBegin; 5875552f7358SJed Brown /* Should work without recalculating size */ 58769566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 5877c9fdaa05SMatthew G. Knepley *values = NULL; 5878552f7358SJed Brown PetscFunctionReturn(0); 5879552f7358SJed Brown } 5880552f7358SJed Brown 58819371c9d4SSatish Balay static inline void add(PetscScalar *x, PetscScalar y) { 58829371c9d4SSatish Balay *x += y; 58839371c9d4SSatish Balay } 58849371c9d4SSatish Balay static inline void insert(PetscScalar *x, PetscScalar y) { 58859371c9d4SSatish Balay *x = y; 58869371c9d4SSatish Balay } 5887552f7358SJed Brown 58889371c9d4SSatish Balay 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[]) { 5889552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 5890552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5891552f7358SJed Brown PetscScalar *a; 5892552f7358SJed Brown PetscInt off, cind = 0, k; 5893552f7358SJed Brown 5894552f7358SJed Brown PetscFunctionBegin; 58959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 58969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 5897552f7358SJed Brown a = &array[off]; 5898552f7358SJed Brown if (!cdof || setBC) { 589997e99dd9SToby Isaac if (clperm) { 59009371c9d4SSatish Balay if (perm) { 5901ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5902552f7358SJed Brown } else { 5903ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 59049371c9d4SSatish Balay } 59059371c9d4SSatish Balay } else { 59069371c9d4SSatish Balay if (perm) { 5907ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 59089371c9d4SSatish Balay } else { 5909ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 59109371c9d4SSatish Balay } 5911552f7358SJed Brown } 5912552f7358SJed Brown } else { 59139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 591497e99dd9SToby Isaac if (clperm) { 59159371c9d4SSatish Balay if (perm) { 59169371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 59179371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 59189371c9d4SSatish Balay ++cind; 59199371c9d4SSatish Balay continue; 59209371c9d4SSatish Balay } 592197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5922552f7358SJed Brown } 5923552f7358SJed Brown } else { 5924552f7358SJed Brown for (k = 0; k < dof; ++k) { 59259371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 59269371c9d4SSatish Balay ++cind; 59279371c9d4SSatish Balay continue; 59289371c9d4SSatish Balay } 592997e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 593097e99dd9SToby Isaac } 593197e99dd9SToby Isaac } 593297e99dd9SToby Isaac } else { 593397e99dd9SToby Isaac if (perm) { 593497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 59359371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 59369371c9d4SSatish Balay ++cind; 59379371c9d4SSatish Balay continue; 59389371c9d4SSatish Balay } 593997e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 594097e99dd9SToby Isaac } 594197e99dd9SToby Isaac } else { 594297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 59439371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 59449371c9d4SSatish Balay ++cind; 59459371c9d4SSatish Balay continue; 59469371c9d4SSatish Balay } 594797e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 594897e99dd9SToby Isaac } 5949552f7358SJed Brown } 5950552f7358SJed Brown } 5951552f7358SJed Brown } 5952552f7358SJed Brown PetscFunctionReturn(0); 5953552f7358SJed Brown } 5954552f7358SJed Brown 59559371c9d4SSatish Balay 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[]) { 5956a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 5957a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5958a5e93ea8SMatthew G. Knepley PetscScalar *a; 5959a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 5960a5e93ea8SMatthew G. Knepley 5961a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 59629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 59639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 5964a5e93ea8SMatthew G. Knepley a = &array[off]; 5965a5e93ea8SMatthew G. Knepley if (cdof) { 59669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 596797e99dd9SToby Isaac if (clperm) { 596897e99dd9SToby Isaac if (perm) { 5969a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 5970a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 597197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 597297e99dd9SToby Isaac cind++; 5973a5e93ea8SMatthew G. Knepley } 5974a5e93ea8SMatthew G. Knepley } 5975a5e93ea8SMatthew G. Knepley } else { 5976a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 5977a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 597897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 597997e99dd9SToby Isaac cind++; 598097e99dd9SToby Isaac } 598197e99dd9SToby Isaac } 598297e99dd9SToby Isaac } 598397e99dd9SToby Isaac } else { 598497e99dd9SToby Isaac if (perm) { 598597e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 598697e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 598797e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 598897e99dd9SToby Isaac cind++; 598997e99dd9SToby Isaac } 599097e99dd9SToby Isaac } 599197e99dd9SToby Isaac } else { 599297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 599397e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 599497e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 599597e99dd9SToby Isaac cind++; 599697e99dd9SToby Isaac } 5997a5e93ea8SMatthew G. Knepley } 5998a5e93ea8SMatthew G. Knepley } 5999a5e93ea8SMatthew G. Knepley } 6000a5e93ea8SMatthew G. Knepley } 6001a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6002a5e93ea8SMatthew G. Knepley } 6003a5e93ea8SMatthew G. Knepley 60049371c9d4SSatish Balay 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[]) { 6005552f7358SJed Brown PetscScalar *a; 60061a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60071a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 600897e99dd9SToby Isaac PetscInt cind = 0, b; 6009552f7358SJed Brown 6010552f7358SJed Brown PetscFunctionBegin; 60119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 60129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 60139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 60141a271a75SMatthew G. Knepley a = &array[foff]; 6015552f7358SJed Brown if (!fcdof || setBC) { 601697e99dd9SToby Isaac if (clperm) { 60179371c9d4SSatish Balay if (perm) { 6018ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6019552f7358SJed Brown } else { 6020ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 60219371c9d4SSatish Balay } 60229371c9d4SSatish Balay } else { 60239371c9d4SSatish Balay if (perm) { 6024ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 60259371c9d4SSatish Balay } else { 6026ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 60279371c9d4SSatish Balay } 6028552f7358SJed Brown } 6029552f7358SJed Brown } else { 60309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 603197e99dd9SToby Isaac if (clperm) { 603297e99dd9SToby Isaac if (perm) { 603397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 60349371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 60359371c9d4SSatish Balay ++cind; 60369371c9d4SSatish Balay continue; 60379371c9d4SSatish Balay } 603897e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6039552f7358SJed Brown } 6040552f7358SJed Brown } else { 604197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 60429371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 60439371c9d4SSatish Balay ++cind; 60449371c9d4SSatish Balay continue; 60459371c9d4SSatish Balay } 604697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 604797e99dd9SToby Isaac } 604897e99dd9SToby Isaac } 604997e99dd9SToby Isaac } else { 605097e99dd9SToby Isaac if (perm) { 605197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 60529371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 60539371c9d4SSatish Balay ++cind; 60549371c9d4SSatish Balay continue; 60559371c9d4SSatish Balay } 605697e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 605797e99dd9SToby Isaac } 605897e99dd9SToby Isaac } else { 605997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 60609371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 60619371c9d4SSatish Balay ++cind; 60629371c9d4SSatish Balay continue; 60639371c9d4SSatish Balay } 606497e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6065552f7358SJed Brown } 6066552f7358SJed Brown } 6067552f7358SJed Brown } 6068552f7358SJed Brown } 60691a271a75SMatthew G. Knepley *offset += fdof; 6070552f7358SJed Brown PetscFunctionReturn(0); 6071552f7358SJed Brown } 6072552f7358SJed Brown 60739371c9d4SSatish Balay 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[]) { 6074a5e93ea8SMatthew G. Knepley PetscScalar *a; 60751a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60761a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 60775da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6078ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6079a5e93ea8SMatthew G. Knepley 6080a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 60819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 60829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 60839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 60849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 60851a271a75SMatthew G. Knepley a = &array[foff]; 6086a5e93ea8SMatthew G. Knepley if (fcdof) { 6087ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 60889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 608997e99dd9SToby Isaac if (clperm) { 609097e99dd9SToby Isaac if (perm) { 6091ba322698SMatthew G. Knepley if (comps) { 6092ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6093ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 60949371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 60959371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 60969371c9d4SSatish Balay ncSet = PETSC_TRUE; 60979371c9d4SSatish Balay } 60989371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 60999371c9d4SSatish Balay ++cind; 61009371c9d4SSatish Balay fcSet = PETSC_TRUE; 61019371c9d4SSatish Balay } 6102ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6103ba322698SMatthew G. Knepley } 6104ba322698SMatthew G. Knepley } else { 610597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 610697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 610797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6108a5e93ea8SMatthew G. Knepley ++cind; 6109a5e93ea8SMatthew G. Knepley } 6110a5e93ea8SMatthew G. Knepley } 6111ba322698SMatthew G. Knepley } 6112ba322698SMatthew G. Knepley } else { 6113ba322698SMatthew G. Knepley if (comps) { 6114ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6115ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61169371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 61179371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 61189371c9d4SSatish Balay ncSet = PETSC_TRUE; 61199371c9d4SSatish Balay } 61209371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 61219371c9d4SSatish Balay ++cind; 61229371c9d4SSatish Balay fcSet = PETSC_TRUE; 61239371c9d4SSatish Balay } 6124ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6125ba322698SMatthew G. Knepley } 6126a5e93ea8SMatthew G. Knepley } else { 612797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 612897e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 612997e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 613097e99dd9SToby Isaac ++cind; 613197e99dd9SToby Isaac } 613297e99dd9SToby Isaac } 613397e99dd9SToby Isaac } 6134ba322698SMatthew G. Knepley } 613597e99dd9SToby Isaac } else { 613697e99dd9SToby Isaac if (perm) { 6137ba322698SMatthew G. Knepley if (comps) { 6138ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6139ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61409371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 61419371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 61429371c9d4SSatish Balay ncSet = PETSC_TRUE; 61439371c9d4SSatish Balay } 61449371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 61459371c9d4SSatish Balay ++cind; 61469371c9d4SSatish Balay fcSet = PETSC_TRUE; 61479371c9d4SSatish Balay } 6148ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6149ba322698SMatthew G. Knepley } 6150ba322698SMatthew G. Knepley } else { 615197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 615297e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 615397e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 615497e99dd9SToby Isaac ++cind; 615597e99dd9SToby Isaac } 615697e99dd9SToby Isaac } 6157ba322698SMatthew G. Knepley } 6158ba322698SMatthew G. Knepley } else { 6159ba322698SMatthew G. Knepley if (comps) { 6160ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6161ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61629371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 61639371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 61649371c9d4SSatish Balay ncSet = PETSC_TRUE; 61659371c9d4SSatish Balay } 61669371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 61679371c9d4SSatish Balay ++cind; 61689371c9d4SSatish Balay fcSet = PETSC_TRUE; 61699371c9d4SSatish Balay } 6170ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6171ba322698SMatthew G. Knepley } 617297e99dd9SToby Isaac } else { 617397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 617497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 617597e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6176a5e93ea8SMatthew G. Knepley ++cind; 6177a5e93ea8SMatthew G. Knepley } 6178a5e93ea8SMatthew G. Knepley } 6179a5e93ea8SMatthew G. Knepley } 6180a5e93ea8SMatthew G. Knepley } 6181a5e93ea8SMatthew G. Knepley } 6182ba322698SMatthew G. Knepley } 61831a271a75SMatthew G. Knepley *offset += fdof; 6184a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6185a5e93ea8SMatthew G. Knepley } 6186a5e93ea8SMatthew G. Knepley 61879371c9d4SSatish Balay static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) { 6188552f7358SJed Brown PetscScalar *array; 61891b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 61901b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6191552f7358SJed Brown 61921b406b76SMatthew G. Knepley PetscFunctionBeginHot; 61939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 61949566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 61959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 61969566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 61979566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6198b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6199b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6200b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6201b6ebb6e6SMatthew G. Knepley 62029371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 62039371c9d4SSatish Balay dof = 0; 62049371c9d4SSatish Balay continue; 62059371c9d4SSatish Balay } 62069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6207b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6208b6ebb6e6SMatthew G. Knepley { 6209b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6210b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6211b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6212b6ebb6e6SMatthew G. Knepley 62139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 62149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6215b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6216b6ebb6e6SMatthew G. Knepley if (!cdof) { 6217b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6218ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6219b6ebb6e6SMatthew G. Knepley } else { 6220ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6221b6ebb6e6SMatthew G. Knepley } 6222b6ebb6e6SMatthew G. Knepley } else { 62239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6224b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6225b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 62269371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 62279371c9d4SSatish Balay ++cind; 62289371c9d4SSatish Balay continue; 62299371c9d4SSatish Balay } 6230b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6231b6ebb6e6SMatthew G. Knepley } 6232b6ebb6e6SMatthew G. Knepley } else { 6233b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 62349371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 62359371c9d4SSatish Balay ++cind; 62369371c9d4SSatish Balay continue; 62379371c9d4SSatish Balay } 6238b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6239b6ebb6e6SMatthew G. Knepley } 6240b6ebb6e6SMatthew G. Knepley } 6241b6ebb6e6SMatthew G. Knepley } 6242b6ebb6e6SMatthew G. Knepley } 6243b6ebb6e6SMatthew G. Knepley } 62449566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6245b6ebb6e6SMatthew G. Knepley PetscFunctionReturn(0); 6246b6ebb6e6SMatthew G. Knepley } 62471b406b76SMatthew G. Knepley 62481b406b76SMatthew G. Knepley /*@C 62491b406b76SMatthew G. Knepley DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 62501b406b76SMatthew G. Knepley 62511b406b76SMatthew G. Knepley Not collective 62521b406b76SMatthew G. Knepley 62531b406b76SMatthew G. Knepley Input Parameters: 62541b406b76SMatthew G. Knepley + dm - The DM 62551b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 62561b406b76SMatthew G. Knepley . v - The local vector 6257eaf898f9SPatrick Sanan . point - The point in the DM 62581b406b76SMatthew G. Knepley . values - The array of values 625922c1ee49SMatthew G. Knepley - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 626022c1ee49SMatthew G. Knepley where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 62611b406b76SMatthew G. Knepley 62621b406b76SMatthew G. Knepley Fortran Notes: 62631b406b76SMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 62641b406b76SMatthew G. Knepley 62651b406b76SMatthew G. Knepley Level: intermediate 62661b406b76SMatthew G. Knepley 6267db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 62681b406b76SMatthew G. Knepley @*/ 62699371c9d4SSatish Balay PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) { 62701b406b76SMatthew G. Knepley PetscSection clSection; 62711b406b76SMatthew G. Knepley IS clPoints; 62721b406b76SMatthew G. Knepley PetscScalar *array; 62731b406b76SMatthew G. Knepley PetscInt *points = NULL; 627427f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6275c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 62761b406b76SMatthew G. Knepley 62771a271a75SMatthew G. Knepley PetscFunctionBeginHot; 62781b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62799566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 62801a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 62811a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 62829566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 62839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 62841b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 62859566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 62861b406b76SMatthew G. Knepley PetscFunctionReturn(0); 62871b406b76SMatthew G. Knepley } 62881a271a75SMatthew G. Knepley /* Get points */ 62899566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6290c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6291c459fbc1SJed Brown PetscInt dof; 62929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6293c459fbc1SJed Brown clsize += dof; 6294c459fbc1SJed Brown } 62959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 62961a271a75SMatthew G. Knepley /* Get array */ 62979566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 62981a271a75SMatthew G. Knepley /* Get values */ 6299ef90cfe2SMatthew G. Knepley if (numFields > 0) { 630097e99dd9SToby Isaac PetscInt offset = 0, f; 6301552f7358SJed Brown for (f = 0; f < numFields; ++f) { 630297e99dd9SToby Isaac const PetscInt **perms = NULL; 630397e99dd9SToby Isaac const PetscScalar **flips = NULL; 630497e99dd9SToby Isaac 63059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6306552f7358SJed Brown switch (mode) { 6307552f7358SJed Brown case INSERT_VALUES: 630897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 630997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 631097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 631197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 631297e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 63139371c9d4SSatish Balay } 63149371c9d4SSatish Balay break; 6315552f7358SJed Brown case INSERT_ALL_VALUES: 631697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 631797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 631897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 631997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 632097e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 63219371c9d4SSatish Balay } 63229371c9d4SSatish Balay break; 6323a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 632497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 632697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6328ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 63299371c9d4SSatish Balay } 63309371c9d4SSatish Balay break; 6331552f7358SJed Brown case ADD_VALUES: 633297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 633397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 633497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 633597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 633697e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 63379371c9d4SSatish Balay } 63389371c9d4SSatish Balay break; 6339552f7358SJed Brown case ADD_ALL_VALUES: 634097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 634197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 634297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 634397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 634497e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 63459371c9d4SSatish Balay } 63469371c9d4SSatish Balay break; 6347304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 634897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 634997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 635097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 635197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6352ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 63539371c9d4SSatish Balay } 63549371c9d4SSatish Balay break; 63559371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6356552f7358SJed Brown } 63579566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 63581a271a75SMatthew G. Knepley } 6359552f7358SJed Brown } else { 63601a271a75SMatthew G. Knepley PetscInt dof, off; 636197e99dd9SToby Isaac const PetscInt **perms = NULL; 636297e99dd9SToby Isaac const PetscScalar **flips = NULL; 63631a271a75SMatthew G. Knepley 63649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 6365552f7358SJed Brown switch (mode) { 6366552f7358SJed Brown case INSERT_VALUES: 636797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 636897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 636997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 637097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 637297e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 63739371c9d4SSatish Balay } 63749371c9d4SSatish Balay break; 6375552f7358SJed Brown case INSERT_ALL_VALUES: 637697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 637797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 637897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 637997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 638197e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 63829371c9d4SSatish Balay } 63839371c9d4SSatish Balay break; 6384a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 638597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 638697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 638797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 638897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 639097e99dd9SToby Isaac updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 63919371c9d4SSatish Balay } 63929371c9d4SSatish Balay break; 6393552f7358SJed Brown case ADD_VALUES: 639497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 639597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 639697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 639797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 639997e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 64009371c9d4SSatish Balay } 64019371c9d4SSatish Balay break; 6402552f7358SJed Brown case ADD_ALL_VALUES: 640397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 640497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 640597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 640697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 640897e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 64099371c9d4SSatish Balay } 64109371c9d4SSatish Balay break; 6411304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 641297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 641397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 641497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 641597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 641797e99dd9SToby Isaac updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 64189371c9d4SSatish Balay } 64199371c9d4SSatish Balay break; 64209371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6421552f7358SJed Brown } 64229566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 6423552f7358SJed Brown } 64241a271a75SMatthew G. Knepley /* Cleanup points */ 64259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 64261a271a75SMatthew G. Knepley /* Cleanup array */ 64279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6428552f7358SJed Brown PetscFunctionReturn(0); 6429552f7358SJed Brown } 6430552f7358SJed Brown 64315f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 643211cc89d2SBarry Smith static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) { 64335f790a90SMatthew G. Knepley PetscFunctionBegin; 643411cc89d2SBarry Smith *contains = PETSC_TRUE; 64355f790a90SMatthew G. Knepley if (label) { 6436d6177c40SToby Isaac PetscInt fdof; 64375f790a90SMatthew G. Knepley 643811cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 643911cc89d2SBarry Smith if (!*contains) { 64409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 64415f790a90SMatthew G. Knepley *offset += fdof; 644211cc89d2SBarry Smith PetscFunctionReturn(0); 64435f790a90SMatthew G. Knepley } 64445f790a90SMatthew G. Knepley } 64455f790a90SMatthew G. Knepley PetscFunctionReturn(0); 64465f790a90SMatthew G. Knepley } 64475f790a90SMatthew G. Knepley 644897529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 64499371c9d4SSatish Balay 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) { 6450e07394fbSMatthew G. Knepley PetscSection clSection; 6451e07394fbSMatthew G. Knepley IS clPoints; 6452e07394fbSMatthew G. Knepley PetscScalar *array; 6453e07394fbSMatthew G. Knepley PetscInt *points = NULL; 645497529cf3SJed Brown const PetscInt *clp; 6455e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 645697e99dd9SToby Isaac PetscInt offset = 0, f; 6457e07394fbSMatthew G. Knepley 6458e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 6459e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64609566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6461e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6462e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6464e07394fbSMatthew G. Knepley /* Get points */ 64659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6466e07394fbSMatthew G. Knepley /* Get array */ 64679566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6468e07394fbSMatthew G. Knepley /* Get values */ 6469e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 647097e99dd9SToby Isaac const PetscInt **perms = NULL; 647197e99dd9SToby Isaac const PetscScalar **flips = NULL; 647211cc89d2SBarry Smith PetscBool contains; 647397e99dd9SToby Isaac 6474e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 6475e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6476e07394fbSMatthew G. Knepley PetscInt fdof; 64779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 6478e07394fbSMatthew G. Knepley offset += fdof; 6479e07394fbSMatthew G. Knepley } 6480e07394fbSMatthew G. Knepley continue; 6481e07394fbSMatthew G. Knepley } 64829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6483e07394fbSMatthew G. Knepley switch (mode) { 6484e07394fbSMatthew G. Knepley case INSERT_VALUES: 648597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 648697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 648797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 648897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 648911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 649011cc89d2SBarry Smith if (!contains) continue; 64919566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 64929371c9d4SSatish Balay } 64939371c9d4SSatish Balay break; 6494e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 649597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 649797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 649911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 650011cc89d2SBarry Smith if (!contains) continue; 65019566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 65029371c9d4SSatish Balay } 65039371c9d4SSatish Balay break; 6504e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 650597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 650697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 650797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 650897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 650911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 651011cc89d2SBarry Smith if (!contains) continue; 65119566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 65129371c9d4SSatish Balay } 65139371c9d4SSatish Balay break; 6514e07394fbSMatthew G. Knepley case ADD_VALUES: 651597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 651697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 651797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 651897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 651911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 652011cc89d2SBarry Smith if (!contains) continue; 65219566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 65229371c9d4SSatish Balay } 65239371c9d4SSatish Balay break; 6524e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 652597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 652697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 652797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 652897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 652911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 653011cc89d2SBarry Smith if (!contains) continue; 65319566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 65329371c9d4SSatish Balay } 65339371c9d4SSatish Balay break; 65349371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6535e07394fbSMatthew G. Knepley } 65369566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6537e07394fbSMatthew G. Knepley } 6538e07394fbSMatthew G. Knepley /* Cleanup points */ 65399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6540e07394fbSMatthew G. Knepley /* Cleanup array */ 65419566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6542e07394fbSMatthew G. Knepley PetscFunctionReturn(0); 6543e07394fbSMatthew G. Knepley } 6544e07394fbSMatthew G. Knepley 65459371c9d4SSatish Balay static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) { 6546552f7358SJed Brown PetscMPIInt rank; 6547552f7358SJed Brown PetscInt i, j; 6548552f7358SJed Brown 6549552f7358SJed Brown PetscFunctionBegin; 65509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 655163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 655263a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 655363a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 6554b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 6555557cf195SMatthew G. Knepley if (!values) PetscFunctionReturn(0); 6556b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 65579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 6558b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 6559519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 65609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 6561552f7358SJed Brown #else 65629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 6563552f7358SJed Brown #endif 6564552f7358SJed Brown } 65659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6566552f7358SJed Brown } 6567552f7358SJed Brown PetscFunctionReturn(0); 6568552f7358SJed Brown } 6569552f7358SJed Brown 657005586334SMatthew G. Knepley /* 657105586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 657205586334SMatthew G. Knepley 657305586334SMatthew G. Knepley Input Parameters: 657405586334SMatthew G. Knepley + section - The section for this data layout 657536fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 657605586334SMatthew G. Knepley . point - The point contributing dofs with these indices 657705586334SMatthew G. Knepley . off - The global offset of this point 657805586334SMatthew G. Knepley . loff - The local offset of each field 6579a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 658005586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 658105586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 658205586334SMatthew G. Knepley 658305586334SMatthew G. Knepley Output Parameter: 658405586334SMatthew G. Knepley . indices - Indices for dofs on this point 658505586334SMatthew G. Knepley 658605586334SMatthew G. Knepley Level: developer 658705586334SMatthew G. Knepley 658805586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 658905586334SMatthew G. Knepley */ 65909371c9d4SSatish Balay PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) { 6591e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 6592552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6593552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6594552f7358SJed Brown PetscInt cind = 0, k; 6595552f7358SJed Brown 6596552f7358SJed Brown PetscFunctionBegin; 659708401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 65989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 65999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 6600552f7358SJed Brown if (!cdof || setBC) { 660105586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 660205586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 660305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 660405586334SMatthew G. Knepley 660505586334SMatthew G. Knepley indices[ind] = off + k; 6606552f7358SJed Brown } 6607552f7358SJed Brown } else { 66089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 66094acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 661005586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 661105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 661205586334SMatthew G. Knepley 66134acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 66144acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 661505586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 66164acb8e1eSToby Isaac ++cind; 66174acb8e1eSToby Isaac } else { 661836fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 6619552f7358SJed Brown } 6620552f7358SJed Brown } 6621552f7358SJed Brown } 6622e6ccafaeSMatthew G Knepley *loff += dof; 6623552f7358SJed Brown PetscFunctionReturn(0); 6624552f7358SJed Brown } 6625552f7358SJed Brown 66267e29afd2SMatthew G. Knepley /* 662736fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 66287e29afd2SMatthew G. Knepley 662936fa2b79SJed Brown Input Parameters: 663036fa2b79SJed Brown + section - a section (global or local) 663136fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 663236fa2b79SJed Brown . point - point within section 663336fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 663436fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 663536fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 663636fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 663736fa2b79SJed Brown . permsoff - offset 663836fa2b79SJed Brown - indperm - index permutation 663936fa2b79SJed Brown 664036fa2b79SJed Brown Output Parameter: 664136fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 664236fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 664336fa2b79SJed Brown 664436fa2b79SJed Brown Notes: 664536fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 664636fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 664736fa2b79SJed Brown in the local vector. 664836fa2b79SJed Brown 664936fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 665036fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 665136fa2b79SJed Brown 665236fa2b79SJed Brown Developer Note: 665336fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 665436fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 665536fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 665636fa2b79SJed Brown 665736fa2b79SJed Brown Example: 665836fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 665936fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 666036fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 666136fa2b79SJed 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. 666236fa2b79SJed Brown 666336fa2b79SJed Brown Level: developer 66647e29afd2SMatthew G. Knepley */ 66659371c9d4SSatish Balay 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[]) { 6666552f7358SJed Brown PetscInt numFields, foff, f; 6667552f7358SJed Brown 6668552f7358SJed Brown PetscFunctionBegin; 666908401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 66709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6671552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 66724acb8e1eSToby Isaac PetscInt fdof, cfdof; 6673552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 66744acb8e1eSToby Isaac PetscInt cind = 0, b; 66754acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6676552f7358SJed Brown 66779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 66789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 6679552f7358SJed Brown if (!cfdof || setBC) { 668005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 668105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 668205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 668305586334SMatthew G. Knepley 668405586334SMatthew G. Knepley indices[ind] = off + foff + b; 668505586334SMatthew G. Knepley } 6686552f7358SJed Brown } else { 66879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 668805586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 668905586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 669005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 669105586334SMatthew G. Knepley 66924acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 669305586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 6694552f7358SJed Brown ++cind; 6695552f7358SJed Brown } else { 669636fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 6697552f7358SJed Brown } 6698552f7358SJed Brown } 6699552f7358SJed Brown } 670036fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6701552f7358SJed Brown foffs[f] += fdof; 6702552f7358SJed Brown } 6703552f7358SJed Brown PetscFunctionReturn(0); 6704552f7358SJed Brown } 6705552f7358SJed Brown 67067e29afd2SMatthew G. Knepley /* 67077e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 67087e29afd2SMatthew G. Knepley 67097e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 6710645102dcSJed Brown 6711645102dcSJed Brown Notes: 6712645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6713645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 67147e29afd2SMatthew G. Knepley */ 67159371c9d4SSatish Balay static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) { 67167e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 67177e29afd2SMatthew G. Knepley 67187e29afd2SMatthew G. Knepley PetscFunctionBegin; 67199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 67207e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 67217e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 67227e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67237e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 67247e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 67257e29afd2SMatthew G. Knepley 67269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 67289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 6729645102dcSJed Brown if (!cfdof) { 673005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 673105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 673205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 673305586334SMatthew G. Knepley 673405586334SMatthew G. Knepley indices[ind] = foff + b; 673505586334SMatthew G. Knepley } 67367e29afd2SMatthew G. Knepley } else { 67379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 673805586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 673905586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 674005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 674105586334SMatthew G. Knepley 67427e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 674305586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 67447e29afd2SMatthew G. Knepley ++cind; 67457e29afd2SMatthew G. Knepley } else { 674605586334SMatthew G. Knepley indices[ind] = foff + b - cind; 67477e29afd2SMatthew G. Knepley } 67487e29afd2SMatthew G. Knepley } 67497e29afd2SMatthew G. Knepley } 67507e29afd2SMatthew G. Knepley foffs[f] += fdof; 67517e29afd2SMatthew G. Knepley } 67527e29afd2SMatthew G. Knepley PetscFunctionReturn(0); 67537e29afd2SMatthew G. Knepley } 67547e29afd2SMatthew G. Knepley 67559371c9d4SSatish Balay 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) { 6756d3d1a6afSToby Isaac Mat cMat; 6757d3d1a6afSToby Isaac PetscSection aSec, cSec; 6758d3d1a6afSToby Isaac IS aIS; 6759d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 6760d3d1a6afSToby Isaac const PetscInt *anchors; 6761e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 6762d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 6763d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 6764d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 6765d3d1a6afSToby Isaac PetscInt newOffsets[32]; 6766d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 6767d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 6768d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 67696ecaa68aSToby Isaac PetscScalar *newValues = NULL, *tmpValues; 6770d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 6771d3d1a6afSToby Isaac 6772d3d1a6afSToby Isaac PetscFunctionBegin; 6773d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6774d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 67759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6776d3d1a6afSToby Isaac 67779566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 6778d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 6779d3d1a6afSToby Isaac if (aSec) { 67809566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 67819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 67829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 6783d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 6784d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 6785d3d1a6afSToby Isaac * into the global matrix anyway) */ 6786d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 6787d3d1a6afSToby Isaac PetscInt b = points[p]; 67884b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6789d3d1a6afSToby Isaac 67909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 6791ad540459SPierre Jolivet if (!bSecDof) continue; 679248a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6793d3d1a6afSToby Isaac if (bDof) { 6794d3d1a6afSToby Isaac /* this point is constrained */ 6795d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 6796d3d1a6afSToby Isaac PetscInt bOff, q; 6797d3d1a6afSToby Isaac 6798d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 6799d3d1a6afSToby Isaac newNumPoints += bDof; 68009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6801d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6802d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6803d3d1a6afSToby Isaac PetscInt aDof; 6804d3d1a6afSToby Isaac 68059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 6806d3d1a6afSToby Isaac newNumIndices += aDof; 6807d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6808d3d1a6afSToby Isaac PetscInt fDof; 6809d3d1a6afSToby Isaac 68109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 6811d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 6812d3d1a6afSToby Isaac } 6813d3d1a6afSToby Isaac } 68149371c9d4SSatish Balay } else { 6815d3d1a6afSToby Isaac /* this point is not constrained */ 6816d3d1a6afSToby Isaac newNumPoints++; 68174b2f2278SToby Isaac newNumIndices += bSecDof; 6818d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6819d3d1a6afSToby Isaac PetscInt fDof; 6820d3d1a6afSToby Isaac 68219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6822d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 6823d3d1a6afSToby Isaac } 6824d3d1a6afSToby Isaac } 6825d3d1a6afSToby Isaac } 6826d3d1a6afSToby Isaac } 6827d3d1a6afSToby Isaac if (!anyConstrained) { 682872b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 682972b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 683072b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 683172b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 68329566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 6833d3d1a6afSToby Isaac PetscFunctionReturn(0); 6834d3d1a6afSToby Isaac } 6835d3d1a6afSToby Isaac 68366ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 68376ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 68386ecaa68aSToby Isaac 6839f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 6840d3d1a6afSToby Isaac 68416ecaa68aSToby Isaac if (!outPoints && !outValues) { 68426ecaa68aSToby Isaac if (offsets) { 6843ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 68446ecaa68aSToby Isaac } 68459566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 68466ecaa68aSToby Isaac PetscFunctionReturn(0); 68476ecaa68aSToby Isaac } 68486ecaa68aSToby Isaac 68491dca8a05SBarry 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); 6850d3d1a6afSToby Isaac 68519566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 6852d3d1a6afSToby Isaac 6853d3d1a6afSToby Isaac /* workspaces */ 6854d3d1a6afSToby Isaac if (numFields) { 6855d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 68569566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 68579566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 6858d3d1a6afSToby Isaac } 68599371c9d4SSatish Balay } else { 68609566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 68619566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0])); 6862d3d1a6afSToby Isaac } 6863d3d1a6afSToby Isaac 6864d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 6865d3d1a6afSToby Isaac if (numFields) { 68664b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 68674b2f2278SToby Isaac 6868d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6869d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 68704b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6871d3d1a6afSToby Isaac 68729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 68734b2f2278SToby Isaac if (!bSecDof) { 68744b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 68754b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 68764b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 68774b2f2278SToby Isaac } 68784b2f2278SToby Isaac continue; 68794b2f2278SToby Isaac } 688048a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6881d3d1a6afSToby Isaac if (bDof) { 6882d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6883d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 6884d3d1a6afSToby Isaac 68859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 68869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6887d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6888d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6889d3d1a6afSToby Isaac PetscInt aFDof; 6890d3d1a6afSToby Isaac 68919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 6892d3d1a6afSToby Isaac allFDof += aFDof; 6893d3d1a6afSToby Isaac } 6894d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = allFDof; 6895d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = fDof * allFDof; 6896d3d1a6afSToby Isaac } 68979371c9d4SSatish Balay } else { 6898d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6899d3d1a6afSToby Isaac PetscInt fDof; 6900d3d1a6afSToby Isaac 69019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6902d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = fDof; 6903d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = 0; 6904d3d1a6afSToby Isaac } 6905d3d1a6afSToby Isaac } 6906d3d1a6afSToby Isaac } 69074b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 69084b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 69094b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 6910d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6911d3d1a6afSToby Isaac newPointOffsets[f][p + 1] += newPointOffsets[f][p]; 6912d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] += pointMatOffsets[f][p]; 6913d3d1a6afSToby Isaac } 691419f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 691519f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 69169566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 6917d3d1a6afSToby Isaac } 69189371c9d4SSatish Balay } else { 6919d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6920d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 69214b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6922d3d1a6afSToby Isaac 69239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 69244b2f2278SToby Isaac if (!bSecDof) { 69254b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 69264b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 69274b2f2278SToby Isaac continue; 69284b2f2278SToby Isaac } 692948a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6930d3d1a6afSToby Isaac if (bDof) { 69314b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 6932d3d1a6afSToby Isaac 69339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6934d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6935d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 6936d3d1a6afSToby Isaac 69379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 6938d3d1a6afSToby Isaac allDof += aDof; 6939d3d1a6afSToby Isaac } 6940d3d1a6afSToby Isaac newPointOffsets[0][p + 1] = allDof; 69414b2f2278SToby Isaac pointMatOffsets[0][p + 1] = bSecDof * allDof; 69429371c9d4SSatish Balay } else { 69434b2f2278SToby Isaac newPointOffsets[0][p + 1] = bSecDof; 6944d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] = 0; 6945d3d1a6afSToby Isaac } 6946d3d1a6afSToby Isaac } 6947d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 6948d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 6949d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6950d3d1a6afSToby Isaac newPointOffsets[0][p + 1] += newPointOffsets[0][p]; 6951d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] += pointMatOffsets[0][p]; 6952d3d1a6afSToby Isaac } 69539566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 6954d3d1a6afSToby Isaac } 6955d3d1a6afSToby Isaac 69566ecaa68aSToby Isaac /* output arrays */ 69579566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 69586ecaa68aSToby Isaac 6959d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 69609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 69619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 69629566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices)); 69639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 6964d3d1a6afSToby Isaac if (numFields) { 6965d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 6966d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 6967d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 69684b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6969d3d1a6afSToby Isaac 69709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 6971ad540459SPierre Jolivet if (!bSecDof) continue; 697248a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6973d3d1a6afSToby Isaac if (bDof) { 6974d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6975d3d1a6afSToby Isaac 6976d3d1a6afSToby Isaac fStart[0] = 0; 6977d3d1a6afSToby Isaac fEnd[0] = 0; 6978d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6979d3d1a6afSToby Isaac PetscInt fDof; 6980d3d1a6afSToby Isaac 69819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 6982d3d1a6afSToby Isaac fStart[f + 1] = fStart[f] + fDof; 6983d3d1a6afSToby Isaac fEnd[f + 1] = fStart[f + 1]; 6984d3d1a6afSToby Isaac } 69859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 69869566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 6987d3d1a6afSToby Isaac 6988d3d1a6afSToby Isaac fAnchorStart[0] = 0; 6989d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 6990d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6991d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6992d3d1a6afSToby Isaac 6993d3d1a6afSToby Isaac fAnchorStart[f + 1] = fAnchorStart[f] + fDof; 6994d3d1a6afSToby Isaac fAnchorEnd[f + 1] = fAnchorStart[f + 1]; 6995d3d1a6afSToby Isaac } 69969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6997d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6998d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 6999d3d1a6afSToby Isaac 7000d3d1a6afSToby 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 */ 7001d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7002d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 70039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70049566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7005d3d1a6afSToby Isaac } 7006d3d1a6afSToby Isaac newP += bDof; 7007d3d1a6afSToby Isaac 70086ecaa68aSToby Isaac if (outValues) { 7009d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 701048a46eb9SPierre 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])); 7011d3d1a6afSToby Isaac } 70129371c9d4SSatish Balay } else { 7013d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7014d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7015d3d1a6afSToby Isaac newP++; 7016d3d1a6afSToby Isaac } 7017d3d1a6afSToby Isaac } 7018d3d1a6afSToby Isaac } else { 7019d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7020d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7021d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 70224b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7023d3d1a6afSToby Isaac 70249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7025ad540459SPierre Jolivet if (!bSecDof) continue; 702648a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7027d3d1a6afSToby Isaac if (bDof) { 7028d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7029d3d1a6afSToby Isaac 70309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 70319566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7032d3d1a6afSToby Isaac 70339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7034d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7035d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7036d3d1a6afSToby Isaac 7037d3d1a6afSToby 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 */ 7038d3d1a6afSToby Isaac 7039d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7040d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 70419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70429566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7043d3d1a6afSToby Isaac } 7044d3d1a6afSToby Isaac newP += bDof; 7045d3d1a6afSToby Isaac 7046d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 704748a46eb9SPierre Jolivet if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p])); 70489371c9d4SSatish Balay } else { 7049d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7050d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7051d3d1a6afSToby Isaac newP++; 7052d3d1a6afSToby Isaac } 7053d3d1a6afSToby Isaac } 7054d3d1a6afSToby Isaac } 7055d3d1a6afSToby Isaac 70566ecaa68aSToby Isaac if (outValues) { 70579566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 70589566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices)); 7059d3d1a6afSToby Isaac /* multiply constraints on the right */ 7060d3d1a6afSToby Isaac if (numFields) { 7061d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7062d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7063d3d1a6afSToby Isaac 7064d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7065d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7066d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7067d3d1a6afSToby Isaac PetscInt c, r, k; 7068d3d1a6afSToby Isaac PetscInt dof; 7069d3d1a6afSToby Isaac 70709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7071ad540459SPierre Jolivet if (!dof) continue; 7072d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7073d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p + 1] - cStart; 7074d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7075d3d1a6afSToby Isaac 7076d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7077d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7078ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7079d3d1a6afSToby Isaac } 7080d3d1a6afSToby Isaac } 70819371c9d4SSatish Balay } else { 7082d3d1a6afSToby Isaac /* copy this column as is */ 7083d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7084ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7085d3d1a6afSToby Isaac } 7086d3d1a6afSToby Isaac } 7087d3d1a6afSToby Isaac oldOff += dof; 7088d3d1a6afSToby Isaac } 7089d3d1a6afSToby Isaac } 70909371c9d4SSatish Balay } else { 7091d3d1a6afSToby Isaac PetscInt oldOff = 0; 7092d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7093d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7094d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7095d3d1a6afSToby Isaac PetscInt c, r, k; 7096d3d1a6afSToby Isaac PetscInt dof; 7097d3d1a6afSToby Isaac 70989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7099ad540459SPierre Jolivet if (!dof) continue; 7100d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7101d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p + 1] - cStart; 7102d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7103d3d1a6afSToby Isaac 7104d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7105d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7106ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7107d3d1a6afSToby Isaac } 7108d3d1a6afSToby Isaac } 71099371c9d4SSatish Balay } else { 7110d3d1a6afSToby Isaac /* copy this column as is */ 7111d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7112ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7113d3d1a6afSToby Isaac } 7114d3d1a6afSToby Isaac } 7115d3d1a6afSToby Isaac oldOff += dof; 7116d3d1a6afSToby Isaac } 7117d3d1a6afSToby Isaac } 7118d3d1a6afSToby Isaac 71196ecaa68aSToby Isaac if (multiplyLeft) { 71209566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues)); 71219566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices)); 7122d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7123d3d1a6afSToby Isaac if (numFields) { 7124d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7125d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7126d3d1a6afSToby Isaac 7127d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7128d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7129d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7130d3d1a6afSToby Isaac PetscInt c, r, k; 7131d3d1a6afSToby Isaac PetscInt dof; 7132d3d1a6afSToby Isaac 71339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7134d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7135d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p + 1] - rStart; 7136d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7137d3d1a6afSToby Isaac 7138d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7139d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7140ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7141d3d1a6afSToby Isaac } 7142d3d1a6afSToby Isaac } 71439371c9d4SSatish Balay } else { 7144d3d1a6afSToby Isaac /* copy this row as is */ 7145d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7146ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7147d3d1a6afSToby Isaac } 7148d3d1a6afSToby Isaac } 7149d3d1a6afSToby Isaac oldOff += dof; 7150d3d1a6afSToby Isaac } 7151d3d1a6afSToby Isaac } 71529371c9d4SSatish Balay } else { 7153d3d1a6afSToby Isaac PetscInt oldOff = 0; 7154d3d1a6afSToby Isaac 7155d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7156d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7157d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7158d3d1a6afSToby Isaac PetscInt c, r, k; 7159d3d1a6afSToby Isaac PetscInt dof; 7160d3d1a6afSToby Isaac 71619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7162d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7163d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p + 1] - rStart; 7164d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7165d3d1a6afSToby Isaac 7166d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7167d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7168ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7169d3d1a6afSToby Isaac } 7170d3d1a6afSToby Isaac } 71719371c9d4SSatish Balay } else { 7172d3d1a6afSToby Isaac /* copy this row as is */ 71739fc93327SToby Isaac for (r = 0; r < dof; r++) { 7174ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7175d3d1a6afSToby Isaac } 7176d3d1a6afSToby Isaac } 7177d3d1a6afSToby Isaac oldOff += dof; 7178d3d1a6afSToby Isaac } 7179d3d1a6afSToby Isaac } 7180d3d1a6afSToby Isaac 71819566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 71829371c9d4SSatish Balay } else { 71836ecaa68aSToby Isaac newValues = tmpValues; 71846ecaa68aSToby Isaac } 71856ecaa68aSToby Isaac } 71866ecaa68aSToby Isaac 7187d3d1a6afSToby Isaac /* clean up */ 71889566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices)); 71899566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 71906ecaa68aSToby Isaac 7191d3d1a6afSToby Isaac if (numFields) { 7192d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 71939566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 71949566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 71959566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7196d3d1a6afSToby Isaac } 71979371c9d4SSatish Balay } else { 71989566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 71999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 72009566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0])); 7201d3d1a6afSToby Isaac } 72029566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7203d3d1a6afSToby Isaac 7204d3d1a6afSToby Isaac /* output */ 72056ecaa68aSToby Isaac if (outPoints) { 7206d3d1a6afSToby Isaac *outPoints = newPoints; 72079371c9d4SSatish Balay } else { 72089566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 72096ecaa68aSToby Isaac } 7210ad540459SPierre Jolivet if (outValues) *outValues = newValues; 7211ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 7212d3d1a6afSToby Isaac PetscFunctionReturn(0); 7213d3d1a6afSToby Isaac } 7214d3d1a6afSToby Isaac 72154a1e0b3eSMatthew G. Knepley /*@C 721671f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 72177cd05799SMatthew G. Knepley 72187cd05799SMatthew G. Knepley Not collective 72197cd05799SMatthew G. Knepley 72207cd05799SMatthew G. Knepley Input Parameters: 72217cd05799SMatthew G. Knepley + dm - The DM 722271f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 722371f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 722471f0bbf9SMatthew G. Knepley . point - The point defining the closure 722571f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 72267cd05799SMatthew G. Knepley 722771f0bbf9SMatthew G. Knepley Output Parameters: 722871f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 722971f0bbf9SMatthew G. Knepley . indices - The dof indices 723071f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 723171f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 72327cd05799SMatthew G. Knepley 723336fa2b79SJed Brown Notes: 723436fa2b79SJed Brown Must call DMPlexRestoreClosureIndices() to free allocated memory 723536fa2b79SJed Brown 723636fa2b79SJed Brown If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 723736fa2b79SJed Brown of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 723836fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 723936fa2b79SJed Brown indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 724036fa2b79SJed Brown indices (with the above semantics) are implied. 72417cd05799SMatthew G. Knepley 72427cd05799SMatthew G. Knepley Level: advanced 72437cd05799SMatthew G. Knepley 7244db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 72454a1e0b3eSMatthew G. Knepley @*/ 72469371c9d4SSatish Balay PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) { 724771f0bbf9SMatthew G. Knepley /* Closure ordering */ 72487773e69fSMatthew G. Knepley PetscSection clSection; 72497773e69fSMatthew G. Knepley IS clPoints; 725071f0bbf9SMatthew G. Knepley const PetscInt *clp; 725171f0bbf9SMatthew G. Knepley PetscInt *points; 725271f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 725371f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 72544acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 725571f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 725671f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 725771f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 725871f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 725971f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 726071f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 726171f0bbf9SMatthew G. Knepley 726271f0bbf9SMatthew G. Knepley PetscInt *idx; 726371f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 726471f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 72657773e69fSMatthew G. Knepley 726671f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 72677773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 72687773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 726936fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7270dadcf809SJacob Faibussowitsch if (numIndices) PetscValidIntPointer(numIndices, 6); 727171f0bbf9SMatthew G. Knepley if (indices) PetscValidPointer(indices, 7); 7272dadcf809SJacob Faibussowitsch if (outOffsets) PetscValidIntPointer(outOffsets, 8); 727371f0bbf9SMatthew G. Knepley if (values) PetscValidPointer(values, 9); 72749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 727563a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 72769566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 727771f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 72789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7279c459fbc1SJed Brown if (useClPerm) { 7280c459fbc1SJed Brown PetscInt depth, clsize; 72819566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7282c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7283c459fbc1SJed Brown PetscInt dof; 72849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7285c459fbc1SJed Brown clsize += dof; 7286c459fbc1SJed Brown } 72879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7288c459fbc1SJed Brown } 728971f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 729071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 72917773e69fSMatthew G. Knepley PetscInt dof, fdof; 72927773e69fSMatthew G. Knepley 72939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 72947773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 72959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 72967773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 72977773e69fSMatthew G. Knepley } 729871f0bbf9SMatthew G. Knepley Ni += dof; 72997773e69fSMatthew G. Knepley } 73007773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 73011dca8a05SBarry 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); 730271f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 730371f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73049566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73059566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 730671f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 730771f0bbf9SMatthew G. Knepley if (values && flips[f]) { 730871f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 73096ecaa68aSToby Isaac 731071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 731171f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 731271f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 731371f0bbf9SMatthew G. Knepley 73149566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 73159566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 731671f0bbf9SMatthew G. Knepley if (flip) { 731771f0bbf9SMatthew G. Knepley PetscInt i, j, k; 731871f0bbf9SMatthew G. Knepley 731971f0bbf9SMatthew G. Knepley if (!valCopy) { 73209566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 732171f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 732271f0bbf9SMatthew G. Knepley *values = valCopy; 732371f0bbf9SMatthew G. Knepley } 732471f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 732571f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 732671f0bbf9SMatthew G. Knepley 732771f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 732871f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 732971f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 73306ecaa68aSToby Isaac } 73316ecaa68aSToby Isaac } 733271f0bbf9SMatthew G. Knepley } 733371f0bbf9SMatthew G. Knepley foffset += fdof; 733471f0bbf9SMatthew G. Knepley } 733571f0bbf9SMatthew G. Knepley } 733671f0bbf9SMatthew G. Knepley } 733771f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 73389566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 733971f0bbf9SMatthew G. Knepley if (NclC) { 73409566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 734171f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73429566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73439566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 734471f0bbf9SMatthew G. Knepley } 734571f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73469566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 73479566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 734871f0bbf9SMatthew G. Knepley } 73499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 735071f0bbf9SMatthew G. Knepley Ncl = NclC; 735171f0bbf9SMatthew G. Knepley Ni = NiC; 735271f0bbf9SMatthew G. Knepley points = pointsC; 735371f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 735471f0bbf9SMatthew G. Knepley } 735571f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 73569566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 735771f0bbf9SMatthew G. Knepley if (Nf) { 735871f0bbf9SMatthew G. Knepley PetscInt idxOff; 735971f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 736071f0bbf9SMatthew G. Knepley 73619371c9d4SSatish Balay if (outOffsets) { 73629371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 73639371c9d4SSatish Balay } 73649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 736571f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 736671f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 736771f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 736871f0bbf9SMatthew G. Knepley 73699566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 73707773e69fSMatthew G. Knepley } 73717773e69fSMatthew G. Knepley } else { 737271f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 737371f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 737471f0bbf9SMatthew G. Knepley 73759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 737671f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 737771f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 737871f0bbf9SMatthew G. Knepley * global section. */ 73799566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 738071f0bbf9SMatthew G. Knepley } 738171f0bbf9SMatthew G. Knepley } 738271f0bbf9SMatthew G. Knepley } else { 738371f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 738471f0bbf9SMatthew G. Knepley 738571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 738671f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 73874acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 73884acb8e1eSToby Isaac 73899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 739071f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 739171f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 73929566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 73937773e69fSMatthew G. Knepley } 73947773e69fSMatthew G. Knepley } 739571f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 739671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73979566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73989566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 73994acb8e1eSToby Isaac } 740071f0bbf9SMatthew G. Knepley if (NclC) { 74019566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 74027773e69fSMatthew G. Knepley } else { 74039566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 74047773e69fSMatthew G. Knepley } 740571f0bbf9SMatthew G. Knepley 740671f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 740771f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 74087773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74097773e69fSMatthew G. Knepley } 74107773e69fSMatthew G. Knepley 74117cd05799SMatthew G. Knepley /*@C 741271f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 74137cd05799SMatthew G. Knepley 74147cd05799SMatthew G. Knepley Not collective 74157cd05799SMatthew G. Knepley 74167cd05799SMatthew G. Knepley Input Parameters: 74177cd05799SMatthew G. Knepley + dm - The DM 741871f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 741971f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 742071f0bbf9SMatthew G. Knepley . point - The point defining the closure 742171f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 742271f0bbf9SMatthew G. Knepley 742371f0bbf9SMatthew G. Knepley Output Parameters: 742471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 742571f0bbf9SMatthew G. Knepley . indices - The dof indices 742671f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 742771f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 742871f0bbf9SMatthew G. Knepley 742971f0bbf9SMatthew G. Knepley Notes: 743071f0bbf9SMatthew G. Knepley If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 743171f0bbf9SMatthew G. Knepley 743271f0bbf9SMatthew G. Knepley If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 743371f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 743471f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 743571f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 743671f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 74377cd05799SMatthew G. Knepley 74387cd05799SMatthew G. Knepley Level: advanced 74397cd05799SMatthew G. Knepley 7440db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 74417cd05799SMatthew G. Knepley @*/ 74429371c9d4SSatish Balay PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) { 74437773e69fSMatthew G. Knepley PetscFunctionBegin; 74447773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7445064a246eSJacob Faibussowitsch PetscValidPointer(indices, 7); 74469566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 74477773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74487773e69fSMatthew G. Knepley } 74497773e69fSMatthew G. Knepley 74507f5d1fdeSMatthew G. Knepley /*@C 74517f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 74527f5d1fdeSMatthew G. Knepley 74537f5d1fdeSMatthew G. Knepley Not collective 74547f5d1fdeSMatthew G. Knepley 74557f5d1fdeSMatthew G. Knepley Input Parameters: 74567f5d1fdeSMatthew G. Knepley + dm - The DM 7457ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section 7458ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section 74597f5d1fdeSMatthew G. Knepley . A - The matrix 7460eaf898f9SPatrick Sanan . point - The point in the DM 74617f5d1fdeSMatthew G. Knepley . values - The array of values 74627f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 74637f5d1fdeSMatthew G. Knepley 74647f5d1fdeSMatthew G. Knepley Fortran Notes: 74657f5d1fdeSMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 74667f5d1fdeSMatthew G. Knepley 74677f5d1fdeSMatthew G. Knepley Level: intermediate 74687f5d1fdeSMatthew G. Knepley 7469db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 74707f5d1fdeSMatthew G. Knepley @*/ 74719371c9d4SSatish Balay PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) { 7472552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 7473552f7358SJed Brown PetscInt *indices; 747471f0bbf9SMatthew G. Knepley PetscInt numIndices; 747571f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 7476552f7358SJed Brown PetscErrorCode ierr; 7477552f7358SJed Brown 7478552f7358SJed Brown PetscFunctionBegin; 7479552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 74809566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 74813dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 74829566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 74833dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 74843dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7485552f7358SJed Brown 74869566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 74870d644c17SKarl Rupp 74889566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 7489d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 74904a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7491552f7358SJed Brown if (ierr) { 7492552f7358SJed Brown PetscMPIInt rank; 7493552f7358SJed Brown 74949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 74959566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 74969566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 74979566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 74989566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 7499c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 7500552f7358SJed Brown } 75014a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 75024a1e0b3eSMatthew G. Knepley PetscInt i; 75039566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 750463a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 75059566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 75064a1e0b3eSMatthew G. Knepley } 750771f0bbf9SMatthew G. Knepley 75089566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 75099566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 751071f0bbf9SMatthew G. Knepley PetscFunctionReturn(0); 75114acb8e1eSToby Isaac } 751271f0bbf9SMatthew G. Knepley 75134a1e0b3eSMatthew G. Knepley /*@C 75144a1e0b3eSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 75154a1e0b3eSMatthew G. Knepley 75164a1e0b3eSMatthew G. Knepley Not collective 75174a1e0b3eSMatthew G. Knepley 75184a1e0b3eSMatthew G. Knepley Input Parameters: 75194a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields 75204a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 75214a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 75224a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields 75234a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 75244a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 75254a1e0b3eSMatthew G. Knepley . A - The matrix 75264a1e0b3eSMatthew G. Knepley . point - The point in the DMs 75274a1e0b3eSMatthew G. Knepley . values - The array of values 75284a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75294a1e0b3eSMatthew G. Knepley 75304a1e0b3eSMatthew G. Knepley Level: intermediate 75314a1e0b3eSMatthew G. Knepley 7532db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 75334a1e0b3eSMatthew G. Knepley @*/ 75349371c9d4SSatish Balay PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) { 753571f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 753671f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 753771f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 753871f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 753971f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 754071f0bbf9SMatthew G. Knepley 754171f0bbf9SMatthew G. Knepley PetscFunctionBegin; 754271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 75439566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 754471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 75459566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 754671f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 754771f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 75489566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 754971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 75509566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 755171f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 755271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 755371f0bbf9SMatthew G. Knepley 75549566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 75559566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 755671f0bbf9SMatthew G. Knepley 75579566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 7558d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 75594a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 756071f0bbf9SMatthew G. Knepley if (ierr) { 756171f0bbf9SMatthew G. Knepley PetscMPIInt rank; 756271f0bbf9SMatthew G. Knepley 75639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 75649566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 75659566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 75669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 75679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values)); 75689566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7569d3d1a6afSToby Isaac } 757071f0bbf9SMatthew G. Knepley 75719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 75729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 75739566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7574552f7358SJed Brown PetscFunctionReturn(0); 7575552f7358SJed Brown } 7576552f7358SJed Brown 75779371c9d4SSatish Balay PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) { 7578de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 7579de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 7580de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 7581de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 758217c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7583de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 7584412e9a14SMatthew G. Knepley DMPolytopeType ct; 75854ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7586de41b84cSMatthew G. Knepley PetscErrorCode ierr; 7587de41b84cSMatthew G. Knepley 7588de41b84cSMatthew G. Knepley PetscFunctionBegin; 7589de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7590de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 75919566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 7592de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 75939566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 7594de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 75959566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 7596de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 75979566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 7598de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7599de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 76009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 760163a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 76029566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 76039566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 7604de41b84cSMatthew G. Knepley /* Column indices */ 76059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 76064ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 7607de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 7608de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 76099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 7610de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 7611de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7612de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 7613de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 7614de41b84cSMatthew G. Knepley ++q; 7615de41b84cSMatthew G. Knepley } 7616de41b84cSMatthew G. Knepley } 7617de41b84cSMatthew G. Knepley numCPoints = q; 7618de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 7619de41b84cSMatthew G. Knepley PetscInt fdof; 7620de41b84cSMatthew G. Knepley 76219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 76224ca5e9f5SMatthew G. Knepley if (!dof) continue; 7623de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 76249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 7625de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 7626de41b84cSMatthew G. Knepley } 7627de41b84cSMatthew G. Knepley numCIndices += dof; 7628de41b84cSMatthew G. Knepley } 7629de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 7630de41b84cSMatthew G. Knepley /* Row indices */ 76319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7632412e9a14SMatthew G. Knepley { 7633012bc364SMatthew G. Knepley DMPlexTransform tr; 7634012bc364SMatthew G. Knepley DMPolytopeType *rct; 7635012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7636012bc364SMatthew G. Knepley 76379566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 76389566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 76399566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7640012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 76419566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7642412e9a14SMatthew G. Knepley } 76439566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 7644de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 7645de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 76469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 7647de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 76489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 7649de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 7650de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 76519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 76524ca5e9f5SMatthew G. Knepley if (!dof) continue; 76539371c9d4SSatish Balay for (s = 0; s < q; ++s) 76549371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 76554ca5e9f5SMatthew G. Knepley if (s < q) continue; 7656de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 7657de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 7658de41b84cSMatthew G. Knepley ++q; 7659de41b84cSMatthew G. Knepley } 7660de41b84cSMatthew G. Knepley } 76619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 7662de41b84cSMatthew G. Knepley } 7663de41b84cSMatthew G. Knepley numFPoints = q; 7664de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 7665de41b84cSMatthew G. Knepley PetscInt fdof; 7666de41b84cSMatthew G. Knepley 76679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 76684ca5e9f5SMatthew G. Knepley if (!dof) continue; 7669de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 76709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 7671de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 7672de41b84cSMatthew G. Knepley } 7673de41b84cSMatthew G. Knepley numFIndices += dof; 7674de41b84cSMatthew G. Knepley } 7675de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 7676de41b84cSMatthew G. Knepley 76771dca8a05SBarry 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); 76781dca8a05SBarry 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); 76799566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 76809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7681de41b84cSMatthew G. Knepley if (numFields) { 76824acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 76834acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 76844acb8e1eSToby Isaac 76854acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 76869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 76879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 7688de41b84cSMatthew G. Knepley } 76894acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 76909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 76919566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 76924acb8e1eSToby Isaac } 76934acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 76949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 76959566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 76964acb8e1eSToby Isaac } 76974acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 76989566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 76999566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 7700de41b84cSMatthew G. Knepley } 7701de41b84cSMatthew G. Knepley } else { 77024acb8e1eSToby Isaac const PetscInt **permsF = NULL; 77034acb8e1eSToby Isaac const PetscInt **permsC = NULL; 77044acb8e1eSToby Isaac 77059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 77069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 77074acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 77084acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 77094acb8e1eSToby Isaac 77109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 77119566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 7712de41b84cSMatthew G. Knepley } 77134acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 77144acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 77154acb8e1eSToby Isaac 77169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 77179566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 7718de41b84cSMatthew G. Knepley } 77199566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 77209566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 7721de41b84cSMatthew G. Knepley } 77229566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77234acb8e1eSToby Isaac /* TODO: flips */ 7724d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 7725de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7726de41b84cSMatthew G. Knepley if (ierr) { 7727de41b84cSMatthew G. Knepley PetscMPIInt rank; 7728de41b84cSMatthew G. Knepley 77299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 77309566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 77319566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77339566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7734de41b84cSMatthew G. Knepley } 77359566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 77369566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 77379566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77389566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7739de41b84cSMatthew G. Knepley PetscFunctionReturn(0); 7740de41b84cSMatthew G. Knepley } 7741de41b84cSMatthew G. Knepley 77429371c9d4SSatish Balay PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) { 77437c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 77447c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 77457c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 774617c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7747412e9a14SMatthew G. Knepley DMPolytopeType ct; 77487c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 77497c927364SMatthew G. Knepley 77507c927364SMatthew G. Knepley PetscFunctionBegin; 77517c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 77527c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 77539566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 77547c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 77559566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 77567c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 77579566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 77587c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 77599566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 77607c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 77619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 776263a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 77639566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 77649566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 77657c927364SMatthew G. Knepley /* Column indices */ 77669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 77677c927364SMatthew G. Knepley maxFPoints = numCPoints; 77687c927364SMatthew G. Knepley /* Compress out points not in the section */ 77697c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 77709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 77717c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 77727c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 77737c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 77747c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 77757c927364SMatthew G. Knepley ++q; 77767c927364SMatthew G. Knepley } 77777c927364SMatthew G. Knepley } 77787c927364SMatthew G. Knepley numCPoints = q; 77797c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 77807c927364SMatthew G. Knepley PetscInt fdof; 77817c927364SMatthew G. Knepley 77829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 77837c927364SMatthew G. Knepley if (!dof) continue; 77847c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 77859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 77867c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 77877c927364SMatthew G. Knepley } 77887c927364SMatthew G. Knepley numCIndices += dof; 77897c927364SMatthew G. Knepley } 77907c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 77917c927364SMatthew G. Knepley /* Row indices */ 77929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7793412e9a14SMatthew G. Knepley { 7794012bc364SMatthew G. Knepley DMPlexTransform tr; 7795012bc364SMatthew G. Knepley DMPolytopeType *rct; 7796012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7797012bc364SMatthew G. Knepley 77989566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 77999566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 78009566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7801012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 78029566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7803412e9a14SMatthew G. Knepley } 78049566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 78057c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 78067c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 78079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 78087c927364SMatthew G. Knepley /* Compress out points not in the section */ 78099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 78107c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 78117c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 78129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 78137c927364SMatthew G. Knepley if (!dof) continue; 78149371c9d4SSatish Balay for (s = 0; s < q; ++s) 78159371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 78167c927364SMatthew G. Knepley if (s < q) continue; 78177c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 78187c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 78197c927364SMatthew G. Knepley ++q; 78207c927364SMatthew G. Knepley } 78217c927364SMatthew G. Knepley } 78229566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 78237c927364SMatthew G. Knepley } 78247c927364SMatthew G. Knepley numFPoints = q; 78257c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 78267c927364SMatthew G. Knepley PetscInt fdof; 78277c927364SMatthew G. Knepley 78289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 78297c927364SMatthew G. Knepley if (!dof) continue; 78307c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 78327c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 78337c927364SMatthew G. Knepley } 78347c927364SMatthew G. Knepley numFIndices += dof; 78357c927364SMatthew G. Knepley } 78367c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 78377c927364SMatthew G. Knepley 78381dca8a05SBarry 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); 78391dca8a05SBarry 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); 78407c927364SMatthew G. Knepley if (numFields) { 78414acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 78424acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 78434acb8e1eSToby Isaac 78444acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 78459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 78469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 78477c927364SMatthew G. Knepley } 78484acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 78499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 78509566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 78514acb8e1eSToby Isaac } 78524acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 78539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 78549566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 78554acb8e1eSToby Isaac } 78564acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 78579566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 78589566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 78597c927364SMatthew G. Knepley } 78607c927364SMatthew G. Knepley } else { 78614acb8e1eSToby Isaac const PetscInt **permsF = NULL; 78624acb8e1eSToby Isaac const PetscInt **permsC = NULL; 78634acb8e1eSToby Isaac 78649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 78659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 78664acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 78674acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 78684acb8e1eSToby Isaac 78699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 78709566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 78717c927364SMatthew G. Knepley } 78724acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 78734acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 78744acb8e1eSToby Isaac 78759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 78769566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 78777c927364SMatthew G. Knepley } 78789566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 78799566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 78807c927364SMatthew G. Knepley } 78819566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 78829566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78837c927364SMatthew G. Knepley PetscFunctionReturn(0); 78847c927364SMatthew G. Knepley } 78857c927364SMatthew G. Knepley 78867cd05799SMatthew G. Knepley /*@C 78877cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 78887cd05799SMatthew G. Knepley 78897cd05799SMatthew G. Knepley Input Parameter: 78907cd05799SMatthew G. Knepley . dm - The DMPlex object 78917cd05799SMatthew G. Knepley 78927cd05799SMatthew G. Knepley Output Parameter: 78937cd05799SMatthew G. Knepley . cellHeight - The height of a cell 78947cd05799SMatthew G. Knepley 78957cd05799SMatthew G. Knepley Level: developer 78967cd05799SMatthew G. Knepley 7897db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()` 78987cd05799SMatthew G. Knepley @*/ 78999371c9d4SSatish Balay PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) { 7900552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 7901552f7358SJed Brown 7902552f7358SJed Brown PetscFunctionBegin; 7903552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7904dadcf809SJacob Faibussowitsch PetscValidIntPointer(cellHeight, 2); 7905552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 7906552f7358SJed Brown PetscFunctionReturn(0); 7907552f7358SJed Brown } 7908552f7358SJed Brown 79097cd05799SMatthew G. Knepley /*@C 79107cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 79117cd05799SMatthew G. Knepley 79127cd05799SMatthew G. Knepley Input Parameters: 79137cd05799SMatthew G. Knepley + dm - The DMPlex object 79147cd05799SMatthew G. Knepley - cellHeight - The height of a cell 79157cd05799SMatthew G. Knepley 79167cd05799SMatthew G. Knepley Level: developer 79177cd05799SMatthew G. Knepley 7918db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()` 79197cd05799SMatthew G. Knepley @*/ 79209371c9d4SSatish Balay PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) { 7921552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 7922552f7358SJed Brown 7923552f7358SJed Brown PetscFunctionBegin; 7924552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7925552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 7926552f7358SJed Brown PetscFunctionReturn(0); 7927552f7358SJed Brown } 7928552f7358SJed Brown 7929e6139122SMatthew G. Knepley /*@ 7930e6139122SMatthew G. Knepley DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7931e6139122SMatthew G. Knepley 7932e6139122SMatthew G. Knepley Input Parameter: 7933e6139122SMatthew G. Knepley . dm - The DMPlex object 7934e6139122SMatthew G. Knepley 7935e6139122SMatthew G. Knepley Output Parameters: 79362a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL 79372a9f31c0SMatthew G. Knepley - gcEnd - The upper bound on ghost cells, or NULL 7938e6139122SMatthew G. Knepley 79392a9f31c0SMatthew G. Knepley Level: advanced 7940e6139122SMatthew G. Knepley 7941db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 7942e6139122SMatthew G. Knepley @*/ 79439371c9d4SSatish Balay PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) { 7944412e9a14SMatthew G. Knepley DMLabel ctLabel; 7945e6139122SMatthew G. Knepley 7946e6139122SMatthew G. Knepley PetscFunctionBegin; 7947e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 79489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 79499566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd)); 7950695799ffSMatthew G. Knepley // Reset label for fast lookup 7951695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 7952e6139122SMatthew G. Knepley PetscFunctionReturn(0); 7953e6139122SMatthew G. Knepley } 7954e6139122SMatthew G. Knepley 79559371c9d4SSatish Balay PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) { 7956552f7358SJed Brown PetscSection section, globalSection; 7957552f7358SJed Brown PetscInt *numbers, p; 7958552f7358SJed Brown 7959552f7358SJed Brown PetscFunctionBegin; 7960d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 79619566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 79629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 796348a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 79649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 79659566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 79669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 7967552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 79689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 7969ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 7970ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 7971552f7358SJed Brown } 79729566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 7973ef48cebcSMatthew G. Knepley if (globalSize) { 7974ef48cebcSMatthew G. Knepley PetscLayout layout; 79759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 79769566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 79779566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 7978ef48cebcSMatthew G. Knepley } 79799566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 79809566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 7981552f7358SJed Brown PetscFunctionReturn(0); 7982552f7358SJed Brown } 7983552f7358SJed Brown 79849371c9d4SSatish Balay PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) { 7985412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 7986552f7358SJed Brown 7987552f7358SJed Brown PetscFunctionBegin; 79889566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 79899566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 79909566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 79919566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 799281ed3555SMatthew G. Knepley PetscFunctionReturn(0); 7993552f7358SJed Brown } 799481ed3555SMatthew G. Knepley 79958dab3259SMatthew G. Knepley /*@ 79967cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 79977cd05799SMatthew G. Knepley 79987cd05799SMatthew G. Knepley Input Parameter: 79997cd05799SMatthew G. Knepley . dm - The DMPlex object 80007cd05799SMatthew G. Knepley 80017cd05799SMatthew G. Knepley Output Parameter: 80027cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 80037cd05799SMatthew G. Knepley 80047cd05799SMatthew G. Knepley Level: developer 80057cd05799SMatthew G. Knepley 8006db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()` 80077cd05799SMatthew G. Knepley @*/ 80089371c9d4SSatish Balay PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) { 800981ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 801081ed3555SMatthew G. Knepley 801181ed3555SMatthew G. Knepley PetscFunctionBegin; 801281ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80139566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8014552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 8015552f7358SJed Brown PetscFunctionReturn(0); 8016552f7358SJed Brown } 8017552f7358SJed Brown 80189371c9d4SSatish Balay PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) { 8019412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 802081ed3555SMatthew G. Knepley 802181ed3555SMatthew G. Knepley PetscFunctionBegin; 802281ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80239566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 80249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 802581ed3555SMatthew G. Knepley PetscFunctionReturn(0); 802681ed3555SMatthew G. Knepley } 802781ed3555SMatthew G. Knepley 80288dab3259SMatthew G. Knepley /*@ 80296aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 80307cd05799SMatthew G. Knepley 80317cd05799SMatthew G. Knepley Input Parameter: 80327cd05799SMatthew G. Knepley . dm - The DMPlex object 80337cd05799SMatthew G. Knepley 80347cd05799SMatthew G. Knepley Output Parameter: 80357cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 80367cd05799SMatthew G. Knepley 80377cd05799SMatthew G. Knepley Level: developer 80387cd05799SMatthew G. Knepley 8039db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 80407cd05799SMatthew G. Knepley @*/ 80419371c9d4SSatish Balay PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) { 8042552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8043552f7358SJed Brown 8044552f7358SJed Brown PetscFunctionBegin; 8045552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80469566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8047552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 8048552f7358SJed Brown PetscFunctionReturn(0); 8049552f7358SJed Brown } 8050552f7358SJed Brown 80518dab3259SMatthew G. Knepley /*@ 8052966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8053966484cfSJed Brown 8054966484cfSJed Brown Collective on dm 80557cd05799SMatthew G. Knepley 80567cd05799SMatthew G. Knepley Input Parameter: 80577cd05799SMatthew G. Knepley . dm - The DMPlex object 80587cd05799SMatthew G. Knepley 80597cd05799SMatthew G. Knepley Output Parameter: 80607cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 80617cd05799SMatthew G. Knepley 8062966484cfSJed Brown Notes: 8063966484cfSJed Brown 8064966484cfSJed Brown The point numbering IS is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8065966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8066966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8067966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8068966484cfSJed Brown 8069966484cfSJed Brown The partitioned mesh is 8070966484cfSJed Brown ``` 8071966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8072966484cfSJed Brown ``` 8073966484cfSJed Brown and its global numbering is 8074966484cfSJed Brown ``` 8075966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8076966484cfSJed Brown ``` 8077966484cfSJed Brown Then the global numbering is provided as 8078966484cfSJed Brown ``` 8079966484cfSJed Brown [0] Number of indices in set 5 8080966484cfSJed Brown [0] 0 0 8081966484cfSJed Brown [0] 1 1 8082966484cfSJed Brown [0] 2 3 8083966484cfSJed Brown [0] 3 4 8084966484cfSJed Brown [0] 4 -6 8085966484cfSJed Brown [1] Number of indices in set 3 8086966484cfSJed Brown [1] 0 2 8087966484cfSJed Brown [1] 1 5 8088966484cfSJed Brown [1] 2 6 8089966484cfSJed Brown ``` 8090966484cfSJed Brown 80917cd05799SMatthew G. Knepley Level: developer 80927cd05799SMatthew G. Knepley 8093db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 80947cd05799SMatthew G. Knepley @*/ 80959371c9d4SSatish Balay PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) { 8096ef48cebcSMatthew G. Knepley IS nums[4]; 8097862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8098ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 80990c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8100ef48cebcSMatthew G. Knepley 8101ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8102ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81039566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 81040c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 81059566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 81060c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8107862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8108862913ffSStefano Zampini PetscInt end; 8109862913ffSStefano Zampini 8110862913ffSStefano Zampini depths[d] = depth - d; 81119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 81120c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8113862913ffSStefano Zampini } 81140c15888dSMatthew G. Knepley if (empty) 81150c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 81160c15888dSMatthew G. Knepley depths[d] = -1; 81170c15888dSMatthew G. Knepley starts[d] = -1; 81180c15888dSMatthew G. Knepley } 81190c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 81201c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8121ad540459SPierre 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]); 81220c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8123ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8124ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8125ef48cebcSMatthew G. Knepley 81269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 81279566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8128ef48cebcSMatthew G. Knepley shift += gsize; 8129ef48cebcSMatthew G. Knepley } 81309566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)dm), depth + 1, nums, globalPointNumbers)); 81319566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 8132ef48cebcSMatthew G. Knepley PetscFunctionReturn(0); 8133ef48cebcSMatthew G. Knepley } 8134ef48cebcSMatthew G. Knepley 813508a22f4bSMatthew G. Knepley /*@ 813608a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 813708a22f4bSMatthew G. Knepley 813808a22f4bSMatthew G. Knepley Input Parameter: 813908a22f4bSMatthew G. Knepley . dm - The DMPlex object 814008a22f4bSMatthew G. Knepley 814108a22f4bSMatthew G. Knepley Output Parameter: 814208a22f4bSMatthew G. Knepley . ranks - The rank field 814308a22f4bSMatthew G. Knepley 814408a22f4bSMatthew G. Knepley Options Database Keys: 814508a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 814608a22f4bSMatthew G. Knepley 814708a22f4bSMatthew G. Knepley Level: intermediate 814808a22f4bSMatthew G. Knepley 8149db781477SPatrick Sanan .seealso: `DMView()` 815008a22f4bSMatthew G. Knepley @*/ 81519371c9d4SSatish Balay PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) { 815208a22f4bSMatthew G. Knepley DM rdm; 815308a22f4bSMatthew G. Knepley PetscFE fe; 815408a22f4bSMatthew G. Knepley PetscScalar *r; 815508a22f4bSMatthew G. Knepley PetscMPIInt rank; 8156a55f9a55SMatthew G. Knepley DMPolytopeType ct; 815708a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8158a55f9a55SMatthew G. Knepley PetscBool simplex; 815908a22f4bSMatthew G. Knepley 816008a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8161f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8162f95ace6aSMatthew G. Knepley PetscValidPointer(ranks, 2); 81639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 81649566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 81659566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 81669566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 81679566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8168a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 81699566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 81709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 81719566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 81729566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 81739566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 81749566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 81759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 81769566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 817708a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 817808a22f4bSMatthew G. Knepley PetscScalar *lr; 817908a22f4bSMatthew G. Knepley 81809566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 818171f09efeSPierre Jolivet if (lr) *lr = rank; 818208a22f4bSMatthew G. Knepley } 81839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 81849566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 818508a22f4bSMatthew G. Knepley PetscFunctionReturn(0); 818608a22f4bSMatthew G. Knepley } 818708a22f4bSMatthew G. Knepley 8188ca8062c8SMatthew G. Knepley /*@ 818918e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 819018e14f0cSMatthew G. Knepley 819118e14f0cSMatthew G. Knepley Input Parameters: 819218e14f0cSMatthew G. Knepley + dm - The DMPlex 819318e14f0cSMatthew G. Knepley - label - The DMLabel 819418e14f0cSMatthew G. Knepley 819518e14f0cSMatthew G. Knepley Output Parameter: 819618e14f0cSMatthew G. Knepley . val - The label value field 819718e14f0cSMatthew G. Knepley 819818e14f0cSMatthew G. Knepley Options Database Keys: 819918e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 820018e14f0cSMatthew G. Knepley 820118e14f0cSMatthew G. Knepley Level: intermediate 820218e14f0cSMatthew G. Knepley 8203db781477SPatrick Sanan .seealso: `DMView()` 820418e14f0cSMatthew G. Knepley @*/ 82059371c9d4SSatish Balay PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) { 820618e14f0cSMatthew G. Knepley DM rdm; 820718e14f0cSMatthew G. Knepley PetscFE fe; 820818e14f0cSMatthew G. Knepley PetscScalar *v; 820918e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 821018e14f0cSMatthew G. Knepley 821118e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 821218e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 821318e14f0cSMatthew G. Knepley PetscValidPointer(label, 2); 821418e14f0cSMatthew G. Knepley PetscValidPointer(val, 3); 82159566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 82169566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 82179566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 82189566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "label_value")); 82199566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 82209566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 82219566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 82229566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82239566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 82249566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*val, "label_value")); 82259566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 822618e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 822718e14f0cSMatthew G. Knepley PetscScalar *lv; 822818e14f0cSMatthew G. Knepley PetscInt cval; 822918e14f0cSMatthew G. Knepley 82309566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 82319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 823218e14f0cSMatthew G. Knepley *lv = cval; 823318e14f0cSMatthew G. Knepley } 82349566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 82359566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 823618e14f0cSMatthew G. Knepley PetscFunctionReturn(0); 823718e14f0cSMatthew G. Knepley } 823818e14f0cSMatthew G. Knepley 823918e14f0cSMatthew G. Knepley /*@ 8240ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8241ca8062c8SMatthew G. Knepley 824269916449SMatthew G. Knepley Input Parameter: 824369916449SMatthew G. Knepley . dm - The DMPlex object 8244ca8062c8SMatthew G. Knepley 824595eb5ee5SVaclav Hapla Notes: 824695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 824795eb5ee5SVaclav Hapla 824895eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8249ca8062c8SMatthew G. Knepley 8250ca8062c8SMatthew G. Knepley Level: developer 8251ca8062c8SMatthew G. Knepley 8252db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8253ca8062c8SMatthew G. Knepley @*/ 82549371c9d4SSatish Balay PetscErrorCode DMPlexCheckSymmetry(DM dm) { 8255ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8256ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8257ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 825857beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 825957beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8260ca8062c8SMatthew G. Knepley 8261ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8262ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 82639566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 82649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 82659566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8266ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 82679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8268ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 82699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 82709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8271ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 827242e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 827342e66dfaSMatthew G. Knepley PetscInt d; 827442e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 82759371c9d4SSatish Balay if (cone[c] == cone[d]) { 82769371c9d4SSatish Balay dup = PETSC_TRUE; 82779371c9d4SSatish Balay break; 82789371c9d4SSatish Balay } 827942e66dfaSMatthew G. Knepley } 82809566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 82819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8282ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8283ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8284ca8062c8SMatthew G. Knepley } 828542e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 828663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 828748a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 82889566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 828963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 829048a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 82919566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 829263a3b9bcSJacob 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]); 8293f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8294ca8062c8SMatthew G. Knepley } 829542e66dfaSMatthew G. Knepley } 82969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 82979371c9d4SSatish Balay if (p != pp) { 82989371c9d4SSatish Balay storagecheck = PETSC_FALSE; 82999371c9d4SSatish Balay continue; 83009371c9d4SSatish Balay } 83019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 83029566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8303ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 83049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 83059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8306ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 83079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 83089371c9d4SSatish Balay if (cone[c] != pp) { 83099371c9d4SSatish Balay c = 0; 83109371c9d4SSatish Balay break; 83119371c9d4SSatish Balay } 8312ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8313ca8062c8SMatthew G. Knepley } 8314ca8062c8SMatthew G. Knepley if (c >= coneSize) { 831563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 831648a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 83179566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 831863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 831948a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 83209566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 832163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8322ca8062c8SMatthew G. Knepley } 8323ca8062c8SMatthew G. Knepley } 8324ca8062c8SMatthew G. Knepley } 832557beb4faSStefano Zampini if (storagecheck) { 83269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 83279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 832863a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 832957beb4faSStefano Zampini } 8330ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8331ca8062c8SMatthew G. Knepley } 8332ca8062c8SMatthew G. Knepley 8333412e9a14SMatthew G. Knepley /* 8334412e9a14SMatthew 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. 8335412e9a14SMatthew G. Knepley */ 83369371c9d4SSatish Balay static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) { 8337412e9a14SMatthew G. Knepley DMPolytopeType cct; 8338412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8339412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8340412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8341412e9a14SMatthew G. Knepley 8342412e9a14SMatthew G. Knepley PetscFunctionBegin; 8343412e9a14SMatthew G. Knepley *unsplit = 0; 8344412e9a14SMatthew G. Knepley switch (ct) { 83459371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: ptpoints[npt++] = c; break; 8346412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 83479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 83489566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8349412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 8351412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8352412e9a14SMatthew G. Knepley } 8353412e9a14SMatthew G. Knepley break; 8354412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8355412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 83569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 83579566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8358412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 83609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8361412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 83629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8363412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8364412e9a14SMatthew G. Knepley PetscInt p; 83659371c9d4SSatish Balay for (p = 0; p < npt; ++p) 83669371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 8367412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8368412e9a14SMatthew G. Knepley } 8369412e9a14SMatthew G. Knepley } 8370412e9a14SMatthew G. Knepley } 8371412e9a14SMatthew G. Knepley break; 8372412e9a14SMatthew G. Knepley default: break; 8373412e9a14SMatthew G. Knepley } 8374412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 83759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8376412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8377412e9a14SMatthew G. Knepley } 8378412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 8379412e9a14SMatthew G. Knepley } 8380412e9a14SMatthew G. Knepley 8381ca8062c8SMatthew G. Knepley /*@ 8382ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8383ca8062c8SMatthew G. Knepley 8384ca8062c8SMatthew G. Knepley Input Parameters: 8385ca8062c8SMatthew G. Knepley + dm - The DMPlex object 838658723a97SMatthew G. Knepley - cellHeight - Normally 0 8387ca8062c8SMatthew G. Knepley 838895eb5ee5SVaclav Hapla Notes: 838995eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 839025c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 8391ca8062c8SMatthew G. Knepley 839295eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 839395eb5ee5SVaclav Hapla 8394ca8062c8SMatthew G. Knepley Level: developer 8395ca8062c8SMatthew G. Knepley 8396db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8397ca8062c8SMatthew G. Knepley @*/ 83989371c9d4SSatish Balay PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) { 8399412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 8400412e9a14SMatthew G. Knepley DMPolytopeType ct; 8401412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 8402ca8062c8SMatthew G. Knepley 8403ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8404ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84059566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 84069566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 84079566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8408412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8409412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 8410412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 841158723a97SMatthew G. Knepley 84129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 841363a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 8414412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 8415412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 84169566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 841763a3b9bcSJacob 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)); 8418412e9a14SMatthew G. Knepley } 84199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 842058723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 842158723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 8422412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 842358723a97SMatthew G. Knepley } 84249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8425412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 8426412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8427412e9a14SMatthew G. Knepley PetscInt unsplit; 842842363296SMatthew G. Knepley 84299566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8430412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 843142363296SMatthew G. Knepley } 843263a3b9bcSJacob 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)); 843342363296SMatthew G. Knepley } 8434ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8435ca8062c8SMatthew G. Knepley } 84369bf0dad6SMatthew G. Knepley 84379bf0dad6SMatthew G. Knepley /*@ 84389bf0dad6SMatthew 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 84399bf0dad6SMatthew G. Knepley 84408f6815adSVaclav Hapla Collective 8441899ea2b8SJacob Faibussowitsch 84429bf0dad6SMatthew G. Knepley Input Parameters: 84439bf0dad6SMatthew G. Knepley + dm - The DMPlex object 84449bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 84459bf0dad6SMatthew G. Knepley 844645da879fSVaclav Hapla Notes: 844745da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 844845da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 844945da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 845045da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 84519bf0dad6SMatthew G. Knepley 845295eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 845395eb5ee5SVaclav Hapla 84549bf0dad6SMatthew G. Knepley Level: developer 84559bf0dad6SMatthew G. Knepley 8456db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 84579bf0dad6SMatthew G. Knepley @*/ 84589371c9d4SSatish Balay PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) { 8459ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8460899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 84619bf0dad6SMatthew G. Knepley 84629bf0dad6SMatthew G. Knepley PetscFunctionBegin; 84639bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84648f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 846545da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 84668f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 84678f6815adSVaclav Hapla PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"); 84688f6815adSVaclav Hapla PetscFunctionReturn(0); 8469899ea2b8SJacob Faibussowitsch } 8470899ea2b8SJacob Faibussowitsch 84719566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 84729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 84739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8474ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 84759566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 84763554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8477412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 8478412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 8479ba2698f1SMatthew G. Knepley DMPolytopeType ct; 8480412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 8481412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 84829bf0dad6SMatthew G. Knepley 84839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 84849566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8485412e9a14SMatthew G. Knepley if (unsplit) continue; 84869566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 84879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 84889566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 84899566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 84909bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 84919bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 84929bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 84939bf0dad6SMatthew G. Knepley } 84949566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 849563a3b9bcSJacob 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); 84969bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 8497d4961f80SStefano Zampini DMPolytopeType fct; 84989bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 84999bf0dad6SMatthew G. Knepley 85009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 85019566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 85029bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 85039bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 85049bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 85059bf0dad6SMatthew G. Knepley } 850663a3b9bcSJacob 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]); 85079bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 8508b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 8509b5a892a1SMatthew G. Knepley PetscInt v1; 8510b5a892a1SMatthew G. Knepley 85119566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 851263a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 85139566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 851463a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 85159566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 851663a3b9bcSJacob 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]); 8517b5a892a1SMatthew G. Knepley } 85189bf0dad6SMatthew G. Knepley } 85199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 8520412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 85219bf0dad6SMatthew G. Knepley } 85229566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 85239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85249bf0dad6SMatthew G. Knepley } 85253554e41dSMatthew G. Knepley } 8526552f7358SJed Brown PetscFunctionReturn(0); 8527552f7358SJed Brown } 85283913d7c8SMatthew G. Knepley 8529bb6a34a8SMatthew G. Knepley /*@ 8530bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 8531bb6a34a8SMatthew G. Knepley 8532bb6a34a8SMatthew G. Knepley Input Parameter: 8533bb6a34a8SMatthew G. Knepley . dm - The DMPlex object 8534bb6a34a8SMatthew G. Knepley 853595eb5ee5SVaclav Hapla Notes: 853695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 853795eb5ee5SVaclav Hapla 853895eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8539bb6a34a8SMatthew G. Knepley 8540bb6a34a8SMatthew G. Knepley Level: developer 8541bb6a34a8SMatthew G. Knepley 8542db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8543bb6a34a8SMatthew G. Knepley @*/ 85449371c9d4SSatish Balay PetscErrorCode DMPlexCheckGeometry(DM dm) { 8545a2a9e04cSMatthew G. Knepley Vec coordinates; 8546bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 8547bb6a34a8SMatthew G. Knepley PetscReal vol; 854851a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 8549bb6a34a8SMatthew G. Knepley 8550bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 85519566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 85529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 855351a74b61SMatthew G. Knepley if (dim != dE) PetscFunctionReturn(0); 85549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8555bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 85569566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8557a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 85589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8559412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8560412e9a14SMatthew G. Knepley DMPolytopeType ct; 8561412e9a14SMatthew G. Knepley PetscInt unsplit; 8562412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 8563412e9a14SMatthew G. Knepley 85649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 8565412e9a14SMatthew G. Knepley switch (ct) { 8566412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 8567412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 85689371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: ignoreZeroVol = PETSC_TRUE; break; 8569412e9a14SMatthew G. Knepley default: break; 8570412e9a14SMatthew G. Knepley } 8571412e9a14SMatthew G. Knepley switch (ct) { 8572412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 8573412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8574412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 85759371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: continue; 8576412e9a14SMatthew G. Knepley default: break; 8577412e9a14SMatthew G. Knepley } 85789566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8579412e9a14SMatthew G. Knepley if (unsplit) continue; 85809566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 85811dca8a05SBarry 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); 858263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 85836858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 85846858538eSMatthew G. Knepley if (depth > 1) { 85859566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 85861dca8a05SBarry 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); 858763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 8588bb6a34a8SMatthew G. Knepley } 8589bb6a34a8SMatthew G. Knepley } 8590bb6a34a8SMatthew G. Knepley PetscFunctionReturn(0); 8591bb6a34a8SMatthew G. Knepley } 8592bb6a34a8SMatthew G. Knepley 859303da9461SVaclav Hapla /*@ 85947726db96SVaclav Hapla DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex. 85957726db96SVaclav Hapla 85967726db96SVaclav Hapla Collective 859703da9461SVaclav Hapla 859803da9461SVaclav Hapla Input Parameters: 85997726db96SVaclav Hapla + dm - The DMPlex object 8600d7d32a9aSMatthew G. Knepley . pointSF - The Point SF, or NULL for Point SF attached to DM 8601d7d32a9aSMatthew G. Knepley - allowExtraRoots - Flag to allow extra points not present in the DM 860203da9461SVaclav Hapla 8603e83a0d2dSVaclav Hapla Notes: 8604e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 860503da9461SVaclav Hapla 860695eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 860795eb5ee5SVaclav Hapla 8608d7d32a9aSMatthew G. Knepley Extra roots can come from priodic cuts, where additional points appear on the boundary 8609d7d32a9aSMatthew G. Knepley 861003da9461SVaclav Hapla Level: developer 861103da9461SVaclav Hapla 8612db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()` 861303da9461SVaclav Hapla @*/ 8614d7d32a9aSMatthew G. Knepley PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) { 86157726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 86167726db96SVaclav Hapla const PetscInt *locals; 86177726db96SVaclav Hapla const PetscSFNode *remotes; 8618f0cfc026SVaclav Hapla PetscBool distributed; 86197726db96SVaclav Hapla MPI_Comm comm; 86207726db96SVaclav Hapla PetscMPIInt rank; 862103da9461SVaclav Hapla 862203da9461SVaclav Hapla PetscFunctionBegin; 862303da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86247726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 86257726db96SVaclav Hapla else pointSF = dm->sf; 86267726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 86277726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 86287726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 86297726db96SVaclav Hapla { 86307726db96SVaclav Hapla PetscMPIInt mpiFlag; 86317726db96SVaclav Hapla 86327726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 86337726db96SVaclav 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); 86347726db96SVaclav Hapla } 86357726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 86369566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 86377726db96SVaclav Hapla if (!distributed) { 86387726db96SVaclav 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); 86398918e3e2SVaclav Hapla PetscFunctionReturn(0); 86408918e3e2SVaclav Hapla } 86417726db96SVaclav 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); 86427726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 864303da9461SVaclav Hapla 86447726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 86457726db96SVaclav Hapla { 86467726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 86477726db96SVaclav Hapla 86487726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86497726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 8650d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 86517726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 86527726db96SVaclav Hapla } 86537726db96SVaclav Hapla 86547726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 86557726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 86567726db96SVaclav 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); 86577726db96SVaclav Hapla } 86587726db96SVaclav Hapla 86597726db96SVaclav Hapla /* Check there are no cells in interface */ 86607726db96SVaclav Hapla if (!overlap) { 86617726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 86627726db96SVaclav Hapla 86639566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 86649566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 8665f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 86667726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 8667f5869d18SMatthew G. Knepley 86687726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 86697726db96SVaclav Hapla } 867003da9461SVaclav Hapla } 8671ece87651SVaclav Hapla 86727726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 86737726db96SVaclav Hapla { 86747726db96SVaclav Hapla const PetscInt *rootdegree; 86757726db96SVaclav Hapla 86767726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 86777726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 8678f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 86797726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 8680f5869d18SMatthew G. Knepley const PetscInt *cone; 8681f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 8682f5869d18SMatthew G. Knepley 86839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 86849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 8685f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8686f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 86877726db96SVaclav Hapla if (locals) { 86889566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 86897726db96SVaclav Hapla } else { 86907726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 86917726db96SVaclav Hapla } 869263a3b9bcSJacob 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]); 8693f5869d18SMatthew G. Knepley } 8694f5869d18SMatthew G. Knepley } 8695ece87651SVaclav Hapla } 86967726db96SVaclav Hapla } 869703da9461SVaclav Hapla PetscFunctionReturn(0); 869803da9461SVaclav Hapla } 869903da9461SVaclav Hapla 87007f9d8d6cSVaclav Hapla /*@ 87017f9d8d6cSVaclav Hapla DMPlexCheck - Perform various checks of Plex sanity 87027f9d8d6cSVaclav Hapla 87037f9d8d6cSVaclav Hapla Input Parameter: 87047f9d8d6cSVaclav Hapla . dm - The DMPlex object 87057f9d8d6cSVaclav Hapla 87067f9d8d6cSVaclav Hapla Notes: 87077f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 87087f9d8d6cSVaclav Hapla 87097f9d8d6cSVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 87107f9d8d6cSVaclav Hapla 87117f9d8d6cSVaclav Hapla Currently does not include DMPlexCheckCellShape(). 87127f9d8d6cSVaclav Hapla 87137f9d8d6cSVaclav Hapla Level: developer 87147f9d8d6cSVaclav Hapla 87157f9d8d6cSVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 87167f9d8d6cSVaclav Hapla @*/ 87179371c9d4SSatish Balay PetscErrorCode DMPlexCheck(DM dm) { 87187f9d8d6cSVaclav Hapla PetscInt cellHeight; 87197f9d8d6cSVaclav Hapla 8720b5a892a1SMatthew G. Knepley PetscFunctionBegin; 87217f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87229566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 87239566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 87249566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 87259566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 8726d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 87279566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 8728b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 8729b5a892a1SMatthew G. Knepley } 8730b5a892a1SMatthew G. Knepley 87319371c9d4SSatish Balay typedef struct cell_stats { 8732068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 8733068a5610SStefano Zampini PetscInt count; 8734068a5610SStefano Zampini } cell_stats_t; 8735068a5610SStefano Zampini 87369371c9d4SSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) { 8737068a5610SStefano Zampini PetscInt i, N = *len; 8738068a5610SStefano Zampini 8739068a5610SStefano Zampini for (i = 0; i < N; i++) { 8740068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 8741068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 8742068a5610SStefano Zampini 8743068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 8744068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 8745068a5610SStefano Zampini B->sum += A->sum; 8746068a5610SStefano Zampini B->squaresum += A->squaresum; 8747068a5610SStefano Zampini B->count += A->count; 8748068a5610SStefano Zampini } 8749068a5610SStefano Zampini } 8750068a5610SStefano Zampini 8751068a5610SStefano Zampini /*@ 875243fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8753068a5610SStefano Zampini 87548261a58bSMatthew G. Knepley Collective on dm 87558261a58bSMatthew G. Knepley 8756068a5610SStefano Zampini Input Parameters: 8757068a5610SStefano Zampini + dm - The DMPlex object 875843fa8764SMatthew G. Knepley . output - If true, statistics will be displayed on stdout 875943fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8760068a5610SStefano Zampini 876195eb5ee5SVaclav Hapla Notes: 876295eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 876395eb5ee5SVaclav Hapla 876495eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8765068a5610SStefano Zampini 8766068a5610SStefano Zampini Level: developer 8767068a5610SStefano Zampini 8768db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 8769068a5610SStefano Zampini @*/ 87709371c9d4SSatish Balay PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) { 8771068a5610SStefano Zampini DM dmCoarse; 877243fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 877343fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 877443fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 877543fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8776412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 877743fa8764SMatthew G. Knepley PetscMPIInt rank, size; 8778068a5610SStefano Zampini 8779068a5610SStefano Zampini PetscFunctionBegin; 8780068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8781068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 8782068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 8783068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 8784068a5610SStefano Zampini stats.count = 0; 8785068a5610SStefano Zampini 87869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 87879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 87889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 87899566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 87909566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 87919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 8792412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 8793068a5610SStefano Zampini PetscInt i; 8794068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8795068a5610SStefano Zampini 87969566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 879763a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 879843fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 8799068a5610SStefano Zampini frobJ += J[i] * J[i]; 8800068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 8801068a5610SStefano Zampini } 8802068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 8803068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 8804068a5610SStefano Zampini 8805068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 8806068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 8807068a5610SStefano Zampini stats.sum += cond; 8808068a5610SStefano Zampini stats.squaresum += cond2; 8809068a5610SStefano Zampini stats.count++; 88108261a58bSMatthew G. Knepley if (output && cond > limit) { 881143fa8764SMatthew G. Knepley PetscSection coordSection; 881243fa8764SMatthew G. Knepley Vec coordsLocal; 881343fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 881443fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 881543fa8764SMatthew G. Knepley 88169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 88179566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 88189566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 881963a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 882043fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 882163a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 882243fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 88239566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 88249566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 882543fa8764SMatthew G. Knepley } 88269566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 882743fa8764SMatthew G. Knepley } 88289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 882943fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 883043fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 883143fa8764SMatthew G. Knepley 883243fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 883343fa8764SMatthew G. Knepley PetscReal len; 883443fa8764SMatthew G. Knepley 88359566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 883663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 883743fa8764SMatthew G. Knepley } 883843fa8764SMatthew G. Knepley } 88399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 88409566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 884143fa8764SMatthew G. Knepley } 8842068a5610SStefano Zampini } 88439566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 8844068a5610SStefano Zampini 8845068a5610SStefano Zampini if (size > 1) { 8846068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 8847068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 8848068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 8849068a5610SStefano Zampini MPI_Op statReduce; 8850068a5610SStefano Zampini 88519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 88529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 88539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 88549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 88559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 88569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 8857068a5610SStefano Zampini } else { 88589566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 8859068a5610SStefano Zampini } 8860dd400576SPatrick Sanan if (rank == 0) { 8861068a5610SStefano Zampini count = globalStats.count; 8862068a5610SStefano Zampini min = globalStats.min; 8863068a5610SStefano Zampini max = globalStats.max; 8864068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 8865068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 8866068a5610SStefano Zampini } 8867068a5610SStefano Zampini 886848a46eb9SPierre 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)); 88699566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 8870068a5610SStefano Zampini 88719566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 8872068a5610SStefano Zampini if (dmCoarse) { 8873068a5610SStefano Zampini PetscBool isplex; 8874068a5610SStefano Zampini 88759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 88761baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 8877068a5610SStefano Zampini } 8878068a5610SStefano Zampini PetscFunctionReturn(0); 8879068a5610SStefano Zampini } 8880068a5610SStefano Zampini 8881f108dbd7SJacob Faibussowitsch /*@ 8882f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8883f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 8884f108dbd7SJacob Faibussowitsch 88856ed19f2fSJacob Faibussowitsch Collective on dm 8886f108dbd7SJacob Faibussowitsch 8887f108dbd7SJacob Faibussowitsch Input Parameters: 8888f108dbd7SJacob Faibussowitsch + dm - The DMPlex object 8889f108dbd7SJacob Faibussowitsch . fv - Optional PetscFV object for pre-computed cell/face centroid information 8890f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 8891f108dbd7SJacob Faibussowitsch 8892f108dbd7SJacob Faibussowitsch Output Parameters: 8893f108dbd7SJacob Faibussowitsch + OrthQual - Vec containing orthogonal quality per cell 8894f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8895f108dbd7SJacob Faibussowitsch 8896f108dbd7SJacob Faibussowitsch Options Database Keys: 8897f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8898f108dbd7SJacob Faibussowitsch supported. 8899f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8900f108dbd7SJacob Faibussowitsch 8901f108dbd7SJacob Faibussowitsch Notes: 8902f108dbd7SJacob Faibussowitsch Orthogonal quality is given by the following formula: 8903f108dbd7SJacob Faibussowitsch 8904f108dbd7SJacob Faibussowitsch \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8905f108dbd7SJacob Faibussowitsch 8906f108dbd7SJacob 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 8907f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8908f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8909f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 8910f108dbd7SJacob Faibussowitsch 8911f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 8912f108dbd7SJacob Faibussowitsch 8913f108dbd7SJacob Faibussowitsch This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8914f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8915f108dbd7SJacob Faibussowitsch 8916f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8917f108dbd7SJacob Faibussowitsch 8918f108dbd7SJacob Faibussowitsch Level: intermediate 8919f108dbd7SJacob Faibussowitsch 8920db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()` 8921f108dbd7SJacob Faibussowitsch @*/ 89229371c9d4SSatish Balay PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) { 89236ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 89246ed19f2fSJacob Faibussowitsch PetscInt *idx; 89256ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 8926f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 89276ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 8928f108dbd7SJacob Faibussowitsch MPI_Comm comm; 8929f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 8930f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 8931f108dbd7SJacob Faibussowitsch IS glob; 8932f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 8933f108dbd7SJacob Faibussowitsch PetscViewer vwr; 8934f108dbd7SJacob Faibussowitsch 8935f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 8936f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8937ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 8938f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQual, 4); 89396bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 89409566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 89419566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 894263a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 89436ed19f2fSJacob Faibussowitsch { 89446ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 89456ed19f2fSJacob Faibussowitsch 89469566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 8947f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8948f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 8949f108dbd7SJacob Faibussowitsch 89509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 895198921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8952f108dbd7SJacob Faibussowitsch } 89536ed19f2fSJacob Faibussowitsch } 8954f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 8955f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQualLabel, 5); 89569566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 89579566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 89589371c9d4SSatish Balay } else { 89599371c9d4SSatish Balay *OrthQualLabel = NULL; 89609371c9d4SSatish Balay } 89619566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 89629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 89639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 89649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 89659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 89669566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 89679566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 89689566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 89699566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 89709566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 89719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 89729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 89739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 89749566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 89759566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 89769566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 89779566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 89789566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 89796ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 89806ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8981f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 8982f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 8983898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 8984f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 8985f108dbd7SJacob Faibussowitsch 89866ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 8987f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 8988f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 89899566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 89909566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 8991f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 89929566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 89936ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 89946ed19f2fSJacob Faibussowitsch PetscInt i; 89956ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 8996f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 8997f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 8998f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 8999f108dbd7SJacob Faibussowitsch 9000f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9001f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 90029566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9003f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 90046ed19f2fSJacob Faibussowitsch { 90056ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 90066ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 90076ed19f2fSJacob Faibussowitsch 90089566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 90099566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 90109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 90116ed19f2fSJacob Faibussowitsch } 9012f108dbd7SJacob Faibussowitsch 9013f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9014f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9015f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9016f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9017f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9018addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9019addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9020addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9021f108dbd7SJacob Faibussowitsch } 9022addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9023addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9024addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9025f108dbd7SJacob Faibussowitsch 9026f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9027f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9028f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9029f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9030f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9031f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9032f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9033f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9034f108dbd7SJacob Faibussowitsch } 9035ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9036ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9037f108dbd7SJacob Faibussowitsch } 90389566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 90399566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9040f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 90416ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9042f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 90439566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9044f108dbd7SJacob Faibussowitsch } 9045f108dbd7SJacob Faibussowitsch } 90469566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 90479566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 90489566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 90499566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 90509566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 90519566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9052f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 90539566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9054f108dbd7SJacob Faibussowitsch } 90559566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 90569566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vwr)); 90579566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 9058f108dbd7SJacob Faibussowitsch PetscFunctionReturn(0); 9059f108dbd7SJacob Faibussowitsch } 9060f108dbd7SJacob Faibussowitsch 90611eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 90621eb70e55SToby Isaac * interpolator construction */ 90639371c9d4SSatish Balay static PetscErrorCode DMGetFullDM(DM dm, DM *odm) { 90641eb70e55SToby Isaac PetscSection section, newSection, gsection; 90651eb70e55SToby Isaac PetscSF sf; 90661eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 90671eb70e55SToby Isaac 90681eb70e55SToby Isaac PetscFunctionBegin; 90691eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90701eb70e55SToby Isaac PetscValidPointer(odm, 2); 90719566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 90729566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 90739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 90741eb70e55SToby Isaac if (!ghasConstraints) { 90759566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 90761eb70e55SToby Isaac *odm = dm; 90771eb70e55SToby Isaac PetscFunctionReturn(0); 90781eb70e55SToby Isaac } 90799566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 90809566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 90819566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 90829566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 90839566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 90849566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 90859566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 90861eb70e55SToby Isaac PetscFunctionReturn(0); 90871eb70e55SToby Isaac } 90881eb70e55SToby Isaac 90899371c9d4SSatish Balay static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) { 90901eb70e55SToby Isaac DM dmco, dmfo; 90911eb70e55SToby Isaac Mat interpo; 90921eb70e55SToby Isaac Vec rscale; 90931eb70e55SToby Isaac Vec cglobalo, clocal; 90941eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 90951eb70e55SToby Isaac PetscBool regular; 90961eb70e55SToby Isaac 90971eb70e55SToby Isaac PetscFunctionBegin; 90989566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 90999566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 91009566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 91019566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 91029566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 91039566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 91049566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 91059566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 91069566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 91079566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 91089566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 91099566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 91109566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 91119566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 91129566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 91139566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 91149566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 91159566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 91169566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 91179566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 91189566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 91199566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 91209566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 91219566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 91221eb70e55SToby Isaac *shift = fglobal; 91239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 91249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 91259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 91269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 91279566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 91289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 91299566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 91309566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 91311eb70e55SToby Isaac PetscFunctionReturn(0); 91321eb70e55SToby Isaac } 91331eb70e55SToby Isaac 91349371c9d4SSatish Balay PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) { 91351eb70e55SToby Isaac PetscObject shifto; 91361eb70e55SToby Isaac Vec shift; 91371eb70e55SToby Isaac 91381eb70e55SToby Isaac PetscFunctionBegin; 91391eb70e55SToby Isaac if (!interp) { 91401eb70e55SToby Isaac Vec rscale; 91411eb70e55SToby Isaac 91429566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 91439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 91441eb70e55SToby Isaac } else { 91459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 91461eb70e55SToby Isaac } 91479566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 91481eb70e55SToby Isaac if (!shifto) { 91499566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 91509566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 91511eb70e55SToby Isaac shifto = (PetscObject)shift; 91529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 91531eb70e55SToby Isaac } 91541eb70e55SToby Isaac shift = (Vec)shifto; 91559566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 91569566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 91579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 91581eb70e55SToby Isaac PetscFunctionReturn(0); 91591eb70e55SToby Isaac } 91601eb70e55SToby Isaac 9161bceba477SMatthew G. Knepley /* Pointwise interpolation 9162bceba477SMatthew G. Knepley Just code FEM for now 9163bceba477SMatthew G. Knepley u^f = I u^c 91644ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 91654ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 91664ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9167bceba477SMatthew G. Knepley */ 91689371c9d4SSatish Balay PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) { 9169bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9170bceba477SMatthew G. Knepley PetscInt m, n; 9171a063dac3SMatthew G. Knepley void *ctx; 917268132eb9SMatthew G. Knepley DM cdm; 9173cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9174bceba477SMatthew G. Knepley 9175bceba477SMatthew G. Knepley PetscFunctionBegin; 91769566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 91779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 91789566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 91799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 918068132eb9SMatthew G. Knepley 91819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 91829566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 91839566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 91849566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 91859566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 918668132eb9SMatthew G. Knepley 91879566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 91889566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 91899566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 91909566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 91919566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 91924db47ee9SStefano Zampini if (scaling) { 91935d1c2e58SMatthew G. Knepley /* Use naive scaling */ 91949566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 91954db47ee9SStefano Zampini } 9196a063dac3SMatthew G. Knepley PetscFunctionReturn(0); 9197a063dac3SMatthew G. Knepley } 9198bceba477SMatthew G. Knepley 91999371c9d4SSatish Balay PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) { 92006dbf9973SLawrence Mitchell VecScatter ctx; 920190748bafSMatthew G. Knepley 9202a063dac3SMatthew G. Knepley PetscFunctionBegin; 92039566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 92049566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 92059566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 9206bceba477SMatthew G. Knepley PetscFunctionReturn(0); 9207bceba477SMatthew G. Knepley } 9208bceba477SMatthew G. Knepley 92099371c9d4SSatish Balay 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[]) { 921000635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 921100635df3SMatthew G. Knepley PetscInt c; 921200635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 92133e9753d6SMatthew G. Knepley } 92143e9753d6SMatthew G. Knepley 92159371c9d4SSatish Balay PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) { 9216b4937a87SMatthew G. Knepley DM dmc; 9217b4937a87SMatthew G. Knepley PetscDS ds; 9218b4937a87SMatthew G. Knepley Vec ones, locmass; 9219b4937a87SMatthew G. Knepley IS cellIS; 9220b4937a87SMatthew G. Knepley PetscFormKey key; 9221b4937a87SMatthew G. Knepley PetscInt depth; 9222b4937a87SMatthew G. Knepley 9223b4937a87SMatthew G. Knepley PetscFunctionBegin; 92249566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 92259566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 92269566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 92279566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92289566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 92299566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 92309566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 92319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 92329566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 92339566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 92349566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9235b4937a87SMatthew G. Knepley key.label = NULL; 9236b4937a87SMatthew G. Knepley key.value = 0; 9237b4937a87SMatthew G. Knepley key.field = 0; 9238b4937a87SMatthew G. Knepley key.part = 0; 92399566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 92409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 92419566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 92429566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 92439566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 92449566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 92459566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 92469566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 9247b4937a87SMatthew G. Knepley PetscFunctionReturn(0); 9248b4937a87SMatthew G. Knepley } 9249b4937a87SMatthew G. Knepley 92509371c9d4SSatish Balay PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) { 9251bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9252bd041c0cSMatthew G. Knepley PetscInt m, n; 9253bd041c0cSMatthew G. Knepley void *ctx; 9254bd041c0cSMatthew G. Knepley DM cdm; 9255bd041c0cSMatthew G. Knepley PetscBool regular; 9256bd041c0cSMatthew G. Knepley 9257bd041c0cSMatthew G. Knepley PetscFunctionBegin; 92583e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 92593e9753d6SMatthew G. Knepley DM dmc; 92603e9753d6SMatthew G. Knepley PetscDS ds; 9261b4937a87SMatthew G. Knepley PetscWeakForm wf; 92623e9753d6SMatthew G. Knepley Vec u; 92633e9753d6SMatthew G. Knepley IS cellIS; 926406ad1575SMatthew G. Knepley PetscFormKey key; 92653e9753d6SMatthew G. Knepley PetscInt depth; 92663e9753d6SMatthew G. Knepley 92679566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 92689566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 92699566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 92709566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 92719566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 92729566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92739566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 92748d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 92759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 92769566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 92779566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 92786528b96dSMatthew G. Knepley key.label = NULL; 92796528b96dSMatthew G. Knepley key.value = 0; 92806528b96dSMatthew G. Knepley key.field = 0; 928106ad1575SMatthew G. Knepley key.part = 0; 92829566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 92839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 92848d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 92859566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 92863e9753d6SMatthew G. Knepley } else { 92879566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 92889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 92899566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 92909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9291bd041c0cSMatthew G. Knepley 92929566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 92939566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 92949566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 92959566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9296bd041c0cSMatthew G. Knepley 92979566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 92989566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 92999566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 93009566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 93013e9753d6SMatthew G. Knepley } 93029566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 9303bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 9304bd041c0cSMatthew G. Knepley } 9305bd041c0cSMatthew G. Knepley 93060aef6b92SMatthew G. Knepley /*@ 93070aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93080aef6b92SMatthew G. Knepley 93090aef6b92SMatthew G. Knepley Input Parameter: 93100aef6b92SMatthew G. Knepley . dm - The DMPlex object 93110aef6b92SMatthew G. Knepley 93120aef6b92SMatthew G. Knepley Output Parameter: 93130aef6b92SMatthew G. Knepley . regular - The flag 93140aef6b92SMatthew G. Knepley 93150aef6b92SMatthew G. Knepley Level: intermediate 93160aef6b92SMatthew G. Knepley 9317db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()` 93180aef6b92SMatthew G. Knepley @*/ 93199371c9d4SSatish Balay PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) { 93200aef6b92SMatthew G. Knepley PetscFunctionBegin; 93210aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9322dadcf809SJacob Faibussowitsch PetscValidBoolPointer(regular, 2); 93230aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 93240aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93250aef6b92SMatthew G. Knepley } 93260aef6b92SMatthew G. Knepley 93270aef6b92SMatthew G. Knepley /*@ 93280aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93290aef6b92SMatthew G. Knepley 93300aef6b92SMatthew G. Knepley Input Parameters: 93310aef6b92SMatthew G. Knepley + dm - The DMPlex object 93320aef6b92SMatthew G. Knepley - regular - The flag 93330aef6b92SMatthew G. Knepley 93340aef6b92SMatthew G. Knepley Level: intermediate 93350aef6b92SMatthew G. Knepley 9336db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()` 93370aef6b92SMatthew G. Knepley @*/ 93389371c9d4SSatish Balay PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) { 93390aef6b92SMatthew G. Knepley PetscFunctionBegin; 93400aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93410aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 93420aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93430aef6b92SMatthew G. Knepley } 93440aef6b92SMatthew G. Knepley 9345f7c74593SToby Isaac /* anchors */ 9346a68b90caSToby Isaac /*@ 9347f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9348ebdb1bfaSJed Brown call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9349a68b90caSToby Isaac 9350e228b242SToby Isaac not collective 9351a68b90caSToby Isaac 9352f899ff85SJose E. Roman Input Parameter: 9353a68b90caSToby Isaac . dm - The DMPlex object 9354a68b90caSToby Isaac 9355a68b90caSToby Isaac Output Parameters: 9356a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9357a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9358a68b90caSToby Isaac 9359a68b90caSToby Isaac Level: intermediate 9360a68b90caSToby Isaac 9361db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9362a68b90caSToby Isaac @*/ 93639371c9d4SSatish Balay PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) { 9364a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9365a68b90caSToby Isaac 9366a68b90caSToby Isaac PetscFunctionBegin; 9367a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93689566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 9369a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 9370a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 9371a68b90caSToby Isaac PetscFunctionReturn(0); 9372a68b90caSToby Isaac } 9373a68b90caSToby Isaac 9374a68b90caSToby Isaac /*@ 9375f7c74593SToby Isaac DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9376f7c74593SToby Isaac when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9377a68b90caSToby Isaac point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9378a68b90caSToby Isaac 9379a17985deSToby Isaac After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9380ebdb1bfaSJed Brown DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9381a68b90caSToby Isaac 9382e228b242SToby Isaac collective on dm 9383a68b90caSToby Isaac 9384a68b90caSToby Isaac Input Parameters: 9385a68b90caSToby Isaac + dm - The DMPlex object 9386e228b242SToby Isaac . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. Must have a local communicator (PETSC_COMM_SELF or derivative). 9387e228b242SToby Isaac - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9388a68b90caSToby Isaac 9389a68b90caSToby Isaac The reference counts of anchorSection and anchorIS are incremented. 9390a68b90caSToby Isaac 9391a68b90caSToby Isaac Level: intermediate 9392a68b90caSToby Isaac 9393db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9394a68b90caSToby Isaac @*/ 93959371c9d4SSatish Balay PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) { 9396a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9397e228b242SToby Isaac PetscMPIInt result; 9398a68b90caSToby Isaac 9399a68b90caSToby Isaac PetscFunctionBegin; 9400a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9401e228b242SToby Isaac if (anchorSection) { 9402e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 94039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 94041dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 9405e228b242SToby Isaac } 9406e228b242SToby Isaac if (anchorIS) { 9407e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 94089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 94091dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 9410e228b242SToby Isaac } 9411a68b90caSToby Isaac 94129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 94139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 9414a68b90caSToby Isaac plex->anchorSection = anchorSection; 9415a68b90caSToby Isaac 94169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 94179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 9418a68b90caSToby Isaac plex->anchorIS = anchorIS; 9419a68b90caSToby Isaac 9420cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9421a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 9422a68b90caSToby Isaac const PetscInt *anchors; 9423a68b90caSToby Isaac 94249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 94259566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 94269566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 9427a68b90caSToby Isaac for (a = 0; a < size; a++) { 9428a68b90caSToby Isaac PetscInt p; 9429a68b90caSToby Isaac 9430a68b90caSToby Isaac p = anchors[a]; 9431a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 9432a68b90caSToby Isaac PetscInt dof; 9433a68b90caSToby Isaac 94349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 9435a68b90caSToby Isaac if (dof) { 94369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 943763a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 9438a68b90caSToby Isaac } 9439a68b90caSToby Isaac } 9440a68b90caSToby Isaac } 94419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 9442a68b90caSToby Isaac } 9443f7c74593SToby Isaac /* reset the generic constraints */ 94449566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 9445a68b90caSToby Isaac PetscFunctionReturn(0); 9446a68b90caSToby Isaac } 9447a68b90caSToby Isaac 94489371c9d4SSatish Balay static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) { 9449f7c74593SToby Isaac PetscSection anchorSection; 94506995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9451a68b90caSToby Isaac 9452a68b90caSToby Isaac PetscFunctionBegin; 9453a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94549566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 94559566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 94569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 94576995de1eSToby Isaac if (numFields) { 9458719ab38cSToby Isaac PetscInt f; 94599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 9460719ab38cSToby Isaac 9461719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 9462719ab38cSToby Isaac PetscInt numComp; 9463719ab38cSToby Isaac 94649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 94659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 9466719ab38cSToby Isaac } 94676995de1eSToby Isaac } 94689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 94699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 94706995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 94716995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 94726995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 94739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 9474a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 94759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 9476a68b90caSToby Isaac if (dof) { 94779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 94789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 9479a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 94809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 94819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 9482a68b90caSToby Isaac } 9483a68b90caSToby Isaac } 9484a68b90caSToby Isaac } 94859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 94869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 9487a68b90caSToby Isaac PetscFunctionReturn(0); 9488a68b90caSToby Isaac } 9489a68b90caSToby Isaac 94909371c9d4SSatish Balay static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) { 9491f7c74593SToby Isaac PetscSection aSec; 9492ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 94930ac89760SToby Isaac const PetscInt *anchors; 94940ac89760SToby Isaac PetscInt numFields, f; 949566ad2231SToby Isaac IS aIS; 9496e19f7ee6SMark Adams MatType mtype; 9497e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 94980ac89760SToby Isaac 94990ac89760SToby Isaac PetscFunctionBegin; 95000ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 95029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 95039566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 95049566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 95059566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 95069566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 95079566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 95089566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 9509e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 9510e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9511e19f7ee6SMark Adams else mtype = MATSEQAIJ; 95129566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 95139566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 95149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 95156995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 95169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 95179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 95189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 95190ac89760SToby Isaac i[0] = 0; 95209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 95210ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 9522f19733c5SToby Isaac PetscInt rDof, rOff, r; 9523f19733c5SToby Isaac 95249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 9525f19733c5SToby Isaac if (!rDof) continue; 95269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 95270ac89760SToby Isaac if (numFields) { 95280ac89760SToby Isaac for (f = 0; f < numFields; f++) { 95290ac89760SToby Isaac annz = 0; 9530f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 9531f19733c5SToby Isaac a = anchors[rOff + r]; 9532ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 95340ac89760SToby Isaac annz += aDof; 95350ac89760SToby Isaac } 95369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 95379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 9538ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 95390ac89760SToby Isaac } 95402f7452b8SBarry Smith } else { 95410ac89760SToby Isaac annz = 0; 95429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 95430ac89760SToby Isaac for (q = 0; q < dof; q++) { 9544ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 9545ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 95470ac89760SToby Isaac annz += aDof; 95480ac89760SToby Isaac } 95499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 95509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 9551ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 95520ac89760SToby Isaac } 95530ac89760SToby Isaac } 95540ac89760SToby Isaac nnz = i[m]; 95559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 95560ac89760SToby Isaac offset = 0; 95570ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 95580ac89760SToby Isaac if (numFields) { 95590ac89760SToby Isaac for (f = 0; f < numFields; f++) { 95609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 95610ac89760SToby Isaac for (q = 0; q < dof; q++) { 95620ac89760SToby Isaac PetscInt rDof, rOff, r; 95639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 95649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 95650ac89760SToby Isaac for (r = 0; r < rDof; r++) { 95660ac89760SToby Isaac PetscInt s; 95670ac89760SToby Isaac 95680ac89760SToby Isaac a = anchors[rOff + r]; 9569ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 95719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 9572ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 95730ac89760SToby Isaac } 95740ac89760SToby Isaac } 95750ac89760SToby Isaac } 95762f7452b8SBarry Smith } else { 95779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 95780ac89760SToby Isaac for (q = 0; q < dof; q++) { 95790ac89760SToby Isaac PetscInt rDof, rOff, r; 95809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 95819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 95820ac89760SToby Isaac for (r = 0; r < rDof; r++) { 95830ac89760SToby Isaac PetscInt s; 95840ac89760SToby Isaac 95850ac89760SToby Isaac a = anchors[rOff + r]; 9586ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 95889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 9589ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 95900ac89760SToby Isaac } 95910ac89760SToby Isaac } 95920ac89760SToby Isaac } 95930ac89760SToby Isaac } 95949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 95959566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 95969566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 95979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 95980ac89760SToby Isaac PetscFunctionReturn(0); 95990ac89760SToby Isaac } 96000ac89760SToby Isaac 96019371c9d4SSatish Balay PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) { 9602f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9603f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 960466ad2231SToby Isaac Mat cMat; 960566ad2231SToby Isaac 960666ad2231SToby Isaac PetscFunctionBegin; 960766ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 96089566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 960966ad2231SToby Isaac if (anchorSection) { 961044a7f3ddSMatthew G. Knepley PetscInt Nf; 9611e228b242SToby Isaac 96129566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 96139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 96149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 96159566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 96169566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 96179566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 96189566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 96199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 962066ad2231SToby Isaac } 962166ad2231SToby Isaac PetscFunctionReturn(0); 962266ad2231SToby Isaac } 9623a93c429eSMatthew G. Knepley 96249371c9d4SSatish Balay PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) { 9625a93c429eSMatthew G. Knepley IS subis; 9626a93c429eSMatthew G. Knepley PetscSection section, subsection; 9627a93c429eSMatthew G. Knepley 9628a93c429eSMatthew G. Knepley PetscFunctionBegin; 96299566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 963028b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 963128b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9632a93c429eSMatthew G. Knepley /* Create subdomain */ 96339566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 9634a93c429eSMatthew G. Knepley /* Create submodel */ 96359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 96369566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 96379566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 96389566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 96399566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 9640a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 9641a93c429eSMatthew G. Knepley if (is) { 9642a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 9643a93c429eSMatthew G. Knepley IS spIS; 9644a93c429eSMatthew G. Knepley const PetscInt *spmap; 9645a93c429eSMatthew G. Knepley PetscInt *subIndices; 9646a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9647a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9648a93c429eSMatthew G. Knepley 96499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 96509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 96519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 96529566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 96539566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 96549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 9655a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9656a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 9657a93c429eSMatthew G. Knepley 96589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 9659a93c429eSMatthew G. Knepley if (gdof > 0) { 9660a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9661a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 9662a93c429eSMatthew G. Knepley 96639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 96649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 9665a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 9666a93c429eSMatthew G. Knepley } 9667a93c429eSMatthew G. Knepley subSize += pSubSize; 9668a93c429eSMatthew G. Knepley if (pSubSize) { 9669a93c429eSMatthew G. Knepley if (bs < 0) { 9670a93c429eSMatthew G. Knepley bs = pSubSize; 9671a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 9672a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 9673a93c429eSMatthew G. Knepley bs = 1; 9674a93c429eSMatthew G. Knepley } 9675a93c429eSMatthew G. Knepley } 9676a93c429eSMatthew G. Knepley } 9677a93c429eSMatthew G. Knepley } 9678a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 96799371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 96809371c9d4SSatish Balay bsLocal[1] = bs; 96819566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 96829371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 96839371c9d4SSatish Balay bs = 1; 96849371c9d4SSatish Balay } else { 96859371c9d4SSatish Balay bs = bsMinMax[0]; 96869371c9d4SSatish Balay } 96879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 9688a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9689a93c429eSMatthew G. Knepley PetscInt gdof, goff; 9690a93c429eSMatthew G. Knepley 96919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 9692a93c429eSMatthew G. Knepley if (gdof > 0) { 9693a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 9694a93c429eSMatthew G. Knepley 96959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 9696a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9697a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 9698a93c429eSMatthew G. Knepley 9699a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 9700a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 97019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 97029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 9703a93c429eSMatthew G. Knepley poff += fdof - fcdof; 9704a93c429eSMatthew G. Knepley } 97059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 97069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 9707ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 9708a93c429eSMatthew G. Knepley } 9709a93c429eSMatthew G. Knepley } 9710a93c429eSMatthew G. Knepley } 97119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 97129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 9713a93c429eSMatthew G. Knepley if (bs > 1) { 9714a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 9715a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 9716a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 9717a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 97189371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 97199371c9d4SSatish Balay set = 0; 97209371c9d4SSatish Balay break; 97219371c9d4SSatish Balay } 9722a93c429eSMatthew G. Knepley } 9723a93c429eSMatthew G. Knepley } 97249566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 9725a93c429eSMatthew G. Knepley } 9726a93c429eSMatthew G. Knepley /* Attach nullspace */ 9727a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9728a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9729a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 9730a93c429eSMatthew G. Knepley } 9731a93c429eSMatthew G. Knepley if (f < Nf) { 9732a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 97339566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 97346823f3c5SBlaise Bourdin 97359566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 97369566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 9737a93c429eSMatthew G. Knepley } 9738a93c429eSMatthew G. Knepley } 9739a93c429eSMatthew G. Knepley PetscFunctionReturn(0); 9740a93c429eSMatthew G. Knepley } 9741c0f0dcc3SMatthew G. Knepley 9742c0f0dcc3SMatthew G. Knepley /*@ 9743c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 9744c0f0dcc3SMatthew G. Knepley 9745c0f0dcc3SMatthew G. Knepley Input Parameter: 9746c0f0dcc3SMatthew G. Knepley - dm - The DM 9747c0f0dcc3SMatthew G. Knepley 9748c0f0dcc3SMatthew G. Knepley Level: developer 9749c0f0dcc3SMatthew G. Knepley 9750c0f0dcc3SMatthew G. Knepley Options Database Keys: 9751c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor 9752c0f0dcc3SMatthew G. Knepley 9753db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()` 9754c0f0dcc3SMatthew G. Knepley @*/ 97559371c9d4SSatish Balay PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) { 9756e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG) 9757c0f0dcc3SMatthew G. Knepley PetscStageLog stageLog; 9758c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 9759c0f0dcc3SMatthew G. Knepley PetscLogStage stage; 9760c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 9761c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 9762c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 9763c0f0dcc3SMatthew G. Knepley const char *name; 9764e5ed2c37SJose E. Roman #endif 9765c0f0dcc3SMatthew G. Knepley 9766c0f0dcc3SMatthew G. Knepley PetscFunctionBegin; 9767c0f0dcc3SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9768c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG) 97699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 97709566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 97719566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 97729566063dSJacob Faibussowitsch PetscCall(PetscLogGetStageLog(&stageLog)); 97739566063dSJacob Faibussowitsch PetscCall(PetscStageLogGetCurrent(stageLog, &stage)); 97749566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 97759566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 9776c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 9777c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 9778c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 977963a3b9bcSJacob 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))); 9780c0f0dcc3SMatthew G. Knepley #else 9781c0f0dcc3SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9782c0f0dcc3SMatthew G. Knepley #endif 9783c0f0dcc3SMatthew G. Knepley PetscFunctionReturn(0); 9784c0f0dcc3SMatthew G. Knepley } 9785