1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/isimpl.h> 3e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 48135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 50c312b8eSJed Brown #include <petscsf.h> 6e228b242SToby Isaac #include <petscds.h> 7e412dcbdSMatthew G. Knepley #include <petscdraw.h> 8f19dbd58SToby Isaac #include <petscdmfield.h> 9012bc364SMatthew G. Knepley #include <petscdmplextransform.h> 10552f7358SJed Brown 11552f7358SJed Brown /* Logging support */ 1202f7d72cSksagiyam 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; 13*252a1336SBarry Smith PetscLogEvent DMPLEX_RebalBuildGraph,DMPLEX_RebalRewriteSF,DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart; 14552f7358SJed Brown 155a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 16552f7358SJed Brown 17e5337592SStefano Zampini /*@ 189318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 199318fe57SMatthew G. Knepley 209318fe57SMatthew G. Knepley Input Parameter: 219318fe57SMatthew G. Knepley . dm - The DMPlex object 229318fe57SMatthew G. Knepley 239318fe57SMatthew G. Knepley Output Parameter: 249318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 259318fe57SMatthew G. Knepley 269318fe57SMatthew 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. 279318fe57SMatthew G. Knepley If the mesh has no cells, this returns PETSC_FALSE. 289318fe57SMatthew G. Knepley 299318fe57SMatthew G. Knepley Level: intermediate 309318fe57SMatthew G. Knepley 31db781477SPatrick Sanan .seealso `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 329318fe57SMatthew G. Knepley @*/ 339318fe57SMatthew G. Knepley PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 349318fe57SMatthew G. Knepley { 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)); 409318fe57SMatthew G. Knepley if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 429318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 439318fe57SMatthew G. Knepley PetscFunctionReturn(0); 449318fe57SMatthew G. Knepley } 459318fe57SMatthew G. Knepley 469318fe57SMatthew G. Knepley /*@ 47412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 48e5337592SStefano Zampini 49d8d19677SJose E. Roman Input Parameters: 50412e9a14SMatthew G. Knepley + dm - The DMPlex object 51412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 52e5337592SStefano Zampini 53e5337592SStefano Zampini Output Parameters: 54412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 55412e9a14SMatthew G. Knepley - cEnd - The upper bound on "normal"" cells 56e5337592SStefano Zampini 57412e9a14SMatthew 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. 58e5337592SStefano Zampini 59412e9a14SMatthew G. Knepley Level: developer 60e5337592SStefano Zampini 61db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 62e5337592SStefano Zampini @*/ 63412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 64e5337592SStefano Zampini { 65412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 66412e9a14SMatthew G. Knepley PetscInt cS, cE, c; 67e5337592SStefano Zampini 68e5337592SStefano Zampini PetscFunctionBegin; 699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE)); 70412e9a14SMatthew G. Knepley for (c = cS; c < cE; ++c) { 71412e9a14SMatthew G. Knepley DMPolytopeType cct; 72412e9a14SMatthew G. Knepley 739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &cct)); 74412e9a14SMatthew G. Knepley if ((PetscInt) cct < 0) break; 75412e9a14SMatthew G. Knepley switch (cct) { 76ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 77ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 78ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 79ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 80ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 81ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 82412e9a14SMatthew G. Knepley ct = cct; 83e5337592SStefano Zampini 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)); 93e5337592SStefano Zampini } 94412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 95412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 96e5337592SStefano Zampini PetscFunctionReturn(0); 97e5337592SStefano Zampini } 98e5337592SStefano Zampini 997afe7537SMatthew G. Knepley PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 1007e42fee7SMatthew G. Knepley { 101412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 102a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 1037e42fee7SMatthew G. Knepley 1047e42fee7SMatthew G. Knepley PetscFunctionBegin; 105e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 1069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1079566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1089566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 1099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1107e42fee7SMatthew G. Knepley if (field >= 0) { 1119566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 1129566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 1137e42fee7SMatthew G. Knepley } else { 1149566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 1159566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 1167e42fee7SMatthew G. Knepley } 1179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 118a99a26bcSAdrian Croucher if (globalvcdof[0]) { 1197e42fee7SMatthew G. Knepley *sStart = vStart; 1207e42fee7SMatthew G. Knepley *sEnd = vEnd; 121f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 1227e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 123a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 1247e42fee7SMatthew G. Knepley *sStart = cStart; 1257e42fee7SMatthew G. Knepley *sEnd = cEnd; 126f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 1277e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 128e630c359SToby Isaac } else { 129e630c359SToby Isaac if (field >= 0) { 130e630c359SToby Isaac const char *fieldname; 131e630c359SToby Isaac 1329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 13363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 134e630c359SToby Isaac } else { 13563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\n")); 136e630c359SToby Isaac } 137e630c359SToby Isaac } 1387e42fee7SMatthew G. Knepley PetscFunctionReturn(0); 1397e42fee7SMatthew G. Knepley } 1407e42fee7SMatthew G. Knepley 1416913077dSMatthew G. Knepley /*@ 1426913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 1436913077dSMatthew G. Knepley 1446913077dSMatthew G. Knepley Collective on dm 1456913077dSMatthew G. Knepley 1466913077dSMatthew G. Knepley Input Parameters: 1476913077dSMatthew G. Knepley + dm - The DMPlex 1486913077dSMatthew G. Knepley . n - The number of vectors 1496913077dSMatthew G. Knepley . u - The array of local vectors 1506913077dSMatthew G. Knepley - viewer - The Draw viewer 1516913077dSMatthew G. Knepley 1526913077dSMatthew G. Knepley Level: advanced 1536913077dSMatthew G. Knepley 154db781477SPatrick Sanan .seealso: `VecViewFromOptions()`, `VecView()` 1556913077dSMatthew G. Knepley @*/ 1566913077dSMatthew G. Knepley PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 1576913077dSMatthew G. Knepley { 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 2256913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 2266913077dSMatthew G. Knepley { 2276913077dSMatthew G. Knepley DM dm; 2286913077dSMatthew G. Knepley 2296913077dSMatthew G. Knepley PetscFunctionBegin; 2309566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 2319566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 2326913077dSMatthew G. Knepley PetscFunctionReturn(0); 2336913077dSMatthew G. Knepley } 2346913077dSMatthew G. Knepley 2356913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 236e412dcbdSMatthew G. Knepley { 237e412dcbdSMatthew G. Knepley DM dm; 238d1df6f1dSMatthew G. Knepley PetscSection s; 239e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 240e412dcbdSMatthew G. Knepley DM cdm; 241e412dcbdSMatthew G. Knepley PetscSection coordSection; 242e412dcbdSMatthew G. Knepley Vec coordinates; 243e412dcbdSMatthew G. Knepley const PetscScalar *coords, *array; 244e412dcbdSMatthew G. Knepley PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 245339e3443SMatthew G. Knepley PetscReal vbound[2], time; 2466913077dSMatthew G. Knepley PetscBool flg; 247d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 248e412dcbdSMatthew G. Knepley const char *name; 249339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 250e412dcbdSMatthew G. Knepley 251e412dcbdSMatthew G. Knepley PetscFunctionBegin; 2529566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2539566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 2549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 2559566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 2569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 2579566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 2589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 2599566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 2609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 263e412dcbdSMatthew G. Knepley 2649566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 2659566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 266e412dcbdSMatthew G. Knepley 2679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 2689566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 269e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 2700c81f2a8SMatthew G. Knepley bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 2710c81f2a8SMatthew G. Knepley bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); 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))); 288d1df6f1dSMatthew G. Knepley 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 3716913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 3726913077dSMatthew G. Knepley { 3736913077dSMatthew G. Knepley DM dm; 3746913077dSMatthew G. Knepley PetscDraw draw; 3756913077dSMatthew G. Knepley PetscInt dim; 3766913077dSMatthew G. Knepley PetscBool isnull; 3776913077dSMatthew G. Knepley 3786913077dSMatthew G. Knepley PetscFunctionBegin; 3799566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3809566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 3816913077dSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 3826913077dSMatthew G. Knepley 3839566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3856913077dSMatthew G. Knepley switch (dim) { 3869566063dSJacob Faibussowitsch case 1: PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));break; 3879566063dSJacob Faibussowitsch case 2: PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));break; 3885f80ce2aSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 3896913077dSMatthew G. Knepley } 3906913077dSMatthew G. Knepley PetscFunctionReturn(0); 3916913077dSMatthew G. Knepley } 3926913077dSMatthew G. Knepley 393684b87d9SLisandro Dalcin static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 394684b87d9SLisandro Dalcin { 395684b87d9SLisandro Dalcin DM dm; 396684b87d9SLisandro Dalcin Vec locv; 397684b87d9SLisandro Dalcin const char *name; 398684b87d9SLisandro Dalcin PetscSection section; 399684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 400e630c359SToby Isaac PetscInt numFields; 401684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 402684b87d9SLisandro Dalcin 403684b87d9SLisandro Dalcin PetscFunctionBegin; 4049566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4059566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 4069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 4079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) locv, name)); 4089566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4099566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 4109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 411e630c359SToby Isaac if (!numFields) { 4129566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 4139566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv)); 414e630c359SToby Isaac } else { 415e630c359SToby Isaac PetscInt f; 416e630c359SToby Isaac 417e630c359SToby Isaac for (f = 0; f < numFields; f++) { 4189566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 419e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 4209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 4219566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv)); 422e630c359SToby Isaac } 4239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 424e630c359SToby Isaac } 425684b87d9SLisandro Dalcin PetscFunctionReturn(0); 426684b87d9SLisandro Dalcin } 427684b87d9SLisandro Dalcin 428552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 429552f7358SJed Brown { 430552f7358SJed Brown DM dm; 431684b87d9SLisandro Dalcin PetscBool isvtk, ishdf5, isdraw, isglvis; 432552f7358SJed Brown 433552f7358SJed Brown PetscFunctionBegin; 4349566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 43528b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 4369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 4379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 4389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 4399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 440684b87d9SLisandro Dalcin if (isvtk || ishdf5 || isdraw || isglvis) { 441684b87d9SLisandro Dalcin PetscInt i,numFields; 442684b87d9SLisandro Dalcin PetscObject fe; 443ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 444684b87d9SLisandro Dalcin Vec locv = v; 445684b87d9SLisandro Dalcin const char *name; 446684b87d9SLisandro Dalcin PetscInt step; 447684b87d9SLisandro Dalcin PetscReal time; 448ef31f671SMatthew G. Knepley 4499566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 450684b87d9SLisandro Dalcin for (i=0; i<numFields; i++) { 4519566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 452684b87d9SLisandro Dalcin if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 453ef31f671SMatthew G. Knepley } 454684b87d9SLisandro Dalcin if (fem) { 455798534f6SMatthew G. Knepley PetscObject isZero; 456798534f6SMatthew G. Knepley 4579566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 4589566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 4599566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) locv, name)); 4609566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero)); 4619566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero)); 4629566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4639566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 4649566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 465ef31f671SMatthew G. Knepley } 466552f7358SJed Brown if (isvtk) { 4679566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 468b136c2c9SMatthew G. Knepley } else if (ishdf5) { 469b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 4709566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 471b136c2c9SMatthew G. Knepley #else 472b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 473b136c2c9SMatthew G. Knepley #endif 474f13a32a3SMatthew G. Knepley } else if (isdraw) { 4759566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 476684b87d9SLisandro Dalcin } else if (isglvis) { 4779566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 4789566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 4799566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 480684b87d9SLisandro Dalcin } 481798534f6SMatthew G. Knepley if (fem) { 4829566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL)); 4839566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 484798534f6SMatthew G. Knepley } 485552f7358SJed Brown } else { 486684b87d9SLisandro Dalcin PetscBool isseq; 487684b87d9SLisandro Dalcin 4889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 4899566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 4909566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 491552f7358SJed Brown } 492552f7358SJed Brown PetscFunctionReturn(0); 493552f7358SJed Brown } 494552f7358SJed Brown 495552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 496552f7358SJed Brown { 497552f7358SJed Brown DM dm; 4986823f3c5SBlaise Bourdin PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 499552f7358SJed Brown 500552f7358SJed Brown PetscFunctionBegin; 5019566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 50228b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 5049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 5059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 5069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 5079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii)); 508684b87d9SLisandro Dalcin if (isvtk || isdraw || isglvis) { 509552f7358SJed Brown Vec locv; 510798534f6SMatthew G. Knepley PetscObject isZero; 511552f7358SJed Brown const char *name; 512552f7358SJed Brown 5139566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 5159566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) locv, name)); 5169566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 5179566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 5189566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero)); 5199566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero)); 5209566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 5219566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL)); 5229566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 523b136c2c9SMatthew G. Knepley } else if (ishdf5) { 524b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5259566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 526b136c2c9SMatthew G. Knepley #else 527b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 528b136c2c9SMatthew G. Knepley #endif 5296823f3c5SBlaise Bourdin } else if (isexodusii) { 5306823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 5319566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 5326823f3c5SBlaise Bourdin #else 5336823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 5346823f3c5SBlaise Bourdin #endif 535552f7358SJed Brown } else { 536684b87d9SLisandro Dalcin PetscBool isseq; 537684b87d9SLisandro Dalcin 5389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 5399566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5409566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 541552f7358SJed Brown } 542552f7358SJed Brown PetscFunctionReturn(0); 543552f7358SJed Brown } 544552f7358SJed Brown 545d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 546d930f514SMatthew G. Knepley { 547d930f514SMatthew G. Knepley DM dm; 548d930f514SMatthew G. Knepley MPI_Comm comm; 549d930f514SMatthew G. Knepley PetscViewerFormat format; 550d930f514SMatthew G. Knepley Vec v; 551d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 552d930f514SMatthew G. Knepley 553d930f514SMatthew G. Knepley PetscFunctionBegin; 5549566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 5559566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) originalv, &comm)); 55628b400f6SJacob Faibussowitsch PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5579566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 5599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 560d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 561a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 562a8ad634aSStefano Zampini /* this need a better fix */ 563a8ad634aSStefano Zampini if (dm->useNatural) { 564a8ad634aSStefano Zampini if (dm->sfNatural) { 565d930f514SMatthew G. Knepley const char *vecname; 566d930f514SMatthew G. Knepley PetscInt n, nroots; 567d930f514SMatthew G. Knepley 5689566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 5699566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 570d930f514SMatthew G. Knepley if (n == nroots) { 5719566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 5729566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 5739566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 5749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname)); 5759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) v, vecname)); 576d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 577d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 578a8ad634aSStefano Zampini } else v = originalv; 579a8ad634aSStefano Zampini } else v = originalv; 580a8ad634aSStefano Zampini 581d930f514SMatthew G. Knepley if (ishdf5) { 582d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5839566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 584d930f514SMatthew G. Knepley #else 585d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 586d930f514SMatthew G. Knepley #endif 587d930f514SMatthew G. Knepley } else if (isvtk) { 588d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 589d930f514SMatthew G. Knepley } else { 590d930f514SMatthew G. Knepley PetscBool isseq; 591d930f514SMatthew G. Knepley 5929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 5939566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5949566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 595d930f514SMatthew G. Knepley } 5969566063dSJacob Faibussowitsch if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v)); 597d930f514SMatthew G. Knepley PetscFunctionReturn(0); 598d930f514SMatthew G. Knepley } 599d930f514SMatthew G. Knepley 6002c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 6012c40f234SMatthew G. Knepley { 6022c40f234SMatthew G. Knepley DM dm; 6032c40f234SMatthew G. Knepley PetscBool ishdf5; 6042c40f234SMatthew G. Knepley 6052c40f234SMatthew G. Knepley PetscFunctionBegin; 6069566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 60728b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 6092c40f234SMatthew G. Knepley if (ishdf5) { 6102c40f234SMatthew G. Knepley DM dmBC; 6112c40f234SMatthew G. Knepley Vec gv; 6122c40f234SMatthew G. Knepley const char *name; 6132c40f234SMatthew G. Knepley 6149566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 6159566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 6169566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 6179566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) gv, name)); 6189566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 6199566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 6209566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 6219566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 6221baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 6232c40f234SMatthew G. Knepley PetscFunctionReturn(0); 6242c40f234SMatthew G. Knepley } 6252c40f234SMatthew G. Knepley 6262c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 6272c40f234SMatthew G. Knepley { 6282c40f234SMatthew G. Knepley DM dm; 6296823f3c5SBlaise Bourdin PetscBool ishdf5,isexodusii; 6302c40f234SMatthew G. Knepley 6312c40f234SMatthew G. Knepley PetscFunctionBegin; 6329566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63328b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 6359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6362c40f234SMatthew G. Knepley if (ishdf5) { 637878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6389566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 639b136c2c9SMatthew G. Knepley #else 640b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 641878b459fSMatthew G. Knepley #endif 6426823f3c5SBlaise Bourdin } else if (isexodusii) { 6436823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6449566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 6456823f3c5SBlaise Bourdin #else 6466823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6476823f3c5SBlaise Bourdin #endif 6481baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 649552f7358SJed Brown PetscFunctionReturn(0); 650552f7358SJed Brown } 651552f7358SJed Brown 652d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 653d930f514SMatthew G. Knepley { 654d930f514SMatthew G. Knepley DM dm; 655d930f514SMatthew G. Knepley PetscViewerFormat format; 656d930f514SMatthew G. Knepley PetscBool ishdf5; 657d930f514SMatthew G. Knepley 658d930f514SMatthew G. Knepley PetscFunctionBegin; 6599566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 66028b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6619566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 663d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 664a8ad634aSStefano Zampini if (dm->useNatural) { 665d930f514SMatthew G. Knepley if (dm->sfNatural) { 666d930f514SMatthew G. Knepley if (ishdf5) { 667d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 668d930f514SMatthew G. Knepley Vec v; 669d930f514SMatthew G. Knepley const char *vecname; 670d930f514SMatthew G. Knepley 6719566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 6729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname)); 6739566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) v, vecname)); 6749566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 6759566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 6769566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 6779566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dm, &v)); 678d930f514SMatthew G. Knepley #else 679d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 680d930f514SMatthew G. Knepley #endif 681d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 682d930f514SMatthew G. Knepley } 6831baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 684d930f514SMatthew G. Knepley } 685d930f514SMatthew G. Knepley PetscFunctionReturn(0); 686d930f514SMatthew G. Knepley } 687d930f514SMatthew G. Knepley 6887cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 689731e8ddeSMatthew G. Knepley { 690731e8ddeSMatthew G. Knepley PetscSection coordSection; 691731e8ddeSMatthew G. Knepley Vec coordinates; 692ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 693731e8ddeSMatthew G. Knepley const char *name[4]; 694731e8ddeSMatthew G. Knepley const PetscScalar *a; 695731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 696731e8ddeSMatthew G. Knepley 697731e8ddeSMatthew G. Knepley PetscFunctionBegin; 6989566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 6999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 7009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7019566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 7029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 7039566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 7049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 7059566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 706731e8ddeSMatthew G. Knepley name[0] = "vertex"; 707731e8ddeSMatthew G. Knepley name[1] = "edge"; 708731e8ddeSMatthew G. Knepley name[dim-1] = "face"; 709731e8ddeSMatthew G. Knepley name[dim] = "cell"; 710731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 711731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 712ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 713731e8ddeSMatthew G. Knepley 7149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 71563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 7169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 718731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 719731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 720731e8ddeSMatthew G. Knepley 721731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 7229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 723731e8ddeSMatthew G. Knepley if (!dof) continue; 7249566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 7259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 72663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 727731e8ddeSMatthew G. Knepley for (p = 0; p < dof/dim; ++p) { 7289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 729731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 7309566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 7319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]))); 732731e8ddeSMatthew G. Knepley } 7339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 734731e8ddeSMatthew G. Knepley } 7359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 736731e8ddeSMatthew G. Knepley } 7379566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 739731e8ddeSMatthew G. Knepley } 7409566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 741731e8ddeSMatthew G. Knepley PetscFunctionReturn(0); 742731e8ddeSMatthew G. Knepley } 743731e8ddeSMatthew G. Knepley 74419ad8254SMatthew G. Knepley typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem; 74519ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 74619ad8254SMatthew G. Knepley 74719ad8254SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 74819ad8254SMatthew G. Knepley { 74919ad8254SMatthew G. Knepley PetscInt i; 75019ad8254SMatthew G. Knepley 75119ad8254SMatthew G. Knepley PetscFunctionBegin; 75219ad8254SMatthew G. Knepley if (dim > 3) { 7539566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]))); 75419ad8254SMatthew G. Knepley } else { 755bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 75619ad8254SMatthew G. Knepley 75719ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 75819ad8254SMatthew G. Knepley switch (cs) { 75919ad8254SMatthew G. Knepley case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break; 76019ad8254SMatthew G. Knepley case CS_POLAR: 76163a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 76219ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 76319ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 76419ad8254SMatthew G. Knepley break; 76519ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 76663a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 76719ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 76819ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 76919ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 77019ad8254SMatthew G. Knepley break; 77119ad8254SMatthew G. Knepley case CS_SPHERICAL: 77263a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 77319ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 77419ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 77519ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 77619ad8254SMatthew G. Knepley break; 77719ad8254SMatthew G. Knepley } 7789566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i])); 77919ad8254SMatthew G. Knepley } 78019ad8254SMatthew G. Knepley PetscFunctionReturn(0); 78119ad8254SMatthew G. Knepley } 78219ad8254SMatthew G. Knepley 7837cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 784552f7358SJed Brown { 785552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7866858538eSMatthew G. Knepley DM cdm, cdmCell; 7876858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 7886858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 789552f7358SJed Brown PetscViewerFormat format; 790552f7358SJed Brown 791552f7358SJed Brown PetscFunctionBegin; 7929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 7936858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 7956858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 7966858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 7976858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 7989566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 799552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 800552f7358SJed Brown const char *name; 801f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 8029318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 803552f7358SJed Brown PetscMPIInt rank, size; 804552f7358SJed Brown 8059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 8079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 8089566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8099566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 8109566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8119566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 81263a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 81363a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 81463a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 81563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 8169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 81763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 818552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 819552f7358SJed Brown PetscInt dof, off, s; 820552f7358SJed Brown 8219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 823552f7358SJed Brown for (s = off; s < off+dof; ++s) { 82463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 825552f7358SJed Brown } 826552f7358SJed Brown } 8279566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 82863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 82963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 830552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 831552f7358SJed Brown PetscInt dof, off, c; 832552f7358SJed Brown 8339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 8349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 835552f7358SJed Brown for (c = off; c < off+dof; ++c) { 83663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c])); 837552f7358SJed Brown } 838552f7358SJed Brown } 8399566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8413d2e540fSStefano Zampini if (coordSection && coordinates) { 84219ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 8436858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 8446858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 84519ad8254SMatthew G. Knepley PetscMPIInt rank; 84619ad8254SMatthew G. Knepley const char *name; 84719ad8254SMatthew G. Knepley 8489566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL)); 8499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 8509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 85163a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 8529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 8536858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 8546858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 8556858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 8566858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 8579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) coordinates, &name)); 85863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 85963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 8609566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 86119ad8254SMatthew G. Knepley 8629566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 8636858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 8649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 8659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 86619ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 86719ad8254SMatthew G. Knepley PetscInt dof, off; 86819ad8254SMatthew G. Knepley 8696858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 8709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 8719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 8726858538eSMatthew G. Knepley if (dof) { 87363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 8749566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 8759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 87619ad8254SMatthew G. Knepley } 8776858538eSMatthew G. Knepley } 8786858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 8796858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 8806858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 8816858538eSMatthew G. Knepley if (dof) { 8826858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 8836858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 8846858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 8856858538eSMatthew G. Knepley } 8866858538eSMatthew G. Knepley } 8876858538eSMatthew G. Knepley } 8889566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8909566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 8916858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 8923d2e540fSStefano Zampini } 8939566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 8949566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 8959318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 8969318fe57SMatthew G. Knepley DMLabel label; 8979318fe57SMatthew G. Knepley PetscBool isdepth; 8989318fe57SMatthew G. Knepley const char *name; 8999318fe57SMatthew G. Knepley 9009566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 9019566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 9029318fe57SMatthew G. Knepley if (isdepth) continue; 9039566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 9049566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 9059318fe57SMatthew G. Knepley } 906552f7358SJed Brown if (size > 1) { 907552f7358SJed Brown PetscSF sf; 908552f7358SJed Brown 9099566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9109566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 911552f7358SJed Brown } 9129566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 913552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 9140588280cSMatthew G. Knepley const char *name, *color; 9150588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 9160588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 917fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 918552f7358SJed Brown PetscReal scale = 2.0; 91978081901SStefano Zampini PetscReal tikzscale = 1.0; 920b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 9210588280cSMatthew G. Knepley double tcoords[3]; 922552f7358SJed Brown PetscScalar *coords; 923b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 924552f7358SJed Brown PetscMPIInt rank, size; 9250588280cSMatthew G. Knepley char **names, **colors, **lcolors; 926b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 927fe1cc32dSStefano Zampini PetscBT wp = NULL; 928fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 929552f7358SJed Brown 9309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9329566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 9330588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 9340588280cSMatthew G. Knepley numColors = 10; 9350588280cSMatthew G. Knepley numLColors = 10; 9369566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 9379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 9389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 9399566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 940b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 941b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 942b7f6ffafSMatthew G. Knepley n = 4; 9439566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 9441dca8a05SBarry 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); 9459566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 9461dca8a05SBarry 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); 9479566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 9480588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 9499566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 9500588280cSMatthew G. Knepley if (!useColors) { 9510588280cSMatthew G. Knepley numColors = 3; 9529566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 9530588280cSMatthew G. Knepley } 9549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 9550588280cSMatthew G. Knepley if (!useColors) { 9560588280cSMatthew G. Knepley numLColors = 4; 9579566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 9580588280cSMatthew G. Knepley } 9599566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 960b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 9619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 9621dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 963202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 9649566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 965fe1cc32dSStefano Zampini 966fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 9679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9709566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 971fe1cc32dSStefano Zampini if (lflg) { 972fe1cc32dSStefano Zampini DMLabel lbl; 973fe1cc32dSStefano Zampini 9749566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 975fe1cc32dSStefano Zampini if (lbl) { 976fe1cc32dSStefano Zampini PetscInt val, defval; 977fe1cc32dSStefano Zampini 9789566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 9799566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd-pStart, &wp)); 980fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 981fe1cc32dSStefano Zampini PetscInt *closure = NULL; 982fe1cc32dSStefano Zampini PetscInt closureSize; 983fe1cc32dSStefano Zampini 9849566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 985fe1cc32dSStefano Zampini if (val == defval) continue; 986fe1cc32dSStefano Zampini 9879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 988fe1cc32dSStefano Zampini for (p = 0; p < closureSize*2; p += 2) { 9899566063dSJacob Faibussowitsch PetscCall(PetscBTSet(wp, closure[p] - pStart)); 990fe1cc32dSStefano Zampini } 9919566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 992fe1cc32dSStefano Zampini } 993fe1cc32dSStefano Zampini } 994fe1cc32dSStefano Zampini } 995fe1cc32dSStefano Zampini 9969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 9999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 10000588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1001552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1002552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1003552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 10045f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 10050588280cSMatthew G. Knepley if (size > 1) { 10069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1007770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 100863a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size-1) ? ", and " : ", ")); 100963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p%numColors], p)); 1010770b213bSMatthew G Knepley } 10119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 10120588280cSMatthew G. Knepley } 1013b7f6ffafSMatthew G. Knepley if (drawHasse) { 1014b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 1015b7f6ffafSMatthew G. Knepley 101663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 101763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd-1)); 101863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd-vStart)); 10199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.)); 102063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 102163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd-1)); 10229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.)); 102363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd-eStart)); 102463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 102563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd-1)); 102663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd-cStart)); 10279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.)); 1028b7f6ffafSMatthew G. Knepley } 10299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale)); 1030fe1cc32dSStefano Zampini 1031552f7358SJed Brown /* Plot vertices */ 10329566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1034552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1035552f7358SJed Brown PetscInt off, dof, d; 10360588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1037552f7358SJed Brown 1038fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,v - pStart)) continue; 10399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 10409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 10419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 104263a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3",v,dof); 10430588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10440588280cSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1045c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 10460588280cSMatthew G. Knepley } 10470588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 10480588280cSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1049552f7358SJed Brown for (d = 0; d < dof; ++d) { 10509566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d])); 1052552f7358SJed Brown } 1053b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0%numColors]; 1054b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 10550588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10560588280cSMatthew G. Knepley PetscInt val; 10579566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 10580588280cSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 10590588280cSMatthew G. Knepley } 1060b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 106163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1062b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 106363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 10641baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1065552f7358SJed Brown } 10669566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 10679566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1068b7f6ffafSMatthew G. Knepley /* Plot edges */ 1069b7f6ffafSMatthew G. Knepley if (plotEdges) { 10709566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1072b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1073b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1074b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1075b7f6ffafSMatthew G. Knepley 1076b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp,e - pStart)) continue; 10779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 107863a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 10799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 10809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 10819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 10829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 10839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1084b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1085b7f6ffafSMatthew G. Knepley tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 1086b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1087b7f6ffafSMatthew G. Knepley } 1088b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1089b7f6ffafSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1090b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10919566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1093b7f6ffafSMatthew G. Knepley } 1094b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1%numColors]; 1095b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 1096b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1097b7f6ffafSMatthew G. Knepley PetscInt val; 10989566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 1099b7f6ffafSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 1100b7f6ffafSMatthew G. Knepley } 110163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1102b7f6ffafSMatthew G. Knepley } 11039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 11049566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 11059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1106b7f6ffafSMatthew G. Knepley } 1107846a3e8bSMatthew G. Knepley /* Plot cells */ 1108b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1109846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1110846a3e8bSMatthew G. Knepley const PetscInt *cone; 1111846a3e8bSMatthew G. Knepley 1112fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1113846a3e8bSMatthew G. Knepley color = colors[rank%numColors]; 1114846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1115846a3e8bSMatthew G. Knepley PetscInt val; 11169566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 1117846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 1118846a3e8bSMatthew G. Knepley } 11199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 112063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1121846a3e8bSMatthew G. Knepley } 1122846a3e8bSMatthew G. Knepley } else { 1123b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1124846a3e8bSMatthew G. Knepley 1125b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1126b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1127fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 11289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1129b7f6ffafSMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1130b7f6ffafSMatthew G. Knepley ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1131b7f6ffafSMatthew G. Knepley ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1132b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1133b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1134b7f6ffafSMatthew G. Knepley 11359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 11369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1137b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1138b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1139b7f6ffafSMatthew G. Knepley 11409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 114163a3b9bcSJacob 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)); 1142b7f6ffafSMatthew G. Knepley } 1143b7f6ffafSMatthew G. Knepley } else { 1144b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1145b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1146b7f6ffafSMatthew G. Knepley 11479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1148846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 1149846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1150846a3e8bSMatthew G. Knepley 1151b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1152846a3e8bSMatthew G. Knepley } 11539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors])); 1154b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1155b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v%Nv]; 1156b7f6ffafSMatthew G. Knepley 1157b7f6ffafSMatthew G. Knepley if (v > 0) { 1158b7f6ffafSMatthew G. Knepley if (plotEdges) { 1159b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1160b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1161b7f6ffafSMatthew G. Knepley 1162b7f6ffafSMatthew G. Knepley endpoints[0] = closure[v-1]; endpoints[1] = vertex; 11639566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 116463a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 116563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 11669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 11671baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1168b7f6ffafSMatthew G. Knepley } 116963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1170b7f6ffafSMatthew G. Knepley } 11719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 11729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1173846a3e8bSMatthew G. Knepley } 1174846a3e8bSMatthew G. Knepley } 1175b7f6ffafSMatthew G. Knepley } 11769566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1177846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1178846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1179846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1180846a3e8bSMatthew G. Knepley PetscInt *closure = NULL; 1181846a3e8bSMatthew G. Knepley PetscInt closureSize, dof, d, n = 0; 1182846a3e8bSMatthew G. Knepley 1183fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,c - pStart)) continue; 11849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 11859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1186846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 1187846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1188846a3e8bSMatthew G. Knepley PetscInt off; 1189846a3e8bSMatthew G. Knepley 1190846a3e8bSMatthew G. Knepley if ((point < vStart) || (point >= vEnd)) continue; 11919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 11929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 1193846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1194846a3e8bSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1195846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1196846a3e8bSMatthew G. Knepley } 1197846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1198846a3e8bSMatthew G. Knepley if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1199846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1200846a3e8bSMatthew G. Knepley ++n; 1201846a3e8bSMatthew G. Knepley } 1202846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 12039566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1204846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12059566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d])); 1207846a3e8bSMatthew G. Knepley } 1208b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth%numColors]; 1209b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 1210846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1211846a3e8bSMatthew G. Knepley PetscInt val; 12129566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 1213846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1214846a3e8bSMatthew G. Knepley } 1215b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 121663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1217b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 121863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 12191baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1220846a3e8bSMatthew G. Knepley } 12219566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 1222b7f6ffafSMatthew G. Knepley if (drawHasse) { 1223b7f6ffafSMatthew G. Knepley color = colors[depth%numColors]; 12249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 12259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 12269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 12289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1229552f7358SJed Brown 1230b7f6ffafSMatthew G. Knepley color = colors[1%numColors]; 12319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 12329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 12339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 12359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1236b7f6ffafSMatthew G. Knepley 1237b7f6ffafSMatthew G. Knepley color = colors[0%numColors]; 12389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 12399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 12409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 12429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1243b7f6ffafSMatthew G. Knepley 1244b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1245b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1246b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1247b7f6ffafSMatthew G. Knepley 12489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 12499566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1250b7f6ffafSMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 125163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank)); 1252552f7358SJed Brown } 12530588280cSMatthew G. Knepley } 12540588280cSMatthew G. Knepley } 12559566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 12579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 125863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 12599566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 12609566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 12619566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 12629566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 12639566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 12640f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 12650f7d6e4aSStefano Zampini Vec cown,acown; 12660f7d6e4aSStefano Zampini VecScatter sct; 12670f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 12680f7d6e4aSStefano Zampini IS gid,acis; 12690f7d6e4aSStefano Zampini MPI_Comm comm,ncomm = MPI_COMM_NULL; 12700f7d6e4aSStefano Zampini MPI_Group ggroup,ngroup; 12710f7d6e4aSStefano Zampini PetscScalar *array,nid; 12720f7d6e4aSStefano Zampini const PetscInt *idxs; 12730f7d6e4aSStefano Zampini PetscInt *idxs2,*start,*adjacency,*work; 12740f7d6e4aSStefano Zampini PetscInt64 lm[3],gm[3]; 12750f7d6e4aSStefano Zampini PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 12760f7d6e4aSStefano Zampini PetscMPIInt d1,d2,rank; 12770f7d6e4aSStefano Zampini 12789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm,&comm)); 12799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 1280b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 12819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm)); 12820f7d6e4aSStefano Zampini #endif 12830f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 12849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm,&ggroup)); 12859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm,&ngroup)); 12860f7d6e4aSStefano Zampini d1 = 0; 12879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2)); 12880f7d6e4aSStefano Zampini nid = d2; 12899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 12909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 12919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 12920f7d6e4aSStefano Zampini } else nid = 0.0; 12930f7d6e4aSStefano Zampini 12940f7d6e4aSStefano Zampini /* Get connectivity */ 12959566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm,&cellHeight)); 12969566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid)); 12970f7d6e4aSStefano Zampini 12980f7d6e4aSStefano Zampini /* filter overlapped local cells */ 12999566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd)); 13009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid,&idxs)); 13019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid,&cum)); 13029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum,&idxs2)); 13030f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 13040f7d6e4aSStefano Zampini if (idxs[c-cStart] < 0) continue; 13050f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c-cStart]; 13060f7d6e4aSStefano Zampini } 13079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid,&idxs)); 130863a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,numVertices,cum); 13099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13109566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid)); 13110f7d6e4aSStefano Zampini 13120f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 13139566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis)); 13149566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown)); 13159566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown)); 13169566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown,&array)); 13170f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 13189566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown,&array)); 13199566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown,acis,acown,NULL,&sct)); 13209566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD)); 13219566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD)); 13229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 13239566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 13249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 13250f7d6e4aSStefano Zampini 13260f7d6e4aSStefano Zampini /* compute edgeCut */ 13270f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 13289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum,&work)); 13299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid,&g2l)); 13309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH)); 13319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13329566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown,&array)); 13330f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 13340f7d6e4aSStefano Zampini PetscInt totl; 13350f7d6e4aSStefano Zampini 13360f7d6e4aSStefano Zampini totl = start[c+1]-start[c]; 13379566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work)); 13380f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 13390f7d6e4aSStefano Zampini if (work[i] < 0) { 13400f7d6e4aSStefano Zampini ect += 1; 13410f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 13420f7d6e4aSStefano Zampini } 13430f7d6e4aSStefano Zampini } 13440f7d6e4aSStefano Zampini } 13459566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 13469566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown,&array)); 13470f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 13480f7d6e4aSStefano Zampini lm[1] = -numVertices; 13491c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm)); 135063a3b9bcSJacob 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])); 13510f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 13520f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 13530f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 13541c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm)); 135563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,", empty %" PetscInt_FMT ")\n",(PetscInt)gm[2])); 1356b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 135763a3b9bcSJacob 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.)); 13580f7d6e4aSStefano Zampini #else 135963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Edge Cut: %" PetscInt_FMT " (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0)); 13600f7d6e4aSStefano Zampini #endif 13619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 13629566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 13639566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 13649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1365552f7358SJed Brown } else { 1366412e9a14SMatthew G. Knepley const char *name; 1367d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1368412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1369d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1370ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 13719318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1372412e9a14SMatthew G. Knepley MPI_Comm comm; 1373412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1374552f7358SJed Brown 13759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 13769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 13779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 13789566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13799566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 13809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 138163a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 138263a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 138363a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 13849566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 13851c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 13869566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd)); 1387d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 13889566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 13899566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1390412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1391412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1392412e9a14SMatthew G. Knepley 13939566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 13949566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1395412e9a14SMatthew G. Knepley ict = ct0; 13969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1397412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType) ict; 1398412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1399412e9a14SMatthew G. Knepley DMPolytopeType ct; 1400412e9a14SMatthew G. Knepley 14019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1402412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1403412e9a14SMatthew G. Knepley else ++Nc[1]; 1404412e9a14SMatthew G. Knepley } 1405ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 14069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 14079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 14089566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 140963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1410834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1411dd400576SPatrick Sanan if (rank == 0) { 141263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]+hybsizes[p])); 141363a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 141463a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1415834065abSMatthew G. Knepley } 1416cbb7f117SMark Adams } 1417ca7bf7eeSMatthew G. Knepley } else { 1418ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1419ca7bf7eeSMatthew G. Knepley 1420ca7bf7eeSMatthew G. Knepley locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1]; 14219566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 1422ca7bf7eeSMatthew G. Knepley locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1]; 14239566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1424ca7bf7eeSMatthew G. Knepley if (d == depth) { 1425ca7bf7eeSMatthew G. Knepley locMinMax[0] = gcNum; locMinMax[1] = gcNum; 14269566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1427ca7bf7eeSMatthew G. Knepley } 142863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 14299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 14309566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 14319566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1432ca7bf7eeSMatthew G. Knepley } 14339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1434552f7358SJed Brown } 14359566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 14369318fe57SMatthew G. Knepley { 14379318fe57SMatthew G. Knepley const PetscReal *maxCell; 14389318fe57SMatthew G. Knepley const PetscReal *L; 14396858538eSMatthew G. Knepley PetscBool localized; 14409318fe57SMatthew G. Knepley 14416858538eSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &L)); 14429566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 14436858538eSMatthew G. Knepley if (L || localized) { 14446858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 14459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 14466858538eSMatthew G. Knepley if (L) { 14476858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 14489318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 14496858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 14506858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 14519318fe57SMatthew G. Knepley } 14526858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 14536858538eSMatthew G. Knepley } 14546858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 14559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14569318fe57SMatthew G. Knepley } 14579318fe57SMatthew G. Knepley } 14589566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 14599566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1460a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1461a57dd577SMatthew G Knepley DMLabel label; 1462a57dd577SMatthew G Knepley const char *name; 1463a57dd577SMatthew G Knepley IS valueIS; 1464a57dd577SMatthew G Knepley const PetscInt *values; 1465a57dd577SMatthew G Knepley PetscInt numValues, v; 1466a57dd577SMatthew G Knepley 14679566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 14689566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 14699566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 147063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 14719566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 14729566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 14739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1474a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1475a57dd577SMatthew G Knepley PetscInt size; 1476a57dd577SMatthew G Knepley 14779566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 14789566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 147963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1480a57dd577SMatthew G Knepley } 14819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 14829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 14849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1485a57dd577SMatthew G Knepley } 1486c1cad2e7SMatthew G. Knepley { 1487c1cad2e7SMatthew G. Knepley char **labelNames; 1488c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1489c1cad2e7SMatthew G. Knepley PetscBool flg; 1490c1cad2e7SMatthew G. Knepley 14919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 14929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1493c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1494c1cad2e7SMatthew G. Knepley DMLabel label; 1495c1cad2e7SMatthew G. Knepley 14969566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1497c1cad2e7SMatthew G. Knepley if (flg) { 14989566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 14999566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1500c1cad2e7SMatthew G. Knepley } 15019566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1502c1cad2e7SMatthew G. Knepley } 15039566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1504c1cad2e7SMatthew G. Knepley } 150534aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 150634aa8a36SMatthew G. Knepley if (dm->Nf) { 150734aa8a36SMatthew G. Knepley PetscInt f; 150834aa8a36SMatthew G. Knepley 150934aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 151034aa8a36SMatthew G. Knepley const char *name; 151134aa8a36SMatthew G. Knepley 15129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 15139566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 15149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15159566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 151634aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 15179566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 15189566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 151934aa8a36SMatthew G. Knepley } else { 15209566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 15219566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 152234aa8a36SMatthew G. Knepley } 15239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 152434aa8a36SMatthew G. Knepley } 152534aa8a36SMatthew G. Knepley } 15269566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 15278e7ff633SMatthew G. Knepley if (cdm) { 15289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15299566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 15309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 15318e7ff633SMatthew G. Knepley } 1532552f7358SJed Brown } 1533552f7358SJed Brown PetscFunctionReturn(0); 1534552f7358SJed Brown } 1535552f7358SJed Brown 1536e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1537e5c487bfSMatthew G. Knepley { 1538e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1539e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1540a12d352dSMatthew G. Knepley PetscInt cdim; 1541e5c487bfSMatthew G. Knepley 1542e5c487bfSMatthew G. Knepley PetscFunctionBegin; 15439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 15449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 15459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1546e5c487bfSMatthew G. Knepley switch (ct) { 1547a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1548a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1549a12d352dSMatthew G. Knepley switch (cdim) { 1550a12d352dSMatthew G. Knepley case 1: 1551a12d352dSMatthew G. Knepley { 1552a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1553a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1554a12d352dSMatthew G. Knepley 15559566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 15569566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK)); 15579566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK)); 1558a12d352dSMatthew G. Knepley } 1559a12d352dSMatthew G. Knepley break; 1560a12d352dSMatthew G. Knepley case 2: 1561a12d352dSMatthew G. Knepley { 1562a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1563a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1564a12d352dSMatthew G. Knepley const PetscReal l = 0.1/PetscSqrtReal(dx*dx + dy*dy); 1565a12d352dSMatthew G. Knepley 15669566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15679566063dSJacob 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)); 15689566063dSJacob 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)); 1569a12d352dSMatthew G. Knepley } 1570a12d352dSMatthew G. Knepley break; 157163a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1572a12d352dSMatthew G. Knepley } 1573a12d352dSMatthew G. Knepley break; 1574e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 15759566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1576e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1577e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15785f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15799566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15809566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15819566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1582e5c487bfSMatthew G. Knepley break; 1583e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 15849566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1585e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1586e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15875f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15889566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1589e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1590e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15915f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15929566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15939566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15949566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 15959566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1596e5c487bfSMatthew G. Knepley break; 159798921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1598e5c487bfSMatthew G. Knepley } 1599e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1600e5c487bfSMatthew G. Knepley } 1601e5c487bfSMatthew G. Knepley 1602e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1603e5c487bfSMatthew G. Knepley { 1604e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1605e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1606e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1607e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1608e5c487bfSMatthew G. Knepley 1609e5c487bfSMatthew G. Knepley PetscFunctionBegin; 16109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 16119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1612e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1613e5c487bfSMatthew G. Knepley switch (ct) { 1614e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 1615e5c487bfSMatthew G. Knepley { 1616e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1617e5c487bfSMatthew G. Knepley 1618e5c487bfSMatthew G. Knepley for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1619e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1620e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e*2+0]; 1621e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e*2+1]; 1622e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1623e5c487bfSMatthew G. Knepley refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1624e5c487bfSMatthew G. Knepley refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1625e5c487bfSMatthew G. Knepley } 16269566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords)); 1627e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 16289566063dSJacob 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)); 16299566063dSJacob 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)); 1630e5c487bfSMatthew G. Knepley } 1631e5c487bfSMatthew G. Knepley } 1632e5c487bfSMatthew G. Knepley } 1633e5c487bfSMatthew G. Knepley break; 163498921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1635e5c487bfSMatthew G. Knepley } 1636e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1637e5c487bfSMatthew G. Knepley } 1638e5c487bfSMatthew G. Knepley 16397cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1640e412dcbdSMatthew G. Knepley { 1641e412dcbdSMatthew G. Knepley PetscDraw draw; 1642e412dcbdSMatthew G. Knepley DM cdm; 1643e412dcbdSMatthew G. Knepley PetscSection coordSection; 1644e412dcbdSMatthew G. Knepley Vec coordinates; 1645e412dcbdSMatthew G. Knepley const PetscScalar *coords; 164629494db1SLisandro Dalcin PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1647e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1648e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1649e5c487bfSMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1650e412dcbdSMatthew G. Knepley 1651e412dcbdSMatthew G. Knepley PetscFunctionBegin; 16529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 165363a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 16549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 16559566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords)); 16569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 16579566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 16589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 16599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 16609566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1661e412dcbdSMatthew G. Knepley 16629566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 16639566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 1664e412dcbdSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 16659566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1666e412dcbdSMatthew G. Knepley 16679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 16689566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 1669e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 16700c81f2a8SMatthew G. Knepley bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 16710c81f2a8SMatthew G. Knepley bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1672e412dcbdSMatthew G. Knepley } 16739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 16741c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm))); 16751c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm))); 16769566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 16779566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1678e412dcbdSMatthew G. Knepley 1679cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1680cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1681ba2698f1SMatthew G. Knepley PetscInt numCoords; 1682cf3064d3SMatthew G. Knepley 16839566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords)); 16841baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 16851baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 16869566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 1687cf3064d3SMatthew G. Knepley } 16889566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 16899566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 16909566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 16919566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 1692e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 1693e412dcbdSMatthew G. Knepley } 1694e412dcbdSMatthew G. Knepley 16951e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 16961e50132fSMatthew G. Knepley #include <exodusII.h> 16976823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 16981e50132fSMatthew G. Knepley #endif 16991e50132fSMatthew G. Knepley 1700552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1701552f7358SJed Brown { 17021e50132fSMatthew G. Knepley PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1703002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1704552f7358SJed Brown 1705552f7358SJed Brown PetscFunctionBegin; 1706552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1707552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii)); 17099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 17109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 17119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 17129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 17139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus)); 1714552f7358SJed Brown if (iascii) { 17158135c375SStefano Zampini PetscViewerFormat format; 17169566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 17171baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 17181baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1719c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1720c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 17219566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1722c6ccd67eSMatthew G. Knepley #else 1723c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1724552f7358SJed Brown #endif 1725e412dcbdSMatthew G. Knepley } else if (isvtk) { 17269566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject) dm,viewer)); 1727e412dcbdSMatthew G. Knepley } else if (isdraw) { 17289566063dSJacob Faibussowitsch PetscCall(DMPlexView_Draw(dm, viewer)); 17298135c375SStefano Zampini } else if (isglvis) { 17309566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 17311e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17321e50132fSMatthew G. Knepley } else if (isexodus) { 17336823f3c5SBlaise Bourdin /* 17346823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 17356823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 17366823f3c5SBlaise Bourdin with ID 1, containig all cells. 17376823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 17386823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 17396823f3c5SBlaise Bourdin */ 17406823f3c5SBlaise Bourdin PetscInt numCS; 17419566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm,"Cell Sets",&numCS)); 17426823f3c5SBlaise Bourdin if (!numCS) { 17431e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 17449566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 17459566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 17469566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 17476823f3c5SBlaise Bourdin } 17489566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 17491e50132fSMatthew G. Knepley #endif 17501baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 17511baa6e33SBarry Smith 1752cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 17539566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg)); 1754cb3ba0daSMatthew G. Knepley if (flg) { 1755cb3ba0daSMatthew G. Knepley Vec ranks; 17569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 17579566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 17589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1759cb3ba0daSMatthew G. Knepley } 1760002a2709SMatthew G. Knepley /* Optionally view a label */ 17619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1762002a2709SMatthew G. Knepley if (flg) { 1763002a2709SMatthew G. Knepley DMLabel label; 1764002a2709SMatthew G. Knepley Vec val; 1765002a2709SMatthew G. Knepley 17669566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 176728b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 17689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 17699566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 17709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1771002a2709SMatthew G. Knepley } 1772552f7358SJed Brown PetscFunctionReturn(0); 1773552f7358SJed Brown } 1774552f7358SJed Brown 17757f96f51bSksagiyam /*@ 17767f96f51bSksagiyam DMPlexTopologyView - Saves a DMPlex topology into a file 17777f96f51bSksagiyam 17787f96f51bSksagiyam Collective on DM 17797f96f51bSksagiyam 17807f96f51bSksagiyam Input Parameters: 17817f96f51bSksagiyam + dm - The DM whose topology is to be saved 17827f96f51bSksagiyam - viewer - The PetscViewer for saving 17837f96f51bSksagiyam 17847f96f51bSksagiyam Level: advanced 17857f96f51bSksagiyam 1786db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()` 17877f96f51bSksagiyam @*/ 17887f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 17897f96f51bSksagiyam { 17907f96f51bSksagiyam PetscBool ishdf5; 17917f96f51bSksagiyam 17927f96f51bSksagiyam PetscFunctionBegin; 17937f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17947f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 17969566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0)); 17977f96f51bSksagiyam if (ishdf5) { 17987f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 17997f96f51bSksagiyam PetscViewerFormat format; 18009566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 18017f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18027f96f51bSksagiyam IS globalPointNumbering; 18037f96f51bSksagiyam 18049566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18059566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 180798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 18087f96f51bSksagiyam #else 18097f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 18107f96f51bSksagiyam #endif 18117f96f51bSksagiyam } 18129566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0)); 18137f96f51bSksagiyam PetscFunctionReturn(0); 18147f96f51bSksagiyam } 18157f96f51bSksagiyam 181677b8e257Sksagiyam /*@ 181777b8e257Sksagiyam DMPlexCoordinatesView - Saves DMPlex coordinates into a file 181877b8e257Sksagiyam 181977b8e257Sksagiyam Collective on DM 182077b8e257Sksagiyam 182177b8e257Sksagiyam Input Parameters: 182277b8e257Sksagiyam + dm - The DM whose coordinates are to be saved 182377b8e257Sksagiyam - viewer - The PetscViewer for saving 182477b8e257Sksagiyam 182577b8e257Sksagiyam Level: advanced 182677b8e257Sksagiyam 1827db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()` 182877b8e257Sksagiyam @*/ 182977b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 183077b8e257Sksagiyam { 183177b8e257Sksagiyam PetscBool ishdf5; 183277b8e257Sksagiyam 183377b8e257Sksagiyam PetscFunctionBegin; 183477b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 183577b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 18379566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0)); 183877b8e257Sksagiyam if (ishdf5) { 183977b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 184077b8e257Sksagiyam PetscViewerFormat format; 18419566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 184277b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18439566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 184498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 184577b8e257Sksagiyam #else 184677b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 184777b8e257Sksagiyam #endif 184877b8e257Sksagiyam } 18499566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0)); 185077b8e257Sksagiyam PetscFunctionReturn(0); 185177b8e257Sksagiyam } 185277b8e257Sksagiyam 1853bd6565f1Sksagiyam /*@ 1854bd6565f1Sksagiyam DMPlexLabelsView - Saves DMPlex labels into a file 1855bd6565f1Sksagiyam 1856bd6565f1Sksagiyam Collective on DM 1857bd6565f1Sksagiyam 1858bd6565f1Sksagiyam Input Parameters: 1859bd6565f1Sksagiyam + dm - The DM whose labels are to be saved 1860bd6565f1Sksagiyam - viewer - The PetscViewer for saving 1861bd6565f1Sksagiyam 1862bd6565f1Sksagiyam Level: advanced 1863bd6565f1Sksagiyam 1864db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()` 1865bd6565f1Sksagiyam @*/ 1866bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1867bd6565f1Sksagiyam { 1868bd6565f1Sksagiyam PetscBool ishdf5; 1869bd6565f1Sksagiyam 1870bd6565f1Sksagiyam PetscFunctionBegin; 1871bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1872bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 18749566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0)); 1875bd6565f1Sksagiyam if (ishdf5) { 1876bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 1877bd6565f1Sksagiyam IS globalPointNumbering; 1878bd6565f1Sksagiyam PetscViewerFormat format; 1879bd6565f1Sksagiyam 18809566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 1881bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18829566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18839566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 188598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1886bd6565f1Sksagiyam #else 1887bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1888bd6565f1Sksagiyam #endif 1889bd6565f1Sksagiyam } 18909566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0)); 1891bd6565f1Sksagiyam PetscFunctionReturn(0); 1892bd6565f1Sksagiyam } 1893bd6565f1Sksagiyam 1894021affd3Sksagiyam /*@ 1895021affd3Sksagiyam DMPlexSectionView - Saves a section associated with a DMPlex 1896021affd3Sksagiyam 1897021affd3Sksagiyam Collective on DM 1898021affd3Sksagiyam 1899021affd3Sksagiyam Input Parameters: 1900021affd3Sksagiyam + dm - The DM that contains the topology on which the section to be saved is defined 1901021affd3Sksagiyam . viewer - The PetscViewer for saving 1902021affd3Sksagiyam - sectiondm - The DM that contains the section to be saved 1903021affd3Sksagiyam 1904021affd3Sksagiyam Level: advanced 1905021affd3Sksagiyam 1906021affd3Sksagiyam Notes: 1907021affd3Sksagiyam 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. 1908021affd3Sksagiyam 1909021affd3Sksagiyam 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. 1910021affd3Sksagiyam 1911db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()` 1912021affd3Sksagiyam @*/ 1913021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1914021affd3Sksagiyam { 1915021affd3Sksagiyam PetscBool ishdf5; 1916021affd3Sksagiyam 1917021affd3Sksagiyam PetscFunctionBegin; 1918021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1919021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1920021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 19229566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0)); 1923021affd3Sksagiyam if (ishdf5) { 1924021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 19259566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 1926021affd3Sksagiyam #else 1927021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1928021affd3Sksagiyam #endif 1929021affd3Sksagiyam } 19309566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0)); 1931021affd3Sksagiyam PetscFunctionReturn(0); 1932021affd3Sksagiyam } 1933021affd3Sksagiyam 19343e97647fSksagiyam /*@ 19353e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 19363e97647fSksagiyam 19373e97647fSksagiyam Collective on DM 19383e97647fSksagiyam 19393e97647fSksagiyam Input Parameters: 19403e97647fSksagiyam + dm - The DM that represents the topology 19413e97647fSksagiyam . viewer - The PetscViewer to save data with 19423e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined 19433e97647fSksagiyam - vec - The global vector to be saved 19443e97647fSksagiyam 19453e97647fSksagiyam Level: advanced 19463e97647fSksagiyam 19473e97647fSksagiyam Notes: 19483e97647fSksagiyam 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. 19493e97647fSksagiyam 19503e97647fSksagiyam Typical calling sequence 19513e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 19523e97647fSksagiyam $ DMSetType(dm, DMPLEX); 19533e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 19543e97647fSksagiyam $ DMClone(dm, §iondm); 19553e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 19563e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 19573e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 19583e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 19593e97647fSksagiyam $ PetscSectionSetUp(section); 19603e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 19613e97647fSksagiyam $ PetscSectionDestroy(§ion); 19623e97647fSksagiyam $ DMGetGlobalVector(sectiondm, &vec); 19633e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 19643e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 19653e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 19663e97647fSksagiyam $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 19673e97647fSksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 19683e97647fSksagiyam $ DMDestroy(§iondm); 19693e97647fSksagiyam $ DMDestroy(&dm); 19703e97647fSksagiyam 1971db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 19723e97647fSksagiyam @*/ 19733e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 19743e97647fSksagiyam { 19753e97647fSksagiyam PetscBool ishdf5; 19763e97647fSksagiyam 19773e97647fSksagiyam PetscFunctionBegin; 19783e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19793e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19803e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19813e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 19823e97647fSksagiyam /* Check consistency */ 19833e97647fSksagiyam { 19843e97647fSksagiyam PetscSection section; 19853e97647fSksagiyam PetscBool includesConstraints; 19863e97647fSksagiyam PetscInt m, m1; 19873e97647fSksagiyam 19889566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 19899566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 19909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 19919566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 19929566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 199363a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 19943e97647fSksagiyam } 19959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19969566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0)); 19973e97647fSksagiyam if (ishdf5) { 19983e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 19999566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20003e97647fSksagiyam #else 20013e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20023e97647fSksagiyam #endif 20033e97647fSksagiyam } 20049566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0)); 20053e97647fSksagiyam PetscFunctionReturn(0); 20063e97647fSksagiyam } 20073e97647fSksagiyam 20083e97647fSksagiyam /*@ 20093e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 20103e97647fSksagiyam 20113e97647fSksagiyam Collective on DM 20123e97647fSksagiyam 20133e97647fSksagiyam Input Parameters: 20143e97647fSksagiyam + dm - The DM that represents the topology 20153e97647fSksagiyam . viewer - The PetscViewer to save data with 20163e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 20173e97647fSksagiyam - vec - The local vector to be saved 20183e97647fSksagiyam 20193e97647fSksagiyam Level: advanced 20203e97647fSksagiyam 20213e97647fSksagiyam Notes: 20223e97647fSksagiyam 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. 20233e97647fSksagiyam 20243e97647fSksagiyam Typical calling sequence 20253e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 20263e97647fSksagiyam $ DMSetType(dm, DMPLEX); 20273e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 20283e97647fSksagiyam $ DMClone(dm, §iondm); 20293e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 20303e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 20313e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 20323e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 20333e97647fSksagiyam $ PetscSectionSetUp(section); 20343e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 20353e97647fSksagiyam $ DMGetLocalVector(sectiondm, &vec); 20363e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 20373e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 20383e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 20393e97647fSksagiyam $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 20403e97647fSksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 20413e97647fSksagiyam $ DMDestroy(§iondm); 20423e97647fSksagiyam $ DMDestroy(&dm); 20433e97647fSksagiyam 2044db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 20453e97647fSksagiyam @*/ 20463e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 20473e97647fSksagiyam { 20483e97647fSksagiyam PetscBool ishdf5; 20493e97647fSksagiyam 20503e97647fSksagiyam PetscFunctionBegin; 20513e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20523e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20533e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 20543e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 20553e97647fSksagiyam /* Check consistency */ 20563e97647fSksagiyam { 20573e97647fSksagiyam PetscSection section; 20583e97647fSksagiyam PetscBool includesConstraints; 20593e97647fSksagiyam PetscInt m, m1; 20603e97647fSksagiyam 20619566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 20629566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 20639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 20649566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 20659566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 206663a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 20673e97647fSksagiyam } 20689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20699566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0)); 20703e97647fSksagiyam if (ishdf5) { 20713e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 20729566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20733e97647fSksagiyam #else 20743e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20753e97647fSksagiyam #endif 20763e97647fSksagiyam } 20779566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0)); 20783e97647fSksagiyam PetscFunctionReturn(0); 20793e97647fSksagiyam } 20803e97647fSksagiyam 20812c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 20822c40f234SMatthew G. Knepley { 2083d4f5a9a0SVaclav Hapla PetscBool ishdf5; 20842c40f234SMatthew G. Knepley 20852c40f234SMatthew G. Knepley PetscFunctionBegin; 20862c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20872c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 2089d4f5a9a0SVaclav Hapla if (ishdf5) { 20902c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 20919c48423bSVaclav Hapla PetscViewerFormat format; 20929566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20939c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 20949566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2095509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20969566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 209798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2098b458e8f1SJose E. Roman PetscFunctionReturn(0); 20992c40f234SMatthew G. Knepley #else 21002c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2101552f7358SJed Brown #endif 210298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2103552f7358SJed Brown } 2104552f7358SJed Brown 2105ea8e1828Sksagiyam /*@ 2106ea8e1828Sksagiyam DMPlexTopologyLoad - Loads a topology into a DMPlex 2107ea8e1828Sksagiyam 2108ea8e1828Sksagiyam Collective on DM 2109ea8e1828Sksagiyam 2110ea8e1828Sksagiyam Input Parameters: 2111ea8e1828Sksagiyam + dm - The DM into which the topology is loaded 2112ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology 2113ea8e1828Sksagiyam 2114dec9e869Sksagiyam Output Parameters: 2115f84dd6b4Sksagiyam . 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 2116dec9e869Sksagiyam 2117ea8e1828Sksagiyam Level: advanced 2118ea8e1828Sksagiyam 2119db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 2120ea8e1828Sksagiyam @*/ 2121f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2122ea8e1828Sksagiyam { 2123ea8e1828Sksagiyam PetscBool ishdf5; 2124ea8e1828Sksagiyam 2125ea8e1828Sksagiyam PetscFunctionBegin; 2126ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2127ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2128f84dd6b4Sksagiyam if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 21299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 21309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0)); 2131ea8e1828Sksagiyam if (ishdf5) { 2132ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2133ea8e1828Sksagiyam PetscViewerFormat format; 21349566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2135ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21369566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 213798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2138ea8e1828Sksagiyam #else 2139ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2140ea8e1828Sksagiyam #endif 2141ea8e1828Sksagiyam } 21429566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0)); 2143ea8e1828Sksagiyam PetscFunctionReturn(0); 2144ea8e1828Sksagiyam } 2145ea8e1828Sksagiyam 21463e701f1cSksagiyam /*@ 21473e701f1cSksagiyam DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 21483e701f1cSksagiyam 21493e701f1cSksagiyam Collective on DM 21503e701f1cSksagiyam 21513e701f1cSksagiyam Input Parameters: 21523e701f1cSksagiyam + dm - The DM into which the coordinates are loaded 2153c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates 2154c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 21553e701f1cSksagiyam 21563e701f1cSksagiyam Level: advanced 21573e701f1cSksagiyam 2158db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 21593e701f1cSksagiyam @*/ 2160c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 21613e701f1cSksagiyam { 21623e701f1cSksagiyam PetscBool ishdf5; 21633e701f1cSksagiyam 21643e701f1cSksagiyam PetscFunctionBegin; 21653e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21663e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2167c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 21689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 21699566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0)); 21703e701f1cSksagiyam if (ishdf5) { 21713e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 21723e701f1cSksagiyam PetscViewerFormat format; 21739566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 21743e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21759566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 217698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 21773e701f1cSksagiyam #else 21783e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21793e701f1cSksagiyam #endif 21803e701f1cSksagiyam } 21819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0)); 21823e701f1cSksagiyam PetscFunctionReturn(0); 21833e701f1cSksagiyam } 21843e701f1cSksagiyam 2185b08ad5deSksagiyam /*@ 2186b08ad5deSksagiyam DMPlexLabelsLoad - Loads labels into a DMPlex 2187b08ad5deSksagiyam 2188b08ad5deSksagiyam Collective on DM 2189b08ad5deSksagiyam 2190b08ad5deSksagiyam Input Parameters: 2191b08ad5deSksagiyam + dm - The DM into which the labels are loaded 2192e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels 2193e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2194b08ad5deSksagiyam 2195b08ad5deSksagiyam Level: advanced 2196b08ad5deSksagiyam 2197e6368b79SVaclav Hapla Notes: 2198e6368b79SVaclav Hapla The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs. 2199e6368b79SVaclav Hapla 2200db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 2201b08ad5deSksagiyam @*/ 2202e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2203b08ad5deSksagiyam { 2204b08ad5deSksagiyam PetscBool ishdf5; 2205b08ad5deSksagiyam 2206b08ad5deSksagiyam PetscFunctionBegin; 2207b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2208b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2209e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 22119566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0)); 2212b08ad5deSksagiyam if (ishdf5) { 2213b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2214b08ad5deSksagiyam PetscViewerFormat format; 2215b08ad5deSksagiyam 22169566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2217b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22189566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 221998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2220b08ad5deSksagiyam #else 2221b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2222b08ad5deSksagiyam #endif 2223b08ad5deSksagiyam } 22249566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0)); 2225b08ad5deSksagiyam PetscFunctionReturn(0); 2226b08ad5deSksagiyam } 2227b08ad5deSksagiyam 2228f84dd6b4Sksagiyam /*@ 2229f84dd6b4Sksagiyam DMPlexSectionLoad - Loads section into a DMPlex 2230f84dd6b4Sksagiyam 2231f84dd6b4Sksagiyam Collective on DM 2232f84dd6b4Sksagiyam 2233f84dd6b4Sksagiyam Input Parameters: 2234f84dd6b4Sksagiyam + dm - The DM that represents the topology 2235f84dd6b4Sksagiyam . viewer - The PetscViewer that represents the on-disk section (sectionA) 2236f84dd6b4Sksagiyam . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2237f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2238f84dd6b4Sksagiyam 2239f84dd6b4Sksagiyam Output Parameters 2240f84dd6b4Sksagiyam + 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) 2241f84dd6b4Sksagiyam - 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) 2242f84dd6b4Sksagiyam 2243f84dd6b4Sksagiyam Level: advanced 2244f84dd6b4Sksagiyam 2245f84dd6b4Sksagiyam Notes: 2246f84dd6b4Sksagiyam 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. 2247f84dd6b4Sksagiyam 2248f84dd6b4Sksagiyam 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. 2249f84dd6b4Sksagiyam 2250f84dd6b4Sksagiyam 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. 2251f84dd6b4Sksagiyam 2252f84dd6b4Sksagiyam Example using 2 processes: 2253f84dd6b4Sksagiyam $ NX (number of points on dm): 4 2254f84dd6b4Sksagiyam $ sectionA : the on-disk section 2255f84dd6b4Sksagiyam $ vecA : a vector associated with sectionA 2256f84dd6b4Sksagiyam $ sectionB : sectiondm's local section constructed in this function 2257f84dd6b4Sksagiyam $ vecB (local) : a vector associated with sectiondm's local section 2258f84dd6b4Sksagiyam $ vecB (global) : a vector associated with sectiondm's global section 2259f84dd6b4Sksagiyam $ 2260f84dd6b4Sksagiyam $ rank 0 rank 1 2261f84dd6b4Sksagiyam $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2262f84dd6b4Sksagiyam $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2263f84dd6b4Sksagiyam $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2264f84dd6b4Sksagiyam $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2265f84dd6b4Sksagiyam $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2266f84dd6b4Sksagiyam $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2267f84dd6b4Sksagiyam $ sectionB->atlasDof : 1 0 1 | 1 3 2268f84dd6b4Sksagiyam $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2269f84dd6b4Sksagiyam $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2270f84dd6b4Sksagiyam $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2271f84dd6b4Sksagiyam $ 2272f84dd6b4Sksagiyam $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2273f84dd6b4Sksagiyam 2274db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()` 2275f84dd6b4Sksagiyam @*/ 2276f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2277f84dd6b4Sksagiyam { 2278f84dd6b4Sksagiyam PetscBool ishdf5; 2279f84dd6b4Sksagiyam 2280f84dd6b4Sksagiyam PetscFunctionBegin; 2281f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2282f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2283f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2284f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2285f84dd6b4Sksagiyam if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2286f84dd6b4Sksagiyam if (localDofSF) PetscValidPointer(localDofSF, 6); 22879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 22889566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0)); 2289f84dd6b4Sksagiyam if (ishdf5) { 2290f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 22919566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2292f84dd6b4Sksagiyam #else 2293f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2294f84dd6b4Sksagiyam #endif 2295f84dd6b4Sksagiyam } 22969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0)); 2297f84dd6b4Sksagiyam PetscFunctionReturn(0); 2298f84dd6b4Sksagiyam } 2299f84dd6b4Sksagiyam 23008be3dfe1Sksagiyam /*@ 23018be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 23028be3dfe1Sksagiyam 23038be3dfe1Sksagiyam Collective on DM 23048be3dfe1Sksagiyam 23058be3dfe1Sksagiyam Input Parameters: 23068be3dfe1Sksagiyam + dm - The DM that represents the topology 23078be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23088be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined 23098be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23108be3dfe1Sksagiyam - vec - The global vector to set values of 23118be3dfe1Sksagiyam 23128be3dfe1Sksagiyam Level: advanced 23138be3dfe1Sksagiyam 23148be3dfe1Sksagiyam Notes: 23158be3dfe1Sksagiyam 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. 23168be3dfe1Sksagiyam 23178be3dfe1Sksagiyam Typical calling sequence 23188be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23198be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23208be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23218be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23228be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23238be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23248be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 23258be3dfe1Sksagiyam $ DMGetGlobalVector(sectiondm, &vec); 23268be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23278be3dfe1Sksagiyam $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 23288be3dfe1Sksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 23298be3dfe1Sksagiyam $ PetscSFDestroy(&gsf); 23308be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 23318be3dfe1Sksagiyam $ DMDestroy(§iondm); 23328be3dfe1Sksagiyam $ DMDestroy(&dm); 23338be3dfe1Sksagiyam 2334db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()` 23358be3dfe1Sksagiyam @*/ 23368be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 23378be3dfe1Sksagiyam { 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 @*/ 24088be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 24098be3dfe1Sksagiyam { 24108be3dfe1Sksagiyam PetscBool ishdf5; 24118be3dfe1Sksagiyam 24128be3dfe1Sksagiyam PetscFunctionBegin; 24138be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24148be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24158be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24168be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24178be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24188be3dfe1Sksagiyam /* Check consistency */ 24198be3dfe1Sksagiyam { 24208be3dfe1Sksagiyam PetscSection section; 24218be3dfe1Sksagiyam PetscBool includesConstraints; 24228be3dfe1Sksagiyam PetscInt m, m1; 24238be3dfe1Sksagiyam 24249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 24259566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 24269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24279566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 24289566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 242963a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 24308be3dfe1Sksagiyam } 24319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 24329566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0)); 24338be3dfe1Sksagiyam if (ishdf5) { 24348be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 24359566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 24368be3dfe1Sksagiyam #else 24378be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24388be3dfe1Sksagiyam #endif 24398be3dfe1Sksagiyam } 24409566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0)); 24418be3dfe1Sksagiyam PetscFunctionReturn(0); 24428be3dfe1Sksagiyam } 24438be3dfe1Sksagiyam 2444552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm) 2445552f7358SJed Brown { 2446552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2447552f7358SJed Brown 2448552f7358SJed Brown PetscFunctionBegin; 24499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL)); 24509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL)); 24519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL)); 24529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL)); 24532e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C", NULL)); 24542e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C", NULL)); 24552e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C", NULL)); 24562e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C", NULL)); 24572e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",NULL)); 24586bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderGetDefault_C", NULL)); 24596bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderSetDefault_C", NULL)); 2460c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",NULL)); 2461c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexSetOverlap_C",NULL)); 24620d644c17SKarl Rupp if (--mesh->refct > 0) PetscFunctionReturn(0); 24639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 24649566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 24659566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 24669566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 24679566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 24689566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 24699566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->facesTmp)); 24709566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 24719566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 24729566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 24739566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 24749566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 24759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 24769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 24779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 24789566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 24799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 24809566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 24819566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 24829566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 24839566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 24849566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 24859566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 24869566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 24879566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 24889566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2489552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 24909566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 2491552f7358SJed Brown PetscFunctionReturn(0); 2492552f7358SJed Brown } 2493552f7358SJed Brown 2494b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2495552f7358SJed Brown { 24968d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2497acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 24989fca9976SJed Brown PetscInt localSize, localStart = 0; 2499837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2500b412c318SBarry Smith MatType mtype; 25011428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2502552f7358SJed Brown 2503552f7358SJed Brown PetscFunctionBegin; 25049566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2505b412c318SBarry Smith mtype = dm->mattype; 25069566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 25079566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 25089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 25099fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm))); 25109566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 25119566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 25129566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 25139566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 25149566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2515acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 25169566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 25179566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 25189566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 25199566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 25209566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 25219566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 25229566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 25239566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2524552f7358SJed Brown if (!isShell) { 2525837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 25269fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2527fad22124SMatthew G Knepley PetscInt pStart, pEnd, p, dof, cdof; 2528552f7358SJed Brown 25299566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm,<og)); 25309fca9976SJed Brown 25319fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 25329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2533e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 25349fca9976SJed Brown PetscInt bdof, offset; 2535a9d99c84SMatthew G. Knepley 25369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 25379fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 25389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 25399fca9976SJed Brown for (PetscInt i=0; i < dof - cdof; i++) 25409fca9976SJed Brown pblocks[offset - localStart + i] = dof - cdof; 25411d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof+1) : dof; 25421d17a0a3SMatthew G. Knepley bdof = cdof && (dof-cdof) ? 1 : dof; 25431d17a0a3SMatthew G. Knepley if (dof) { 25441d17a0a3SMatthew G. Knepley if (bs < 0) {bs = bdof;} 25459fca9976SJed Brown else if (bs != bdof) {bs = 1;} 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 25699fca9976SJed Brown for (PetscInt j=1; j<pblocks[i]; j++) { 25709fca9976SJed Brown 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]); 25719fca9976SJed Brown } 25729fca9976SJed Brown } 25739fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 25749fca9976SJed Brown } 25759fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2576aa0f6e3cSJed Brown } 25779566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 2578552f7358SJed Brown PetscFunctionReturn(0); 2579552f7358SJed Brown } 2580552f7358SJed Brown 25817cd05799SMatthew G. Knepley /*@ 2582a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2583be36d101SStefano Zampini 2584be36d101SStefano Zampini Not collective 2585be36d101SStefano Zampini 2586be36d101SStefano Zampini Input Parameter: 2587be36d101SStefano Zampini . mesh - The DMPlex 2588be36d101SStefano Zampini 2589be36d101SStefano Zampini Output Parameters: 2590be36d101SStefano Zampini . subsection - The subdomain section 2591be36d101SStefano Zampini 2592be36d101SStefano Zampini Level: developer 2593be36d101SStefano Zampini 2594be36d101SStefano Zampini .seealso: 25957cd05799SMatthew G. Knepley @*/ 2596be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2597be36d101SStefano Zampini { 2598be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex*) dm->data; 2599be36d101SStefano Zampini 2600be36d101SStefano Zampini PetscFunctionBegin; 2601be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2602be36d101SStefano Zampini if (!mesh->subdomainSection) { 2603be36d101SStefano Zampini PetscSection section; 2604be36d101SStefano Zampini PetscSF sf; 2605be36d101SStefano Zampini 26069566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sf)); 26079566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm,§ion)); 26089566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection)); 26099566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2610be36d101SStefano Zampini } 2611be36d101SStefano Zampini *subsection = mesh->subdomainSection; 2612be36d101SStefano Zampini PetscFunctionReturn(0); 2613be36d101SStefano Zampini } 2614be36d101SStefano Zampini 2615552f7358SJed Brown /*@ 2616552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2617552f7358SJed Brown 2618552f7358SJed Brown Not collective 2619552f7358SJed Brown 2620552f7358SJed Brown Input Parameter: 2621552f7358SJed Brown . mesh - The DMPlex 2622552f7358SJed Brown 2623552f7358SJed Brown Output Parameters: 2624552f7358SJed Brown + pStart - The first mesh point 2625552f7358SJed Brown - pEnd - The upper bound for mesh points 2626552f7358SJed Brown 2627552f7358SJed Brown Level: beginner 2628552f7358SJed Brown 2629db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()` 2630552f7358SJed Brown @*/ 2631552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2632552f7358SJed Brown { 2633552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2634552f7358SJed Brown 2635552f7358SJed Brown PetscFunctionBegin; 2636552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 2638552f7358SJed Brown PetscFunctionReturn(0); 2639552f7358SJed Brown } 2640552f7358SJed Brown 2641552f7358SJed Brown /*@ 2642552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2643552f7358SJed Brown 2644552f7358SJed Brown Not collective 2645552f7358SJed Brown 2646552f7358SJed Brown Input Parameters: 2647552f7358SJed Brown + mesh - The DMPlex 2648552f7358SJed Brown . pStart - The first mesh point 2649552f7358SJed Brown - pEnd - The upper bound for mesh points 2650552f7358SJed Brown 2651552f7358SJed Brown Output Parameters: 2652552f7358SJed Brown 2653552f7358SJed Brown Level: beginner 2654552f7358SJed Brown 2655db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()` 2656552f7358SJed Brown @*/ 2657552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2658552f7358SJed Brown { 2659552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2660552f7358SJed Brown 2661552f7358SJed Brown PetscFunctionBegin; 2662552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 26649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 2665552f7358SJed Brown PetscFunctionReturn(0); 2666552f7358SJed Brown } 2667552f7358SJed Brown 2668552f7358SJed Brown /*@ 2669eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2670552f7358SJed Brown 2671552f7358SJed Brown Not collective 2672552f7358SJed Brown 2673552f7358SJed Brown Input Parameters: 2674552f7358SJed Brown + mesh - The DMPlex 2675eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2676552f7358SJed Brown 2677552f7358SJed Brown Output Parameter: 2678552f7358SJed Brown . size - The cone size for point p 2679552f7358SJed Brown 2680552f7358SJed Brown Level: beginner 2681552f7358SJed Brown 2682db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2683552f7358SJed Brown @*/ 2684552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2685552f7358SJed Brown { 2686552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2687552f7358SJed Brown 2688552f7358SJed Brown PetscFunctionBegin; 2689552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2690dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 26919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 2692552f7358SJed Brown PetscFunctionReturn(0); 2693552f7358SJed Brown } 2694552f7358SJed Brown 2695552f7358SJed Brown /*@ 2696eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2697552f7358SJed Brown 2698552f7358SJed Brown Not collective 2699552f7358SJed Brown 2700552f7358SJed Brown Input Parameters: 2701552f7358SJed Brown + mesh - The DMPlex 2702eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2703552f7358SJed Brown - size - The cone size for point p 2704552f7358SJed Brown 2705552f7358SJed Brown Output Parameter: 2706552f7358SJed Brown 2707552f7358SJed Brown Note: 2708552f7358SJed Brown This should be called after DMPlexSetChart(). 2709552f7358SJed Brown 2710552f7358SJed Brown Level: beginner 2711552f7358SJed Brown 2712db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2713552f7358SJed Brown @*/ 2714552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2715552f7358SJed Brown { 2716552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2717552f7358SJed Brown 2718552f7358SJed Brown PetscFunctionBegin; 2719552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 2721552f7358SJed Brown PetscFunctionReturn(0); 2722552f7358SJed Brown } 2723552f7358SJed Brown 2724f5a469b9SMatthew G. Knepley /*@ 2725eaf898f9SPatrick Sanan DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2726f5a469b9SMatthew G. Knepley 2727f5a469b9SMatthew G. Knepley Not collective 2728f5a469b9SMatthew G. Knepley 2729f5a469b9SMatthew G. Knepley Input Parameters: 2730f5a469b9SMatthew G. Knepley + mesh - The DMPlex 2731eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2732f5a469b9SMatthew G. Knepley - size - The additional cone size for point p 2733f5a469b9SMatthew G. Knepley 2734f5a469b9SMatthew G. Knepley Output Parameter: 2735f5a469b9SMatthew G. Knepley 2736f5a469b9SMatthew G. Knepley Note: 2737f5a469b9SMatthew G. Knepley This should be called after DMPlexSetChart(). 2738f5a469b9SMatthew G. Knepley 2739f5a469b9SMatthew G. Knepley Level: beginner 2740f5a469b9SMatthew G. Knepley 2741db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2742f5a469b9SMatthew G. Knepley @*/ 2743f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2744f5a469b9SMatthew G. Knepley { 2745f5a469b9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 2746f5a469b9SMatthew G. Knepley PetscFunctionBegin; 2747f5a469b9SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27489566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->coneSection, p, size)); 2749f5a469b9SMatthew G. Knepley PetscFunctionReturn(0); 2750f5a469b9SMatthew G. Knepley } 2751f5a469b9SMatthew G. Knepley 2752552f7358SJed Brown /*@C 2753eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2754552f7358SJed Brown 2755552f7358SJed Brown Not collective 2756552f7358SJed Brown 2757552f7358SJed Brown Input Parameters: 2758833c876bSVaclav Hapla + dm - The DMPlex 2759eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2760552f7358SJed Brown 2761552f7358SJed Brown Output Parameter: 2762552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 2763552f7358SJed Brown 2764552f7358SJed Brown Level: beginner 2765552f7358SJed Brown 27663813dfbdSMatthew G Knepley Fortran Notes: 27673813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 27683813dfbdSMatthew G Knepley include petsc.h90 in your code. 2769922102d1SVaclav Hapla You must also call DMPlexRestoreCone() after you finish using the returned array. 2770922102d1SVaclav Hapla DMPlexRestoreCone() is not needed/available in C. 27713813dfbdSMatthew G Knepley 2772db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()` 2773552f7358SJed Brown @*/ 2774552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2775552f7358SJed Brown { 2776552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2777552f7358SJed Brown PetscInt off; 2778552f7358SJed Brown 2779552f7358SJed Brown PetscFunctionBegin; 2780552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2781552f7358SJed Brown PetscValidPointer(cone, 3); 27829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 2783552f7358SJed Brown *cone = &mesh->cones[off]; 2784552f7358SJed Brown PetscFunctionReturn(0); 2785552f7358SJed Brown } 2786552f7358SJed Brown 27870ce7577fSVaclav Hapla /*@C 27880ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 27890ce7577fSVaclav Hapla 27900ce7577fSVaclav Hapla Not collective 27910ce7577fSVaclav Hapla 27920ce7577fSVaclav Hapla Input Parameters: 27930ce7577fSVaclav Hapla + dm - The DMPlex 27940ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 27950ce7577fSVaclav Hapla 2796d8d19677SJose E. Roman Output Parameters: 27970ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones 27980ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p 27990ce7577fSVaclav Hapla 28000ce7577fSVaclav Hapla Level: intermediate 28010ce7577fSVaclav Hapla 2802db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()` 28030ce7577fSVaclav Hapla @*/ 28040ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 28050ce7577fSVaclav Hapla { 28060ce7577fSVaclav Hapla PetscSection cs, newcs; 28070ce7577fSVaclav Hapla PetscInt *cones; 28080ce7577fSVaclav Hapla PetscInt *newarr=NULL; 28090ce7577fSVaclav Hapla PetscInt n; 28100ce7577fSVaclav Hapla 28110ce7577fSVaclav Hapla PetscFunctionBegin; 28129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 28139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 28149566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL)); 28150ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 28160ce7577fSVaclav Hapla if (pCones) { 28179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 28189566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 28190ce7577fSVaclav Hapla } 28200ce7577fSVaclav Hapla PetscFunctionReturn(0); 28210ce7577fSVaclav Hapla } 28220ce7577fSVaclav Hapla 2823af9eab45SVaclav Hapla /*@ 2824af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2825d4636a37SVaclav Hapla 2826d4636a37SVaclav Hapla Not collective 2827d4636a37SVaclav Hapla 2828d4636a37SVaclav Hapla Input Parameters: 2829d4636a37SVaclav Hapla + dm - The DMPlex 2830af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2831d4636a37SVaclav Hapla 2832d4636a37SVaclav Hapla Output Parameter: 2833af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 2834d4636a37SVaclav Hapla 2835d4636a37SVaclav Hapla Level: advanced 2836d4636a37SVaclav Hapla 2837af9eab45SVaclav Hapla Notes: 2838af9eab45SVaclav Hapla Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2839af9eab45SVaclav Hapla There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2840af9eab45SVaclav Hapla 2841db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()` 2842d4636a37SVaclav Hapla @*/ 2843af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2844d4636a37SVaclav Hapla { 2845af9eab45SVaclav Hapla IS *expandedPointsAll; 2846af9eab45SVaclav Hapla PetscInt depth; 2847d4636a37SVaclav Hapla 2848d4636a37SVaclav Hapla PetscFunctionBegin; 2849af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2850af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2851af9eab45SVaclav Hapla PetscValidPointer(expandedPoints, 3); 28529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2853af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 28549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 28559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2856af9eab45SVaclav Hapla PetscFunctionReturn(0); 2857af9eab45SVaclav Hapla } 2858af9eab45SVaclav Hapla 2859af9eab45SVaclav Hapla /*@ 2860af9eab45SVaclav 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). 2861af9eab45SVaclav Hapla 2862af9eab45SVaclav Hapla Not collective 2863af9eab45SVaclav Hapla 2864af9eab45SVaclav Hapla Input Parameters: 2865af9eab45SVaclav Hapla + dm - The DMPlex 2866af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2867af9eab45SVaclav Hapla 2868d8d19677SJose E. Roman Output Parameters: 2869af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2870af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 2871af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2872af9eab45SVaclav Hapla 2873af9eab45SVaclav Hapla Level: advanced 2874af9eab45SVaclav Hapla 2875af9eab45SVaclav Hapla Notes: 2876af9eab45SVaclav Hapla Like DMPlexGetConeTuple() but recursive. 2877af9eab45SVaclav Hapla 2878af9eab45SVaclav 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. 2879af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2880af9eab45SVaclav Hapla 2881af9eab45SVaclav 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: 2882af9eab45SVaclav Hapla (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2883af9eab45SVaclav Hapla (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2884af9eab45SVaclav Hapla 2885db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2886af9eab45SVaclav Hapla @*/ 2887af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2888af9eab45SVaclav Hapla { 2889af9eab45SVaclav Hapla const PetscInt *arr0=NULL, *cone=NULL; 2890af9eab45SVaclav Hapla PetscInt *arr=NULL, *newarr=NULL; 2891af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 2892af9eab45SVaclav Hapla IS *expandedPoints_; 2893af9eab45SVaclav Hapla PetscSection *sections_; 2894af9eab45SVaclav Hapla 2895af9eab45SVaclav Hapla PetscFunctionBegin; 2896af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2897af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2898af9eab45SVaclav Hapla if (depth) PetscValidIntPointer(depth, 3); 2899af9eab45SVaclav Hapla if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2900af9eab45SVaclav Hapla if (sections) PetscValidPointer(sections, 5); 29019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 29029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 29039566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29049566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 29059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 2906af9eab45SVaclav Hapla arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2907af9eab45SVaclav Hapla for (d=depth_-1; d>=0; d--) { 29089566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 29099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 2910af9eab45SVaclav Hapla for (i=0; i<n; i++) { 29119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d+1, &start, &end)); 2912af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 29139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 29149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 2915af9eab45SVaclav Hapla } else { 29169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 2917af9eab45SVaclav Hapla } 2918af9eab45SVaclav Hapla } 29199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 29209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 29219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 2922af9eab45SVaclav Hapla for (i=0; i<n; i++) { 29239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 29249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 2925af9eab45SVaclav Hapla if (cn > 1) { 29269566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 29279566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt))); 2928af9eab45SVaclav Hapla } else { 2929af9eab45SVaclav Hapla newarr[co] = arr[i]; 2930af9eab45SVaclav Hapla } 2931af9eab45SVaclav Hapla } 29329566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 2933af9eab45SVaclav Hapla arr = newarr; 2934af9eab45SVaclav Hapla n = newn; 2935af9eab45SVaclav Hapla } 29369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 2937af9eab45SVaclav Hapla *depth = depth_; 2938af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 2939af9eab45SVaclav Hapla else { 29409566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 29419566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 2942af9eab45SVaclav Hapla } 2943af9eab45SVaclav Hapla if (sections) *sections = sections_; 2944af9eab45SVaclav Hapla else { 29459566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 29469566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 2947af9eab45SVaclav Hapla } 2948af9eab45SVaclav Hapla PetscFunctionReturn(0); 2949af9eab45SVaclav Hapla } 2950af9eab45SVaclav Hapla 2951af9eab45SVaclav Hapla /*@ 2952af9eab45SVaclav Hapla DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2953af9eab45SVaclav Hapla 2954af9eab45SVaclav Hapla Not collective 2955af9eab45SVaclav Hapla 2956af9eab45SVaclav Hapla Input Parameters: 2957af9eab45SVaclav Hapla + dm - The DMPlex 2958af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2959af9eab45SVaclav Hapla 2960d8d19677SJose E. Roman Output Parameters: 2961af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2962af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 2963af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2964af9eab45SVaclav Hapla 2965af9eab45SVaclav Hapla Level: advanced 2966af9eab45SVaclav Hapla 2967af9eab45SVaclav Hapla Notes: 2968af9eab45SVaclav Hapla See DMPlexGetConeRecursive() for details. 2969af9eab45SVaclav Hapla 2970db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2971af9eab45SVaclav Hapla @*/ 2972af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2973af9eab45SVaclav Hapla { 2974af9eab45SVaclav Hapla PetscInt d, depth_; 2975af9eab45SVaclav Hapla 2976af9eab45SVaclav Hapla PetscFunctionBegin; 29779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29781dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2979af9eab45SVaclav Hapla if (depth) *depth = 0; 2980af9eab45SVaclav Hapla if (expandedPoints) { 29819566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 29829566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 2983af9eab45SVaclav Hapla } 2984af9eab45SVaclav Hapla if (sections) { 29859566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 29869566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 2987af9eab45SVaclav Hapla } 2988d4636a37SVaclav Hapla PetscFunctionReturn(0); 2989d4636a37SVaclav Hapla } 2990d4636a37SVaclav Hapla 2991552f7358SJed Brown /*@ 299292371b87SBarry 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 2993552f7358SJed Brown 2994552f7358SJed Brown Not collective 2995552f7358SJed Brown 2996552f7358SJed Brown Input Parameters: 2997552f7358SJed Brown + mesh - The DMPlex 2998eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2999552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 3000552f7358SJed Brown 3001552f7358SJed Brown Output Parameter: 3002552f7358SJed Brown 3003552f7358SJed Brown Note: 3004552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3005552f7358SJed Brown 3006552f7358SJed Brown Level: beginner 3007552f7358SJed Brown 3008db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3009552f7358SJed Brown @*/ 3010552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3011552f7358SJed Brown { 3012552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3013552f7358SJed Brown PetscInt pStart, pEnd; 3014552f7358SJed Brown PetscInt dof, off, c; 3015552f7358SJed Brown 3016552f7358SJed Brown PetscFunctionBegin; 3017552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 30199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3020dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(cone, 3); 30219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 302263a3b9bcSJacob 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); 3023552f7358SJed Brown for (c = 0; c < dof; ++c) { 302463a3b9bcSJacob 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); 3025552f7358SJed Brown mesh->cones[off+c] = cone[c]; 3026552f7358SJed Brown } 3027552f7358SJed Brown PetscFunctionReturn(0); 3028552f7358SJed Brown } 3029552f7358SJed Brown 3030552f7358SJed Brown /*@C 3031eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3032552f7358SJed Brown 3033552f7358SJed Brown Not collective 3034552f7358SJed Brown 3035552f7358SJed Brown Input Parameters: 3036552f7358SJed Brown + mesh - The DMPlex 3037eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3038552f7358SJed Brown 3039552f7358SJed Brown Output Parameter: 3040552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 3041b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3042552f7358SJed Brown 3043552f7358SJed Brown Level: beginner 3044552f7358SJed Brown 3045b5a892a1SMatthew G. Knepley Notes: 3046b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3047b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3048b5a892a1SMatthew G. Knepley of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 3049b5a892a1SMatthew G. Knepley with the identity. 3050b5a892a1SMatthew G. Knepley 30513813dfbdSMatthew G Knepley Fortran Notes: 30523813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 30533813dfbdSMatthew G Knepley include petsc.h90 in your code. 30543b12b3d8SVaclav Hapla You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 3055922102d1SVaclav Hapla DMPlexRestoreConeOrientation() is not needed/available in C. 30563813dfbdSMatthew G Knepley 3057db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3058552f7358SJed Brown @*/ 3059552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3060552f7358SJed Brown { 3061552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3062552f7358SJed Brown PetscInt off; 3063552f7358SJed Brown 3064552f7358SJed Brown PetscFunctionBegin; 3065552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 306676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3067552f7358SJed Brown PetscInt dof; 30689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3069552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 3070552f7358SJed Brown } 30719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30720d644c17SKarl Rupp 3073552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 3074552f7358SJed Brown PetscFunctionReturn(0); 3075552f7358SJed Brown } 3076552f7358SJed Brown 3077552f7358SJed Brown /*@ 3078eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3079552f7358SJed Brown 3080552f7358SJed Brown Not collective 3081552f7358SJed Brown 3082552f7358SJed Brown Input Parameters: 3083552f7358SJed Brown + mesh - The DMPlex 3084eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3085b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3086552f7358SJed Brown Output Parameter: 3087552f7358SJed Brown 3088b5a892a1SMatthew G. Knepley Notes: 3089552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3090552f7358SJed Brown 3091b5a892a1SMatthew G. Knepley The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3092b5a892a1SMatthew G. Knepley 3093552f7358SJed Brown Level: beginner 3094552f7358SJed Brown 3095db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3096552f7358SJed Brown @*/ 3097552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3098552f7358SJed Brown { 3099552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3100552f7358SJed Brown PetscInt pStart, pEnd; 3101552f7358SJed Brown PetscInt dof, off, c; 3102552f7358SJed Brown 3103552f7358SJed Brown PetscFunctionBegin; 3104552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 31069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3107dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(coneOrientation, 3); 31089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 310963a3b9bcSJacob 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); 3110552f7358SJed Brown for (c = 0; c < dof; ++c) { 3111552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3112552f7358SJed Brown 31139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof)); 31141dca8a05SBarry 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); 3115552f7358SJed Brown mesh->coneOrientations[off+c] = o; 3116552f7358SJed Brown } 3117552f7358SJed Brown PetscFunctionReturn(0); 3118552f7358SJed Brown } 3119552f7358SJed Brown 31207cd05799SMatthew G. Knepley /*@ 3121eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 31227cd05799SMatthew G. Knepley 31237cd05799SMatthew G. Knepley Not collective 31247cd05799SMatthew G. Knepley 31257cd05799SMatthew G. Knepley Input Parameters: 31267cd05799SMatthew G. Knepley + mesh - The DMPlex 3127eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31287cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31297cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 31307cd05799SMatthew G. Knepley 31317cd05799SMatthew G. Knepley Level: beginner 31327cd05799SMatthew G. Knepley 3133db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31347cd05799SMatthew G. Knepley @*/ 3135552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3136552f7358SJed Brown { 3137552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3138552f7358SJed Brown PetscInt pStart, pEnd; 3139552f7358SJed Brown PetscInt dof, off; 3140552f7358SJed Brown 3141552f7358SJed Brown PetscFunctionBegin; 3142552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 314463a3b9bcSJacob 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); 314563a3b9bcSJacob 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); 31469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 314863a3b9bcSJacob 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); 3149552f7358SJed Brown mesh->cones[off+conePos] = conePoint; 3150552f7358SJed Brown PetscFunctionReturn(0); 3151552f7358SJed Brown } 3152552f7358SJed Brown 31537cd05799SMatthew G. Knepley /*@ 3154eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 31557cd05799SMatthew G. Knepley 31567cd05799SMatthew G. Knepley Not collective 31577cd05799SMatthew G. Knepley 31587cd05799SMatthew G. Knepley Input Parameters: 31597cd05799SMatthew G. Knepley + mesh - The DMPlex 3160eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31617cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31627cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 31637cd05799SMatthew G. Knepley 31647cd05799SMatthew G. Knepley Level: beginner 31657cd05799SMatthew G. Knepley 3166b5a892a1SMatthew G. Knepley Notes: 3167b5a892a1SMatthew G. Knepley The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3168b5a892a1SMatthew G. Knepley 3169db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31707cd05799SMatthew G. Knepley @*/ 317177c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 317277c88f5bSMatthew G Knepley { 317377c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 317477c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 317577c88f5bSMatthew G Knepley PetscInt dof, off; 317677c88f5bSMatthew G Knepley 317777c88f5bSMatthew G Knepley PetscFunctionBegin; 317877c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 318063a3b9bcSJacob 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); 31819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 318363a3b9bcSJacob 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); 318477c88f5bSMatthew G Knepley mesh->coneOrientations[off+conePos] = coneOrientation; 318577c88f5bSMatthew G Knepley PetscFunctionReturn(0); 318677c88f5bSMatthew G Knepley } 318777c88f5bSMatthew G Knepley 3188552f7358SJed Brown /*@ 3189eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3190552f7358SJed Brown 3191552f7358SJed Brown Not collective 3192552f7358SJed Brown 3193552f7358SJed Brown Input Parameters: 3194552f7358SJed Brown + mesh - The DMPlex 3195eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3196552f7358SJed Brown 3197552f7358SJed Brown Output Parameter: 3198552f7358SJed Brown . size - The support size for point p 3199552f7358SJed Brown 3200552f7358SJed Brown Level: beginner 3201552f7358SJed Brown 3202db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3203552f7358SJed Brown @*/ 3204552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3205552f7358SJed Brown { 3206552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3207552f7358SJed Brown 3208552f7358SJed Brown PetscFunctionBegin; 3209552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3210dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 32119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 3212552f7358SJed Brown PetscFunctionReturn(0); 3213552f7358SJed Brown } 3214552f7358SJed Brown 3215552f7358SJed Brown /*@ 3216eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3217552f7358SJed Brown 3218552f7358SJed Brown Not collective 3219552f7358SJed Brown 3220552f7358SJed Brown Input Parameters: 3221552f7358SJed Brown + mesh - The DMPlex 3222eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3223552f7358SJed Brown - size - The support size for point p 3224552f7358SJed Brown 3225552f7358SJed Brown Output Parameter: 3226552f7358SJed Brown 3227552f7358SJed Brown Note: 3228552f7358SJed Brown This should be called after DMPlexSetChart(). 3229552f7358SJed Brown 3230552f7358SJed Brown Level: beginner 3231552f7358SJed Brown 3232db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3233552f7358SJed Brown @*/ 3234552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3235552f7358SJed Brown { 3236552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3237552f7358SJed Brown 3238552f7358SJed Brown PetscFunctionBegin; 3239552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 3241552f7358SJed Brown PetscFunctionReturn(0); 3242552f7358SJed Brown } 3243552f7358SJed Brown 3244552f7358SJed Brown /*@C 3245eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3246552f7358SJed Brown 3247552f7358SJed Brown Not collective 3248552f7358SJed Brown 3249552f7358SJed Brown Input Parameters: 3250552f7358SJed Brown + mesh - The DMPlex 3251eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3252552f7358SJed Brown 3253552f7358SJed Brown Output Parameter: 3254552f7358SJed Brown . support - An array of points which are on the out-edges for point p 3255552f7358SJed Brown 3256552f7358SJed Brown Level: beginner 3257552f7358SJed Brown 32583813dfbdSMatthew G Knepley Fortran Notes: 32593813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 32603813dfbdSMatthew G Knepley include petsc.h90 in your code. 32613b12b3d8SVaclav Hapla You must also call DMPlexRestoreSupport() after you finish using the returned array. 3262922102d1SVaclav Hapla DMPlexRestoreSupport() is not needed/available in C. 32633813dfbdSMatthew G Knepley 3264db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3265552f7358SJed Brown @*/ 3266552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3267552f7358SJed Brown { 3268552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3269552f7358SJed Brown PetscInt off; 3270552f7358SJed Brown 3271552f7358SJed Brown PetscFunctionBegin; 3272552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3273552f7358SJed Brown PetscValidPointer(support, 3); 32749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3275552f7358SJed Brown *support = &mesh->supports[off]; 3276552f7358SJed Brown PetscFunctionReturn(0); 3277552f7358SJed Brown } 3278552f7358SJed Brown 3279552f7358SJed Brown /*@ 328092371b87SBarry 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 3281552f7358SJed Brown 3282552f7358SJed Brown Not collective 3283552f7358SJed Brown 3284552f7358SJed Brown Input Parameters: 3285552f7358SJed Brown + mesh - The DMPlex 3286eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 328792371b87SBarry Smith - support - An array of points which are on the out-edges for point p 3288552f7358SJed Brown 3289552f7358SJed Brown Output Parameter: 3290552f7358SJed Brown 3291552f7358SJed Brown Note: 3292552f7358SJed Brown This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3293552f7358SJed Brown 3294552f7358SJed Brown Level: beginner 3295552f7358SJed Brown 3296db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3297552f7358SJed Brown @*/ 3298552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3299552f7358SJed Brown { 3300552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3301552f7358SJed Brown PetscInt pStart, pEnd; 3302552f7358SJed Brown PetscInt dof, off, c; 3303552f7358SJed Brown 3304552f7358SJed Brown PetscFunctionBegin; 3305552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 3308dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(support, 3); 33099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 331063a3b9bcSJacob 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); 3311552f7358SJed Brown for (c = 0; c < dof; ++c) { 331263a3b9bcSJacob 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); 3313552f7358SJed Brown mesh->supports[off+c] = support[c]; 3314552f7358SJed Brown } 3315552f7358SJed Brown PetscFunctionReturn(0); 3316552f7358SJed Brown } 3317552f7358SJed Brown 33187cd05799SMatthew G. Knepley /*@ 3319eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 33207cd05799SMatthew G. Knepley 33217cd05799SMatthew G. Knepley Not collective 33227cd05799SMatthew G. Knepley 33237cd05799SMatthew G. Knepley Input Parameters: 33247cd05799SMatthew G. Knepley + mesh - The DMPlex 3325eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 33267cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 33277cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 33287cd05799SMatthew G. Knepley 33297cd05799SMatthew G. Knepley Level: beginner 33307cd05799SMatthew G. Knepley 3331db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 33327cd05799SMatthew G. Knepley @*/ 3333552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3334552f7358SJed Brown { 3335552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3336552f7358SJed Brown PetscInt pStart, pEnd; 3337552f7358SJed Brown PetscInt dof, off; 3338552f7358SJed Brown 3339552f7358SJed Brown PetscFunctionBegin; 3340552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 33439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 334463a3b9bcSJacob 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); 334563a3b9bcSJacob 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); 334663a3b9bcSJacob 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); 3347552f7358SJed Brown mesh->supports[off+supportPos] = supportPoint; 3348552f7358SJed Brown PetscFunctionReturn(0); 3349552f7358SJed Brown } 3350552f7358SJed Brown 3351b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3352b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3353b5a892a1SMatthew G. Knepley { 3354b5a892a1SMatthew G. Knepley switch (ct) { 3355b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3356b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3357b5a892a1SMatthew G. Knepley break; 3358b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3359b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3360b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3361b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3362b5a892a1SMatthew G. Knepley break; 3363b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3364b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3365b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3366b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3367b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3368b5a892a1SMatthew G. Knepley break; 3369b5a892a1SMatthew G. Knepley default: return o; 3370b5a892a1SMatthew G. Knepley } 3371b5a892a1SMatthew G. Knepley return o; 3372b5a892a1SMatthew G. Knepley } 3373b5a892a1SMatthew G. Knepley 3374b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3375b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3376b5a892a1SMatthew G. Knepley { 3377b5a892a1SMatthew G. Knepley switch (ct) { 3378b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3379b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3380b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3381b5a892a1SMatthew G. Knepley break; 3382b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3383b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3384b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3385b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3386b5a892a1SMatthew G. Knepley break; 3387b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3388b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3389b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3390b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3391b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3392b5a892a1SMatthew G. Knepley break; 3393b5a892a1SMatthew G. Knepley default: return o; 3394b5a892a1SMatthew G. Knepley } 3395b5a892a1SMatthew G. Knepley return o; 3396b5a892a1SMatthew G. Knepley } 3397b5a892a1SMatthew G. Knepley 3398b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3399b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3400b5a892a1SMatthew G. Knepley { 3401b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3402b5a892a1SMatthew G. Knepley 3403b5a892a1SMatthew G. Knepley PetscFunctionBegin; 34049566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3405b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3406b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3407b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3408b5a892a1SMatthew G. Knepley 34099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 34109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 34119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3412b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3413b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3414b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3415b5a892a1SMatthew G. Knepley 34169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3417b5a892a1SMatthew G. Knepley switch (ct) { 3418b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 34199566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34209566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3421b5a892a1SMatthew G. Knepley break; 3422b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 34239566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 34249566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34259566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3426b5a892a1SMatthew G. Knepley break; 3427b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 34289566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 34299566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34309566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 34319566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3432b5a892a1SMatthew G. Knepley break; 3433b5a892a1SMatthew G. Knepley default: break; 3434b5a892a1SMatthew G. Knepley } 3435b5a892a1SMatthew G. Knepley } 3436b5a892a1SMatthew G. Knepley } 3437b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3438b5a892a1SMatthew G. Knepley } 3439b5a892a1SMatthew G. Knepley 3440012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3441b5a892a1SMatthew G. Knepley { 3442b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3443b5a892a1SMatthew G. Knepley PetscInt *closure; 3444b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3445b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3446b5a892a1SMatthew G. Knepley 3447b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3448b5a892a1SMatthew G. Knepley if (ornt) { 34499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3450b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3451b5a892a1SMatthew G. Knepley } 3452b5a892a1SMatthew G. Knepley if (*points) { 3453b5a892a1SMatthew G. Knepley closure = *points; 3454b5a892a1SMatthew G. Knepley } else { 3455b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 34569566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 34579566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure)); 3458b5a892a1SMatthew G. Knepley } 3459b5a892a1SMatthew G. Knepley if (useCone) { 34609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &tmpSize)); 34619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &tmp)); 34629566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO)); 3463b5a892a1SMatthew G. Knepley } else { 34649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize)); 34659566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &tmp)); 3466b5a892a1SMatthew G. Knepley } 3467b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3468b5a892a1SMatthew G. Knepley closure[off++] = p; 3469b5a892a1SMatthew G. Knepley closure[off++] = 0; 3470b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3471b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3472b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3473b5a892a1SMatthew G. Knepley } 3474b5a892a1SMatthew G. Knepley } else { 34755f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3476b5a892a1SMatthew G. Knepley 3477b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3478b5a892a1SMatthew G. Knepley closure[off++] = p; 3479b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3480b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3481b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3482b5a892a1SMatthew G. Knepley 34839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3484b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3485b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3486b5a892a1SMatthew G. Knepley } 3487b5a892a1SMatthew G. Knepley } 3488b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize+1; 3489b5a892a1SMatthew G. Knepley if (points) *points = closure; 3490b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3491b5a892a1SMatthew G. Knepley } 3492b5a892a1SMatthew G. Knepley 3493b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3494b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3495b5a892a1SMatthew G. Knepley { 3496b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3497b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3498b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3499b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3500b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3501b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3502b5a892a1SMatthew G. Knepley 3503b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 35049566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 35059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 35069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 35079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &ornt)); 35089566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3509b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3510b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3511b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 3512b5a892a1SMatthew G. Knepley if (*points) {pts = *points;} 35139566063dSJacob Faibussowitsch else PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts)); 3514b5a892a1SMatthew G. Knepley c = 0; 3515b5a892a1SMatthew G. Knepley pts[c++] = point; 3516b5a892a1SMatthew G. Knepley pts[c++] = o; 35179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft)); 35189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure)); 3519b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 35209566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure)); 3521b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 35229566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3523b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 35249566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft)); 3525b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d*2+0]]; 3526b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3527b5a892a1SMatthew G. Knepley } 3528b5a892a1SMatthew G. Knepley if (dim >= 3) { 3529b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3530b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d*2+0]]; 3531b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3532b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3533b5a892a1SMatthew G. Knepley 35349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3535b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 35369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize)); 35379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, fpoint, &fcone)); 35389566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt)); 3539b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3540b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc*2+0]]; 3541b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc*2+1]; 3542b5a892a1SMatthew G. Knepley 3543b5a892a1SMatthew G. Knepley for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3544b5a892a1SMatthew G. Knepley if (i == c) { 35459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3546b5a892a1SMatthew G. Knepley pts[c++] = cp; 3547b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3548b5a892a1SMatthew G. Knepley } 3549b5a892a1SMatthew G. Knepley } 3550b5a892a1SMatthew G. Knepley } 3551b5a892a1SMatthew G. Knepley } 3552b5a892a1SMatthew G. Knepley *numPoints = c/2; 3553b5a892a1SMatthew G. Knepley *points = pts; 3554b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3555b5a892a1SMatthew G. Knepley } 3556b5a892a1SMatthew G. Knepley 3557b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3558b5a892a1SMatthew G. Knepley { 3559b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3560b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3561b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3562b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3563b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3564b5a892a1SMatthew G. Knepley 3565b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 35669566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3567b5a892a1SMatthew G. Knepley if (depth == 1) { 35689566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 3569b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3570b5a892a1SMatthew G. Knepley } 35719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3572b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3573b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 35749566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 3575b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3576b5a892a1SMatthew G. Knepley } 35779566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3578b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3579b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3580b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 35819566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3582b5a892a1SMatthew G. Knepley if (*points) {closure = *points;} 35839566063dSJacob Faibussowitsch else PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure)); 3584b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3585b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3586b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3587b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3588b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3589b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3590b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3591b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3592b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3593b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3594b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3595b5a892a1SMatthew G. Knepley const PetscInt *tmp, *tmpO; 3596b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3597b5a892a1SMatthew G. Knepley 3598b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3599b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 360063a3b9bcSJacob 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); 3601b5a892a1SMatthew G. Knepley } 3602b5a892a1SMatthew G. Knepley if (useCone) { 36039566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &tmpSize)); 36049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &tmp)); 36059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO)); 3606b5a892a1SMatthew G. Knepley } else { 36079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize)); 36089566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &tmp)); 3609b5a892a1SMatthew G. Knepley tmpO = NULL; 3610b5a892a1SMatthew G. Knepley } 3611b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3612b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3613b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3614b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 36159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3616b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3617b5a892a1SMatthew G. Knepley PetscInt c; 3618b5a892a1SMatthew G. Knepley 3619b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3620b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3621b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3622b5a892a1SMatthew G. Knepley } 3623b5a892a1SMatthew G. Knepley if (c == closureSize) { 3624b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3625b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3626b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3627b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3628b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3629b5a892a1SMatthew G. Knepley } 3630b5a892a1SMatthew G. Knepley } 3631b5a892a1SMatthew G. Knepley } 36329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3633b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize/2; 3634b5a892a1SMatthew G. Knepley if (points) *points = closure; 3635b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3636b5a892a1SMatthew G. Knepley } 3637b5a892a1SMatthew G. Knepley 3638552f7358SJed Brown /*@C 3639eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3640552f7358SJed Brown 3641552f7358SJed Brown Not collective 3642552f7358SJed Brown 3643552f7358SJed Brown Input Parameters: 3644b5a892a1SMatthew G. Knepley + dm - The DMPlex 3645b5a892a1SMatthew G. Knepley . p - The mesh point 36466b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star 3647552f7358SJed Brown 36486b867d5aSJose E. Roman Input/Output Parameter: 36496b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 36506b867d5aSJose E. Roman if NULL on input, internal storage will be returned, otherwise the provided array is used 36516b867d5aSJose E. Roman 36526b867d5aSJose E. Roman Output Parameter: 36536b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3654552f7358SJed Brown 3655552f7358SJed Brown Note: 36560298fd71SBarry Smith If using internal storage (points is NULL on input), each call overwrites the last output. 3657552f7358SJed Brown 36583813dfbdSMatthew G Knepley Fortran Notes: 3659b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36603813dfbdSMatthew G Knepley 36613813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36623813dfbdSMatthew G Knepley 3663552f7358SJed Brown Level: beginner 3664552f7358SJed Brown 3665db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3666552f7358SJed Brown @*/ 3667552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3668552f7358SJed Brown { 3669b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3670552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3671b5a892a1SMatthew G. Knepley if (numPoints) PetscValidIntPointer(numPoints, 4); 3672b5a892a1SMatthew G. Knepley if (points) PetscValidPointer(points, 5); 36739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 36749bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 36759bf0dad6SMatthew G. Knepley } 36769bf0dad6SMatthew G. Knepley 3677552f7358SJed Brown /*@C 3678eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3679552f7358SJed Brown 3680552f7358SJed Brown Not collective 3681552f7358SJed Brown 3682552f7358SJed Brown Input Parameters: 3683b5a892a1SMatthew G. Knepley + dm - The DMPlex 3684b5a892a1SMatthew G. Knepley . p - The mesh point 3685b5a892a1SMatthew G. Knepley . useCone - PETSC_TRUE for the closure, otherwise return the star 3686b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3687b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3688552f7358SJed Brown 3689552f7358SJed Brown Note: 36900298fd71SBarry Smith If not using internal storage (points is not NULL on input), this call is unnecessary 3691552f7358SJed Brown 36923813dfbdSMatthew G Knepley Fortran Notes: 3693b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36943813dfbdSMatthew G Knepley 36953813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36963813dfbdSMatthew G Knepley 3697552f7358SJed Brown Level: beginner 3698552f7358SJed Brown 3699db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3700552f7358SJed Brown @*/ 3701552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3702552f7358SJed Brown { 3703b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3704552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37054ff43b2cSJed Brown if (numPoints) *numPoints = 0; 37069566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 3707552f7358SJed Brown PetscFunctionReturn(0); 3708552f7358SJed Brown } 3709552f7358SJed Brown 3710552f7358SJed Brown /*@ 3711eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3712552f7358SJed Brown 3713552f7358SJed Brown Not collective 3714552f7358SJed Brown 3715552f7358SJed Brown Input Parameter: 3716552f7358SJed Brown . mesh - The DMPlex 3717552f7358SJed Brown 3718552f7358SJed Brown Output Parameters: 3719552f7358SJed Brown + maxConeSize - The maximum number of in-edges 3720552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 3721552f7358SJed Brown 3722552f7358SJed Brown Level: beginner 3723552f7358SJed Brown 3724db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3725552f7358SJed Brown @*/ 3726552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3727552f7358SJed Brown { 3728552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3729552f7358SJed Brown 3730552f7358SJed Brown PetscFunctionBegin; 3731552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37321baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 37331baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 3734552f7358SJed Brown PetscFunctionReturn(0); 3735552f7358SJed Brown } 3736552f7358SJed Brown 3737552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm) 3738552f7358SJed Brown { 3739552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 37406302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 3741552f7358SJed Brown 3742552f7358SJed Brown PetscFunctionBegin; 3743552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 37459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 37469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 37479566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 37489566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt))); 37496302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 37506302a7fbSVaclav Hapla if (maxSupportSize) { 37519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 37529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 37539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 37549566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt))); 3755552f7358SJed Brown } 3756552f7358SJed Brown PetscFunctionReturn(0); 3757552f7358SJed Brown } 3758552f7358SJed Brown 3759276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3760552f7358SJed Brown { 3761552f7358SJed Brown PetscFunctionBegin; 37629566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 37639566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 3764c2939958SSatish Balay if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3765736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 3766f94b4a02SBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 3767f94b4a02SBlaise Bourdin PetscSection section, sectionSeq; 3768f94b4a02SBlaise Bourdin 37693dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 37709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dm->sfMigration)); 37719566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection((*subdm), §ion)); 37729566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv)); 37739566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq)); 37749566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 3775f94b4a02SBlaise Bourdin 37769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural)); 3777c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 37789566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionSeq)); 37799566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 3780f94b4a02SBlaise Bourdin } 3781552f7358SJed Brown PetscFunctionReturn(0); 3782552f7358SJed Brown } 3783552f7358SJed Brown 37842adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 37852adcc780SMatthew G. Knepley { 37863dcd263cSBlaise Bourdin PetscInt i = 0; 37872adcc780SMatthew G. Knepley 37882adcc780SMatthew G. Knepley PetscFunctionBegin; 37899566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 37909566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 3791c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 37923dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 37933dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 37943dcd263cSBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 37953dcd263cSBlaise Bourdin PetscSection section, sectionSeq; 37963dcd263cSBlaise Bourdin 37973dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 37989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dms[i]->sfMigration)); 3799c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 38009566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection((*superdm), §ion)); 38019566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv)); 38029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq)); 38039566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 38043dcd263cSBlaise Bourdin 38059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural)); 3806c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 38079566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionSeq)); 38089566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 38093dcd263cSBlaise Bourdin break; 38103dcd263cSBlaise Bourdin } 38113dcd263cSBlaise Bourdin } 38122adcc780SMatthew G. Knepley PetscFunctionReturn(0); 38132adcc780SMatthew G. Knepley } 38142adcc780SMatthew G. Knepley 3815552f7358SJed Brown /*@ 3816eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3817552f7358SJed Brown 3818552f7358SJed Brown Not collective 3819552f7358SJed Brown 3820552f7358SJed Brown Input Parameter: 3821552f7358SJed Brown . mesh - The DMPlex 3822552f7358SJed Brown 3823552f7358SJed Brown Output Parameter: 3824552f7358SJed Brown 3825552f7358SJed Brown Note: 3826552f7358SJed Brown This should be called after all calls to DMPlexSetCone() 3827552f7358SJed Brown 3828552f7358SJed Brown Level: beginner 3829552f7358SJed Brown 3830db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 3831552f7358SJed Brown @*/ 3832552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm) 3833552f7358SJed Brown { 3834552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3835552f7358SJed Brown PetscInt *offsets; 3836552f7358SJed Brown PetscInt supportSize; 3837552f7358SJed Brown PetscInt pStart, pEnd, p; 3838552f7358SJed Brown 3839552f7358SJed Brown PetscFunctionBegin; 3840552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 384128b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 38429566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0)); 3843552f7358SJed Brown /* Calculate support sizes */ 38449566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3845552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3846552f7358SJed Brown PetscInt dof, off, c; 3847552f7358SJed Brown 38489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3850552f7358SJed Brown for (c = off; c < off+dof; ++c) { 38519566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 3852552f7358SJed Brown } 3853552f7358SJed Brown } 38549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 3855552f7358SJed Brown /* Calculate supports */ 38569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 38579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 38589566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 3859552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3860552f7358SJed Brown PetscInt dof, off, c; 3861552f7358SJed Brown 38629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3864552f7358SJed Brown for (c = off; c < off+dof; ++c) { 3865552f7358SJed Brown const PetscInt q = mesh->cones[c]; 3866552f7358SJed Brown PetscInt offS; 3867552f7358SJed Brown 38689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 38690d644c17SKarl Rupp 3870552f7358SJed Brown mesh->supports[offS+offsets[q]] = p; 3871552f7358SJed Brown ++offsets[q]; 3872552f7358SJed Brown } 3873552f7358SJed Brown } 38749566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 38759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0)); 3876552f7358SJed Brown PetscFunctionReturn(0); 3877552f7358SJed Brown } 3878552f7358SJed Brown 3879277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3880277ea44aSLisandro Dalcin { 3881277ea44aSLisandro Dalcin IS stratumIS; 3882277ea44aSLisandro Dalcin 3883277ea44aSLisandro Dalcin PetscFunctionBegin; 3884277ea44aSLisandro Dalcin if (pStart >= pEnd) PetscFunctionReturn(0); 388576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3886277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 3887277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 38889566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 3889277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 38909566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3891277ea44aSLisandro Dalcin if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3892277ea44aSLisandro Dalcin } 389363a3b9bcSJacob 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); 3894277ea44aSLisandro Dalcin } 38959566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS)); 38969566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 38979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 3898277ea44aSLisandro Dalcin PetscFunctionReturn(0); 3899277ea44aSLisandro Dalcin } 3900277ea44aSLisandro Dalcin 3901552f7358SJed Brown /*@ 3902a8d69d7bSBarry Smith DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 39036dd80730SBarry Smith can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3904552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3905552f7358SJed Brown the DAG. 3906552f7358SJed Brown 3907bf4602e4SToby Isaac Collective on dm 3908552f7358SJed Brown 3909552f7358SJed Brown Input Parameter: 3910552f7358SJed Brown . mesh - The DMPlex 3911552f7358SJed Brown 3912552f7358SJed Brown Output Parameter: 3913552f7358SJed Brown 3914552f7358SJed Brown Notes: 3915b1bb481bSMatthew Knepley Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3916b1bb481bSMatthew 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 3917b1bb481bSMatthew Knepley until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3918c58f1c22SToby Isaac manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3919150b719bSJed Brown via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3920552f7358SJed Brown 3921b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3922b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3923b1bb481bSMatthew 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 3924b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 3925b1bb481bSMatthew Knepley $ cone(c0) = {e0, v2} 3926b1bb481bSMatthew Knepley $ cone(e0) = {v0, v1} 3927b1bb481bSMatthew Knepley If DMPlexStratify() is run on this mesh, it will give depths 3928b1bb481bSMatthew Knepley $ depth 0 = {v0, v1, v2} 3929b1bb481bSMatthew Knepley $ depth 1 = {e0, c0} 3930b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3931b1bb481bSMatthew Knepley 3932150b719bSJed Brown DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3933552f7358SJed Brown 3934552f7358SJed Brown Level: beginner 3935552f7358SJed Brown 3936db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 3937552f7358SJed Brown @*/ 3938552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm) 3939552f7358SJed Brown { 3940df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 3941aa50250dSMatthew G. Knepley DMLabel label; 3942552f7358SJed Brown PetscInt pStart, pEnd, p; 3943552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 3944552f7358SJed Brown 3945552f7358SJed Brown PetscFunctionBegin; 3946552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0)); 3948277ea44aSLisandro Dalcin 3949277ea44aSLisandro Dalcin /* Create depth label */ 39509566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 39519566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 39529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 3953277ea44aSLisandro Dalcin 3954277ea44aSLisandro Dalcin { 3955552f7358SJed Brown /* Initialize roots and count leaves */ 3956277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3957277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3958552f7358SJed Brown PetscInt coneSize, supportSize; 3959552f7358SJed Brown 3960277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39619566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39629566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3963552f7358SJed Brown if (!coneSize && supportSize) { 3964277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3965277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3966552f7358SJed Brown ++numRoots; 3967552f7358SJed Brown } else if (!supportSize && coneSize) { 3968552f7358SJed Brown ++numLeaves; 3969552f7358SJed Brown } else if (!supportSize && !coneSize) { 3970552f7358SJed Brown /* Isolated points */ 3971277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3972277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3973552f7358SJed Brown } 3974552f7358SJed Brown } 39759566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1)); 3976277ea44aSLisandro Dalcin } 3977277ea44aSLisandro Dalcin 3978552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 3979277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3980277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3981552f7358SJed Brown PetscInt coneSize, supportSize; 3982552f7358SJed Brown 3983277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39859566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3986552f7358SJed Brown if (!supportSize && coneSize) { 3987277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3988277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3989552f7358SJed Brown } 3990552f7358SJed Brown } 39919566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1)); 3992552f7358SJed Brown } else { 3993277ea44aSLisandro Dalcin PetscInt level = 0; 3994277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 3995552f7358SJed Brown 39969566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3997277ea44aSLisandro Dalcin while (qEnd > qStart) { 3998277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3999277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 400074ef644bSMatthew G. Knepley 4001277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 400274ef644bSMatthew G. Knepley const PetscInt *support; 400374ef644bSMatthew G. Knepley PetscInt supportSize, s; 400474ef644bSMatthew G. Knepley 40059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 40069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &support)); 400774ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 4008277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 4009277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 4010552f7358SJed Brown } 4011552f7358SJed Brown } 40129566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &level)); 40139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1)); 40149566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 401574ef644bSMatthew G. Knepley } 401674ef644bSMatthew G. Knepley } 4017bf4602e4SToby Isaac { /* just in case there is an empty process */ 4018bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4019bf4602e4SToby Isaac 40209566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 40219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 4022bf4602e4SToby Isaac for (v = numValues; v < maxValues; v++) { 40239566063dSJacob Faibussowitsch PetscCall(DMLabelAddStratum(label, v)); 4024bf4602e4SToby Isaac } 4025bf4602e4SToby Isaac } 40269566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject) label, &mesh->depthState)); 40279566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0)); 4028552f7358SJed Brown PetscFunctionReturn(0); 4029552f7358SJed Brown } 4030552f7358SJed Brown 4031412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4032ba2698f1SMatthew G. Knepley { 4033412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4034412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4035ba2698f1SMatthew G. Knepley 4036412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 40379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 40389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 40399566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4040ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4041ba2698f1SMatthew G. Knepley if (depth <= 1) { 4042ba2698f1SMatthew G. Knepley switch (pdepth) { 4043ba2698f1SMatthew G. Knepley case 0: ct = DM_POLYTOPE_POINT;break; 4044ba2698f1SMatthew G. Knepley case 1: 4045ba2698f1SMatthew G. Knepley switch (coneSize) { 4046ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4047ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4048ba2698f1SMatthew G. Knepley case 4: 4049ba2698f1SMatthew G. Knepley switch (dim) { 4050ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 4051ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 4052ba2698f1SMatthew G. Knepley default: break; 4053ba2698f1SMatthew G. Knepley } 4054ba2698f1SMatthew G. Knepley break; 4055da9060c4SMatthew G. Knepley case 5: ct = DM_POLYTOPE_PYRAMID;break; 4056ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4057ba2698f1SMatthew G. Knepley case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 4058ba2698f1SMatthew G. Knepley default: break; 4059ba2698f1SMatthew G. Knepley } 4060ba2698f1SMatthew G. Knepley } 4061ba2698f1SMatthew G. Knepley } else { 4062ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4063ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4064ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4065ba2698f1SMatthew G. Knepley switch (dim) { 4066ba2698f1SMatthew G. Knepley case 1: 4067ba2698f1SMatthew G. Knepley switch (coneSize) { 4068ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4069ba2698f1SMatthew G. Knepley default: break; 4070ba2698f1SMatthew G. Knepley } 4071ba2698f1SMatthew G. Knepley break; 4072ba2698f1SMatthew G. Knepley case 2: 4073ba2698f1SMatthew G. Knepley switch (coneSize) { 4074ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4075ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4076ba2698f1SMatthew G. Knepley default: break; 4077ba2698f1SMatthew G. Knepley } 4078ba2698f1SMatthew G. Knepley break; 4079ba2698f1SMatthew G. Knepley case 3: 4080ba2698f1SMatthew G. Knepley switch (coneSize) { 4081ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4082da9060c4SMatthew G. Knepley case 5: 4083da9060c4SMatthew G. Knepley { 4084da9060c4SMatthew G. Knepley const PetscInt *cone; 4085da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4086da9060c4SMatthew G. Knepley 40879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 40889566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4089da9060c4SMatthew G. Knepley switch (faceConeSize) { 4090da9060c4SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4091da9060c4SMatthew G. Knepley case 4: ct = DM_POLYTOPE_PYRAMID;break; 4092da9060c4SMatthew G. Knepley } 4093da9060c4SMatthew G. Knepley } 4094da9060c4SMatthew G. Knepley break; 4095ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4096ba2698f1SMatthew G. Knepley default: break; 4097ba2698f1SMatthew G. Knepley } 4098ba2698f1SMatthew G. Knepley break; 4099ba2698f1SMatthew G. Knepley default: break; 4100ba2698f1SMatthew G. Knepley } 4101ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4102ba2698f1SMatthew G. Knepley switch (coneSize) { 4103ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4104ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4105ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4106ba2698f1SMatthew G. Knepley default: break; 4107ba2698f1SMatthew G. Knepley } 4108ba2698f1SMatthew G. Knepley } 4109ba2698f1SMatthew G. Knepley } 4110412e9a14SMatthew G. Knepley *pt = ct; 4111412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4112ba2698f1SMatthew G. Knepley } 4113412e9a14SMatthew G. Knepley 4114412e9a14SMatthew G. Knepley /*@ 4115412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4116412e9a14SMatthew G. Knepley 4117412e9a14SMatthew G. Knepley Collective on dm 4118412e9a14SMatthew G. Knepley 4119412e9a14SMatthew G. Knepley Input Parameter: 4120412e9a14SMatthew G. Knepley . mesh - The DMPlex 4121412e9a14SMatthew G. Knepley 4122412e9a14SMatthew G. Knepley DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4123412e9a14SMatthew G. Knepley 4124412e9a14SMatthew G. Knepley Level: developer 4125412e9a14SMatthew G. Knepley 4126412e9a14SMatthew G. Knepley Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4127412e9a14SMatthew G. Knepley internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4128412e9a14SMatthew G. Knepley automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4129412e9a14SMatthew G. Knepley 4130db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4131412e9a14SMatthew G. Knepley @*/ 4132412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm) 4133412e9a14SMatthew G. Knepley { 4134412e9a14SMatthew G. Knepley DM_Plex *mesh; 4135412e9a14SMatthew G. Knepley DMLabel ctLabel; 4136412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4137412e9a14SMatthew G. Knepley 4138412e9a14SMatthew G. Knepley PetscFunctionBegin; 4139412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4140412e9a14SMatthew G. Knepley mesh = (DM_Plex *) dm->data; 41419566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 41429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 41439566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4144412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4145327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4146412e9a14SMatthew G. Knepley PetscInt pdepth; 4147412e9a14SMatthew G. Knepley 41489566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 41499566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 415063a3b9bcSJacob Faibussowitsch PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 41519566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 4152412e9a14SMatthew G. Knepley } 41539566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState)); 41549566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view")); 4155ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4156ba2698f1SMatthew G. Knepley } 4157ba2698f1SMatthew G. Knepley 4158552f7358SJed Brown /*@C 4159552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4160552f7358SJed Brown 4161552f7358SJed Brown Not Collective 4162552f7358SJed Brown 4163552f7358SJed Brown Input Parameters: 4164552f7358SJed Brown + dm - The DMPlex object 4165552f7358SJed Brown . numPoints - The number of input points for the join 4166552f7358SJed Brown - points - The input points 4167552f7358SJed Brown 4168552f7358SJed Brown Output Parameters: 4169552f7358SJed Brown + numCoveredPoints - The number of points in the join 4170552f7358SJed Brown - coveredPoints - The points in the join 4171552f7358SJed Brown 4172552f7358SJed Brown Level: intermediate 4173552f7358SJed Brown 4174552f7358SJed Brown Note: Currently, this is restricted to a single level join 4175552f7358SJed Brown 41763813dfbdSMatthew G Knepley Fortran Notes: 41773813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 41783813dfbdSMatthew G Knepley include petsc.h90 in your code. 41793813dfbdSMatthew G Knepley 41803813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 41813813dfbdSMatthew G Knepley 4182db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4183552f7358SJed Brown @*/ 4184552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4185552f7358SJed Brown { 4186552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4187552f7358SJed Brown PetscInt *join[2]; 4188552f7358SJed Brown PetscInt joinSize, i = 0; 4189552f7358SJed Brown PetscInt dof, off, p, c, m; 41906302a7fbSVaclav Hapla PetscInt maxSupportSize; 4191552f7358SJed Brown 4192552f7358SJed Brown PetscFunctionBegin; 4193552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 419448bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 419548bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 419648bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 41976302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41986302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 41996302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4200552f7358SJed Brown /* Copy in support of first point */ 42019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 42029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4203552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4204552f7358SJed Brown join[i][joinSize] = mesh->supports[off+joinSize]; 4205552f7358SJed Brown } 4206552f7358SJed Brown /* Check each successive support */ 4207552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4208552f7358SJed Brown PetscInt newJoinSize = 0; 4209552f7358SJed Brown 42109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 42119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4212552f7358SJed Brown for (c = 0; c < dof; ++c) { 4213552f7358SJed Brown const PetscInt point = mesh->supports[off+c]; 4214552f7358SJed Brown 4215552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4216552f7358SJed Brown if (point == join[i][m]) { 4217552f7358SJed Brown join[1-i][newJoinSize++] = point; 4218552f7358SJed Brown break; 4219552f7358SJed Brown } 4220552f7358SJed Brown } 4221552f7358SJed Brown } 4222552f7358SJed Brown joinSize = newJoinSize; 4223552f7358SJed Brown i = 1-i; 4224552f7358SJed Brown } 4225552f7358SJed Brown *numCoveredPoints = joinSize; 4226552f7358SJed Brown *coveredPoints = join[i]; 42276302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1-i])); 4228552f7358SJed Brown PetscFunctionReturn(0); 4229552f7358SJed Brown } 4230552f7358SJed Brown 4231552f7358SJed Brown /*@C 4232552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4233552f7358SJed Brown 4234552f7358SJed Brown Not Collective 4235552f7358SJed Brown 4236552f7358SJed Brown Input Parameters: 4237552f7358SJed Brown + dm - The DMPlex object 4238552f7358SJed Brown . numPoints - The number of input points for the join 4239552f7358SJed Brown - points - The input points 4240552f7358SJed Brown 4241552f7358SJed Brown Output Parameters: 4242552f7358SJed Brown + numCoveredPoints - The number of points in the join 4243552f7358SJed Brown - coveredPoints - The points in the join 4244552f7358SJed Brown 42453813dfbdSMatthew G Knepley Fortran Notes: 42463813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42473813dfbdSMatthew G Knepley include petsc.h90 in your code. 42483813dfbdSMatthew G Knepley 42493813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42503813dfbdSMatthew G Knepley 4251552f7358SJed Brown Level: intermediate 4252552f7358SJed Brown 4253db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4254552f7358SJed Brown @*/ 4255552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4256552f7358SJed Brown { 4257552f7358SJed Brown PetscFunctionBegin; 4258552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4259d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4260d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4261d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 42629566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4263d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4264552f7358SJed Brown PetscFunctionReturn(0); 4265552f7358SJed Brown } 4266552f7358SJed Brown 4267552f7358SJed Brown /*@C 4268552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4269552f7358SJed Brown 4270552f7358SJed Brown Not Collective 4271552f7358SJed Brown 4272552f7358SJed Brown Input Parameters: 4273552f7358SJed Brown + dm - The DMPlex object 4274552f7358SJed Brown . numPoints - The number of input points for the join 4275552f7358SJed Brown - points - The input points 4276552f7358SJed Brown 4277552f7358SJed Brown Output Parameters: 4278552f7358SJed Brown + numCoveredPoints - The number of points in the join 4279552f7358SJed Brown - coveredPoints - The points in the join 4280552f7358SJed Brown 42813813dfbdSMatthew G Knepley Fortran Notes: 42823813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42833813dfbdSMatthew G Knepley include petsc.h90 in your code. 42843813dfbdSMatthew G Knepley 42853813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42863813dfbdSMatthew G Knepley 4287552f7358SJed Brown Level: intermediate 4288552f7358SJed Brown 4289db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4290552f7358SJed Brown @*/ 4291552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4292552f7358SJed Brown { 4293552f7358SJed Brown PetscInt *offsets, **closures; 4294552f7358SJed Brown PetscInt *join[2]; 4295552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 429624c766afSToby Isaac PetscInt p, d, c, m, ms; 4297552f7358SJed Brown 4298552f7358SJed Brown PetscFunctionBegin; 4299552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 430048bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 430148bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 430248bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 4303552f7358SJed Brown 43049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 43059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 43069566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 43076302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 430824c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 43099566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 43109566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4311552f7358SJed Brown 4312552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4313552f7358SJed Brown PetscInt closureSize; 4314552f7358SJed Brown 43159566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 43160d644c17SKarl Rupp 4317552f7358SJed Brown offsets[p*(depth+2)+0] = 0; 4318552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4319552f7358SJed Brown PetscInt pStart, pEnd, i; 4320552f7358SJed Brown 43219566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4322552f7358SJed Brown for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4323552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4324552f7358SJed Brown offsets[p*(depth+2)+d+1] = i; 4325552f7358SJed Brown break; 4326552f7358SJed Brown } 4327552f7358SJed Brown } 4328552f7358SJed Brown if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4329552f7358SJed Brown } 433063a3b9bcSJacob 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); 4331552f7358SJed Brown } 4332552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4333552f7358SJed Brown PetscInt dof; 4334552f7358SJed Brown 4335552f7358SJed Brown /* Copy in support of first point */ 4336552f7358SJed Brown dof = offsets[d+1] - offsets[d]; 4337552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4338552f7358SJed Brown join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4339552f7358SJed Brown } 4340552f7358SJed Brown /* Check each successive cone */ 4341552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4342552f7358SJed Brown PetscInt newJoinSize = 0; 4343552f7358SJed Brown 4344552f7358SJed Brown dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4345552f7358SJed Brown for (c = 0; c < dof; ++c) { 4346552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4347552f7358SJed Brown 4348552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4349552f7358SJed Brown if (point == join[i][m]) { 4350552f7358SJed Brown join[1-i][newJoinSize++] = point; 4351552f7358SJed Brown break; 4352552f7358SJed Brown } 4353552f7358SJed Brown } 4354552f7358SJed Brown } 4355552f7358SJed Brown joinSize = newJoinSize; 4356552f7358SJed Brown i = 1-i; 4357552f7358SJed Brown } 4358552f7358SJed Brown if (joinSize) break; 4359552f7358SJed Brown } 4360552f7358SJed Brown *numCoveredPoints = joinSize; 4361552f7358SJed Brown *coveredPoints = join[i]; 4362552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 43639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 4364552f7358SJed Brown } 43659566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 43669566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 43676302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1-i])); 4368552f7358SJed Brown PetscFunctionReturn(0); 4369552f7358SJed Brown } 4370552f7358SJed Brown 4371552f7358SJed Brown /*@C 4372552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4373552f7358SJed Brown 4374552f7358SJed Brown Not Collective 4375552f7358SJed Brown 4376552f7358SJed Brown Input Parameters: 4377552f7358SJed Brown + dm - The DMPlex object 4378552f7358SJed Brown . numPoints - The number of input points for the meet 4379552f7358SJed Brown - points - The input points 4380552f7358SJed Brown 4381552f7358SJed Brown Output Parameters: 4382552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4383552f7358SJed Brown - coveredPoints - The points in the meet 4384552f7358SJed Brown 4385552f7358SJed Brown Level: intermediate 4386552f7358SJed Brown 4387552f7358SJed Brown Note: Currently, this is restricted to a single level meet 4388552f7358SJed Brown 43893813dfbdSMatthew G Knepley Fortran Notes: 43903813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 43913813dfbdSMatthew G Knepley include petsc.h90 in your code. 43923813dfbdSMatthew G Knepley 43933813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 43943813dfbdSMatthew G Knepley 4395db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4396552f7358SJed Brown @*/ 4397552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4398552f7358SJed Brown { 4399552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4400552f7358SJed Brown PetscInt *meet[2]; 4401552f7358SJed Brown PetscInt meetSize, i = 0; 4402552f7358SJed Brown PetscInt dof, off, p, c, m; 44036302a7fbSVaclav Hapla PetscInt maxConeSize; 4404552f7358SJed Brown 4405552f7358SJed Brown PetscFunctionBegin; 4406552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4407dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4408dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveringPoints, 4); 4409064a246eSJacob Faibussowitsch PetscValidPointer(coveringPoints, 5); 44106302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 44116302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 44126302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4413552f7358SJed Brown /* Copy in cone of first point */ 44149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 44159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4416552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4417552f7358SJed Brown meet[i][meetSize] = mesh->cones[off+meetSize]; 4418552f7358SJed Brown } 4419552f7358SJed Brown /* Check each successive cone */ 4420552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4421552f7358SJed Brown PetscInt newMeetSize = 0; 4422552f7358SJed Brown 44239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 44249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4425552f7358SJed Brown for (c = 0; c < dof; ++c) { 4426552f7358SJed Brown const PetscInt point = mesh->cones[off+c]; 4427552f7358SJed Brown 4428552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4429552f7358SJed Brown if (point == meet[i][m]) { 4430552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4431552f7358SJed Brown break; 4432552f7358SJed Brown } 4433552f7358SJed Brown } 4434552f7358SJed Brown } 4435552f7358SJed Brown meetSize = newMeetSize; 4436552f7358SJed Brown i = 1-i; 4437552f7358SJed Brown } 4438552f7358SJed Brown *numCoveringPoints = meetSize; 4439552f7358SJed Brown *coveringPoints = meet[i]; 44406302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1-i])); 4441552f7358SJed Brown PetscFunctionReturn(0); 4442552f7358SJed Brown } 4443552f7358SJed Brown 4444552f7358SJed Brown /*@C 4445552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4446552f7358SJed Brown 4447552f7358SJed Brown Not Collective 4448552f7358SJed Brown 4449552f7358SJed Brown Input Parameters: 4450552f7358SJed Brown + dm - The DMPlex object 4451552f7358SJed Brown . numPoints - The number of input points for the meet 4452552f7358SJed Brown - points - The input points 4453552f7358SJed Brown 4454552f7358SJed Brown Output Parameters: 4455552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4456552f7358SJed Brown - coveredPoints - The points in the meet 4457552f7358SJed Brown 4458552f7358SJed Brown Level: intermediate 4459552f7358SJed Brown 44603813dfbdSMatthew G Knepley Fortran Notes: 44613813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44623813dfbdSMatthew G Knepley include petsc.h90 in your code. 44633813dfbdSMatthew G Knepley 44643813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44653813dfbdSMatthew G Knepley 4466db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4467552f7358SJed Brown @*/ 4468552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4469552f7358SJed Brown { 4470552f7358SJed Brown PetscFunctionBegin; 4471552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4472d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4473d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4474d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints,5); 44759566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4476d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4477552f7358SJed Brown PetscFunctionReturn(0); 4478552f7358SJed Brown } 4479552f7358SJed Brown 4480552f7358SJed Brown /*@C 4481552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4482552f7358SJed Brown 4483552f7358SJed Brown Not Collective 4484552f7358SJed Brown 4485552f7358SJed Brown Input Parameters: 4486552f7358SJed Brown + dm - The DMPlex object 4487552f7358SJed Brown . numPoints - The number of input points for the meet 4488552f7358SJed Brown - points - The input points 4489552f7358SJed Brown 4490552f7358SJed Brown Output Parameters: 4491552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4492552f7358SJed Brown - coveredPoints - The points in the meet 4493552f7358SJed Brown 4494552f7358SJed Brown Level: intermediate 4495552f7358SJed Brown 44963813dfbdSMatthew G Knepley Fortran Notes: 44973813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44983813dfbdSMatthew G Knepley include petsc.h90 in your code. 44993813dfbdSMatthew G Knepley 45003813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 45013813dfbdSMatthew G Knepley 4502db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4503552f7358SJed Brown @*/ 4504552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4505552f7358SJed Brown { 4506552f7358SJed Brown PetscInt *offsets, **closures; 4507552f7358SJed Brown PetscInt *meet[2]; 4508552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 450924c766afSToby Isaac PetscInt p, h, c, m, mc; 4510552f7358SJed Brown 4511552f7358SJed Brown PetscFunctionBegin; 4512552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4513dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4514dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveredPoints, 4); 4515064a246eSJacob Faibussowitsch PetscValidPointer(coveredPoints, 5); 4516552f7358SJed Brown 45179566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 45189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 45199566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 45206302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 452124c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 45229566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 45239566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4524552f7358SJed Brown 4525552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4526552f7358SJed Brown PetscInt closureSize; 4527552f7358SJed Brown 45289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 45290d644c17SKarl Rupp 4530552f7358SJed Brown offsets[p*(height+2)+0] = 0; 4531552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4532552f7358SJed Brown PetscInt pStart, pEnd, i; 4533552f7358SJed Brown 45349566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4535552f7358SJed Brown for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4536552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4537552f7358SJed Brown offsets[p*(height+2)+h+1] = i; 4538552f7358SJed Brown break; 4539552f7358SJed Brown } 4540552f7358SJed Brown } 4541552f7358SJed Brown if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4542552f7358SJed Brown } 454363a3b9bcSJacob 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); 4544552f7358SJed Brown } 4545552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4546552f7358SJed Brown PetscInt dof; 4547552f7358SJed Brown 4548552f7358SJed Brown /* Copy in cone of first point */ 4549552f7358SJed Brown dof = offsets[h+1] - offsets[h]; 4550552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4551552f7358SJed Brown meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4552552f7358SJed Brown } 4553552f7358SJed Brown /* Check each successive cone */ 4554552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4555552f7358SJed Brown PetscInt newMeetSize = 0; 4556552f7358SJed Brown 4557552f7358SJed Brown dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4558552f7358SJed Brown for (c = 0; c < dof; ++c) { 4559552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4560552f7358SJed Brown 4561552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4562552f7358SJed Brown if (point == meet[i][m]) { 4563552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4564552f7358SJed Brown break; 4565552f7358SJed Brown } 4566552f7358SJed Brown } 4567552f7358SJed Brown } 4568552f7358SJed Brown meetSize = newMeetSize; 4569552f7358SJed Brown i = 1-i; 4570552f7358SJed Brown } 4571552f7358SJed Brown if (meetSize) break; 4572552f7358SJed Brown } 4573552f7358SJed Brown *numCoveredPoints = meetSize; 4574552f7358SJed Brown *coveredPoints = meet[i]; 4575552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 45769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 4577552f7358SJed Brown } 45789566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 45799566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 45806302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1-i])); 4581552f7358SJed Brown PetscFunctionReturn(0); 4582552f7358SJed Brown } 4583552f7358SJed Brown 45844e3744c5SMatthew G. Knepley /*@C 45854e3744c5SMatthew G. Knepley DMPlexEqual - Determine if two DMs have the same topology 45864e3744c5SMatthew G. Knepley 45874e3744c5SMatthew G. Knepley Not Collective 45884e3744c5SMatthew G. Knepley 45894e3744c5SMatthew G. Knepley Input Parameters: 45904e3744c5SMatthew G. Knepley + dmA - A DMPlex object 45914e3744c5SMatthew G. Knepley - dmB - A DMPlex object 45924e3744c5SMatthew G. Knepley 45934e3744c5SMatthew G. Knepley Output Parameters: 45944e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical 45954e3744c5SMatthew G. Knepley 45964e3744c5SMatthew G. Knepley Level: intermediate 45974e3744c5SMatthew G. Knepley 45984e3744c5SMatthew G. Knepley Notes: 45994e3744c5SMatthew G. Knepley We are not solving graph isomorphism, so we do not permutation. 46004e3744c5SMatthew G. Knepley 4601db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 46024e3744c5SMatthew G. Knepley @*/ 46034e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 46044e3744c5SMatthew G. Knepley { 46054e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 46064e3744c5SMatthew G. Knepley 46074e3744c5SMatthew G. Knepley PetscFunctionBegin; 46084e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 46094e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4610dadcf809SJacob Faibussowitsch PetscValidBoolPointer(equal, 3); 46114e3744c5SMatthew G. Knepley 46124e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 46139566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 46149566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 46154e3744c5SMatthew G. Knepley if (depth != depthB) PetscFunctionReturn(0); 46169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 46179566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 46184e3744c5SMatthew G. Knepley if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 46194e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 46204e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 46214e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 46224e3744c5SMatthew G. Knepley 46239566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 46249566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 46259566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 46269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 46279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 46289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 46294e3744c5SMatthew G. Knepley if (coneSize != coneSizeB) PetscFunctionReturn(0); 46304e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 46314e3744c5SMatthew G. Knepley if (cone[c] != coneB[c]) PetscFunctionReturn(0); 46324e3744c5SMatthew G. Knepley if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 46334e3744c5SMatthew G. Knepley } 46349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 46359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 46369566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 46379566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 46384e3744c5SMatthew G. Knepley if (supportSize != supportSizeB) PetscFunctionReturn(0); 46394e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 46404e3744c5SMatthew G. Knepley if (support[s] != supportB[s]) PetscFunctionReturn(0); 46414e3744c5SMatthew G. Knepley } 46424e3744c5SMatthew G. Knepley } 46434e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 46444e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 46454e3744c5SMatthew G. Knepley } 46464e3744c5SMatthew G. Knepley 46477cd05799SMatthew G. Knepley /*@C 46487cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 46497cd05799SMatthew G. Knepley 46507cd05799SMatthew G. Knepley Not Collective 46517cd05799SMatthew G. Knepley 46527cd05799SMatthew G. Knepley Input Parameters: 46537cd05799SMatthew G. Knepley + dm - The DMPlex 46547cd05799SMatthew G. Knepley . cellDim - The cell dimension 46557cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 46567cd05799SMatthew G. Knepley 46577cd05799SMatthew G. Knepley Output Parameters: 46587cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 46597cd05799SMatthew G. Knepley 46607cd05799SMatthew G. Knepley Level: developer 46617cd05799SMatthew G. Knepley 46627cd05799SMatthew G. Knepley Notes: 46637cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 46647cd05799SMatthew G. Knepley 4665db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 46667cd05799SMatthew G. Knepley @*/ 466718ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4668a6dfd86eSKarl Rupp { 466982f516ccSBarry Smith MPI_Comm comm; 4670552f7358SJed Brown 4671552f7358SJed Brown PetscFunctionBegin; 46729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm,&comm)); 4673dadcf809SJacob Faibussowitsch PetscValidIntPointer(numFaceVertices,4); 4674552f7358SJed Brown switch (cellDim) { 4675552f7358SJed Brown case 0: 4676552f7358SJed Brown *numFaceVertices = 0; 4677552f7358SJed Brown break; 4678552f7358SJed Brown case 1: 4679552f7358SJed Brown *numFaceVertices = 1; 4680552f7358SJed Brown break; 4681552f7358SJed Brown case 2: 4682552f7358SJed Brown switch (numCorners) { 468319436ca2SJed Brown case 3: /* triangle */ 468419436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4685552f7358SJed Brown break; 468619436ca2SJed Brown case 4: /* quadrilateral */ 468719436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4688552f7358SJed Brown break; 468919436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 469019436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4691552f7358SJed Brown break; 469219436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 469319436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4694552f7358SJed Brown break; 4695552f7358SJed Brown default: 469663a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4697552f7358SJed Brown } 4698552f7358SJed Brown break; 4699552f7358SJed Brown case 3: 4700552f7358SJed Brown switch (numCorners) { 470119436ca2SJed Brown case 4: /* tetradehdron */ 470219436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 4703552f7358SJed Brown break; 470419436ca2SJed Brown case 6: /* tet cohesive cells */ 470519436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4706552f7358SJed Brown break; 470719436ca2SJed Brown case 8: /* hexahedron */ 470819436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4709552f7358SJed Brown break; 471019436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 471119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4712552f7358SJed Brown break; 471319436ca2SJed Brown case 10: /* quadratic tetrahedron */ 471419436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4715552f7358SJed Brown break; 471619436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 471719436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4718552f7358SJed Brown break; 471919436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 472019436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4721552f7358SJed Brown break; 472219436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 472319436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 4724552f7358SJed Brown break; 4725552f7358SJed Brown default: 472663a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4727552f7358SJed Brown } 4728552f7358SJed Brown break; 4729552f7358SJed Brown default: 473063a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 4731552f7358SJed Brown } 4732552f7358SJed Brown PetscFunctionReturn(0); 4733552f7358SJed Brown } 4734552f7358SJed Brown 4735552f7358SJed Brown /*@ 4736aa50250dSMatthew G. Knepley DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4737552f7358SJed Brown 4738552f7358SJed Brown Not Collective 4739552f7358SJed Brown 4740aa50250dSMatthew G. Knepley Input Parameter: 4741552f7358SJed Brown . dm - The DMPlex object 4742552f7358SJed Brown 4743aa50250dSMatthew G. Knepley Output Parameter: 4744aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth 4745552f7358SJed Brown 4746552f7358SJed Brown Level: developer 4747552f7358SJed Brown 4748db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 4749aa50250dSMatthew G. Knepley @*/ 4750aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4751aa50250dSMatthew G. Knepley { 4752aa50250dSMatthew G. Knepley PetscFunctionBegin; 4753aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4754aa50250dSMatthew G. Knepley PetscValidPointer(depthLabel, 2); 4755c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 4756aa50250dSMatthew G. Knepley PetscFunctionReturn(0); 4757aa50250dSMatthew G. Knepley } 4758aa50250dSMatthew G. Knepley 4759aa50250dSMatthew G. Knepley /*@ 4760aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 4761aa50250dSMatthew G. Knepley 4762aa50250dSMatthew G. Knepley Not Collective 4763aa50250dSMatthew G. Knepley 4764aa50250dSMatthew G. Knepley Input Parameter: 4765aa50250dSMatthew G. Knepley . dm - The DMPlex object 4766aa50250dSMatthew G. Knepley 4767aa50250dSMatthew G. Knepley Output Parameter: 4768aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 4769aa50250dSMatthew G. Knepley 4770aa50250dSMatthew G. Knepley Level: developer 4771552f7358SJed Brown 4772b1bb481bSMatthew Knepley Notes: 4773b1bb481bSMatthew Knepley This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4774dc287ab2SVaclav Hapla The point depth is described more in detail in DMPlexGetDepthStratum(). 4775dc287ab2SVaclav Hapla An empty mesh gives -1. 4776b1bb481bSMatthew Knepley 4777db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 4778552f7358SJed Brown @*/ 4779552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4780552f7358SJed Brown { 4781aa50250dSMatthew G. Knepley DMLabel label; 4782aa50250dSMatthew G. Knepley PetscInt d = 0; 4783552f7358SJed Brown 4784552f7358SJed Brown PetscFunctionBegin; 4785552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4786dadcf809SJacob Faibussowitsch PetscValidIntPointer(depth, 2); 47879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 47889566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 4789552f7358SJed Brown *depth = d-1; 4790552f7358SJed Brown PetscFunctionReturn(0); 4791552f7358SJed Brown } 4792552f7358SJed Brown 4793552f7358SJed Brown /*@ 4794552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4795552f7358SJed Brown 4796552f7358SJed Brown Not Collective 4797552f7358SJed Brown 4798552f7358SJed Brown Input Parameters: 4799552f7358SJed Brown + dm - The DMPlex object 4800570fa34dSVaclav Hapla - depth - The requested depth 4801552f7358SJed Brown 4802552f7358SJed Brown Output Parameters: 4803552f7358SJed Brown + start - The first point at this depth 4804552f7358SJed Brown - end - One beyond the last point at this depth 4805552f7358SJed Brown 4806647867b2SJed Brown Notes: 4807647867b2SJed Brown Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4808647867b2SJed Brown often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4809647867b2SJed Brown higher dimension, e.g., "edges". 4810647867b2SJed Brown 4811552f7358SJed Brown Level: developer 4812552f7358SJed Brown 4813db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 4814552f7358SJed Brown @*/ 4815570fa34dSVaclav Hapla PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 48160adebc6cSBarry Smith { 4817aa50250dSMatthew G. Knepley DMLabel label; 481863d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 4819552f7358SJed Brown 4820552f7358SJed Brown PetscFunctionBegin; 4821552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4822dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4823dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48249566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 48250d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4826570fa34dSVaclav Hapla if (depth < 0) { 482763d1a920SMatthew G. Knepley if (start) *start = pStart; 482863d1a920SMatthew G. Knepley if (end) *end = pEnd; 482963d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4830552f7358SJed Brown } 48319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 483228b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4833570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 4834552f7358SJed Brown PetscFunctionReturn(0); 4835552f7358SJed Brown } 4836552f7358SJed Brown 4837552f7358SJed Brown /*@ 4838552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4839552f7358SJed Brown 4840552f7358SJed Brown Not Collective 4841552f7358SJed Brown 4842552f7358SJed Brown Input Parameters: 4843552f7358SJed Brown + dm - The DMPlex object 4844570fa34dSVaclav Hapla - height - The requested height 4845552f7358SJed Brown 4846552f7358SJed Brown Output Parameters: 4847552f7358SJed Brown + start - The first point at this height 4848552f7358SJed Brown - end - One beyond the last point at this height 4849552f7358SJed Brown 4850647867b2SJed Brown Notes: 4851647867b2SJed Brown Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4852647867b2SJed Brown points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4853647867b2SJed Brown stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4854647867b2SJed Brown 4855552f7358SJed Brown Level: developer 4856552f7358SJed Brown 4857db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4858552f7358SJed Brown @*/ 4859570fa34dSVaclav Hapla PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 48600adebc6cSBarry Smith { 4861aa50250dSMatthew G. Knepley DMLabel label; 486263d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 4863552f7358SJed Brown 4864552f7358SJed Brown PetscFunctionBegin; 4865552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4866dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4867dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48689566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 48690d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4870570fa34dSVaclav Hapla if (height < 0) { 487163d1a920SMatthew G. Knepley if (start) *start = pStart; 487263d1a920SMatthew G. Knepley if (end) *end = pEnd; 487363d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4874552f7358SJed Brown } 48759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 487628b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 48779566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 4878570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth-1-height, start, end)); 4879552f7358SJed Brown PetscFunctionReturn(0); 4880552f7358SJed Brown } 4881552f7358SJed Brown 4882ba2698f1SMatthew G. Knepley /*@ 4883ba2698f1SMatthew G. Knepley DMPlexGetPointDepth - Get the depth of a given point 4884ba2698f1SMatthew G. Knepley 4885ba2698f1SMatthew G. Knepley Not Collective 4886ba2698f1SMatthew G. Knepley 4887d8d19677SJose E. Roman Input Parameters: 4888ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4889ba2698f1SMatthew G. Knepley - point - The point 4890ba2698f1SMatthew G. Knepley 4891ba2698f1SMatthew G. Knepley Output Parameter: 4892ba2698f1SMatthew G. Knepley . depth - The depth of the point 4893ba2698f1SMatthew G. Knepley 4894ba2698f1SMatthew G. Knepley Level: intermediate 4895ba2698f1SMatthew G. Knepley 4896db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4897ba2698f1SMatthew G. Knepley @*/ 4898ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4899ba2698f1SMatthew G. Knepley { 4900ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4901ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 490240a2aa30SMatthew G. Knepley PetscValidIntPointer(depth, 3); 49039566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 4904ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4905ba2698f1SMatthew G. Knepley } 4906ba2698f1SMatthew G. Knepley 4907ba2698f1SMatthew G. Knepley /*@ 49080c0a32dcSVaclav Hapla DMPlexGetPointHeight - Get the height of a given point 49090c0a32dcSVaclav Hapla 49100c0a32dcSVaclav Hapla Not Collective 49110c0a32dcSVaclav Hapla 4912d8d19677SJose E. Roman Input Parameters: 49130c0a32dcSVaclav Hapla + dm - The DMPlex object 49140c0a32dcSVaclav Hapla - point - The point 49150c0a32dcSVaclav Hapla 49160c0a32dcSVaclav Hapla Output Parameter: 49170c0a32dcSVaclav Hapla . height - The height of the point 49180c0a32dcSVaclav Hapla 49190c0a32dcSVaclav Hapla Level: intermediate 49200c0a32dcSVaclav Hapla 4921db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 49220c0a32dcSVaclav Hapla @*/ 49230c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 49240c0a32dcSVaclav Hapla { 49250c0a32dcSVaclav Hapla PetscInt n, pDepth; 49260c0a32dcSVaclav Hapla 49270c0a32dcSVaclav Hapla PetscFunctionBegin; 49280c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49290c0a32dcSVaclav Hapla PetscValidIntPointer(height, 3); 49309566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 49319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 49320c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 49330c0a32dcSVaclav Hapla PetscFunctionReturn(0); 49340c0a32dcSVaclav Hapla } 49350c0a32dcSVaclav Hapla 49360c0a32dcSVaclav Hapla /*@ 4937ba2698f1SMatthew G. Knepley DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4938ba2698f1SMatthew G. Knepley 4939ba2698f1SMatthew G. Knepley Not Collective 4940ba2698f1SMatthew G. Knepley 4941ba2698f1SMatthew G. Knepley Input Parameter: 4942ba2698f1SMatthew G. Knepley . dm - The DMPlex object 4943ba2698f1SMatthew G. Knepley 4944ba2698f1SMatthew G. Knepley Output Parameter: 4945ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type 4946ba2698f1SMatthew G. Knepley 4947412e9a14SMatthew G. Knepley Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4948412e9a14SMatthew G. Knepley DMCreateLabel(dm, "celltype") beforehand. 4949412e9a14SMatthew G. Knepley 4950ba2698f1SMatthew G. Knepley Level: developer 4951ba2698f1SMatthew G. Knepley 4952db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 4953ba2698f1SMatthew G. Knepley @*/ 4954ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4955ba2698f1SMatthew G. Knepley { 4956ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4957ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4958ba2698f1SMatthew G. Knepley PetscValidPointer(celltypeLabel, 2); 49599566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 4960ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 4961ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4962ba2698f1SMatthew G. Knepley } 4963ba2698f1SMatthew G. Knepley 4964ba2698f1SMatthew G. Knepley /*@ 4965ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 4966ba2698f1SMatthew G. Knepley 4967ba2698f1SMatthew G. Knepley Not Collective 4968ba2698f1SMatthew G. Knepley 4969d8d19677SJose E. Roman Input Parameters: 4970ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4971ba2698f1SMatthew G. Knepley - cell - The cell 4972ba2698f1SMatthew G. Knepley 4973ba2698f1SMatthew G. Knepley Output Parameter: 4974ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 4975ba2698f1SMatthew G. Knepley 4976ba2698f1SMatthew G. Knepley Level: intermediate 4977ba2698f1SMatthew G. Knepley 4978db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 4979ba2698f1SMatthew G. Knepley @*/ 4980ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4981ba2698f1SMatthew G. Knepley { 4982ba2698f1SMatthew G. Knepley DMLabel label; 4983ba2698f1SMatthew G. Knepley PetscInt ct; 4984ba2698f1SMatthew G. Knepley 4985ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4986ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4987ba2698f1SMatthew G. Knepley PetscValidPointer(celltype, 3); 49889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 49899566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 499063a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 4991ba2698f1SMatthew G. Knepley *celltype = (DMPolytopeType) ct; 4992ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4993ba2698f1SMatthew G. Knepley } 4994ba2698f1SMatthew G. Knepley 4995412e9a14SMatthew G. Knepley /*@ 4996412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 4997412e9a14SMatthew G. Knepley 4998412e9a14SMatthew G. Knepley Not Collective 4999412e9a14SMatthew G. Knepley 5000412e9a14SMatthew G. Knepley Input Parameters: 5001412e9a14SMatthew G. Knepley + dm - The DMPlex object 5002412e9a14SMatthew G. Knepley . cell - The cell 5003412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5004412e9a14SMatthew G. Knepley 5005412e9a14SMatthew G. Knepley Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 5006412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5007412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5008412e9a14SMatthew G. Knepley DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 5009412e9a14SMatthew G. Knepley 5010412e9a14SMatthew G. Knepley Level: advanced 5011412e9a14SMatthew G. Knepley 5012db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5013412e9a14SMatthew G. Knepley @*/ 5014412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5015412e9a14SMatthew G. Knepley { 5016412e9a14SMatthew G. Knepley DMLabel label; 5017412e9a14SMatthew G. Knepley 5018412e9a14SMatthew G. Knepley PetscFunctionBegin; 5019412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 50219566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 5022412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 5023412e9a14SMatthew G. Knepley } 5024412e9a14SMatthew G. Knepley 50250adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 50260adebc6cSBarry Smith { 5027efe440bfSMatthew G. Knepley PetscSection section, s; 5028efe440bfSMatthew G. Knepley Mat m; 50293e922f36SToby Isaac PetscInt maxHeight; 5030552f7358SJed Brown 5031552f7358SJed Brown PetscFunctionBegin; 50329566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 50339566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 50349566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 50359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 50369566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 50379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 50389566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 50399566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 50409566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 50419566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 50429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 50438f4c458bSMatthew G. Knepley 50449566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 50459566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5046552f7358SJed Brown PetscFunctionReturn(0); 5047552f7358SJed Brown } 5048552f7358SJed Brown 5049f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5050f19dbd58SToby Isaac { 50516858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 50526858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5053f19dbd58SToby Isaac 5054f19dbd58SToby Isaac PetscFunctionBegin; 5055f19dbd58SToby Isaac *field = NULL; 50569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 50579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 50586858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 50596858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5060f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 50616858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 50626858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5063f19dbd58SToby Isaac } 5064f19dbd58SToby Isaac PetscFunctionReturn(0); 5065f19dbd58SToby Isaac } 5066f19dbd58SToby Isaac 50677cd05799SMatthew G. Knepley /*@C 50687cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 50697cd05799SMatthew G. Knepley 50707cd05799SMatthew G. Knepley Not Collective 50717cd05799SMatthew G. Knepley 50727cd05799SMatthew G. Knepley Input Parameters: 50737cd05799SMatthew G. Knepley . dm - The DMPlex object 50747cd05799SMatthew G. Knepley 50757cd05799SMatthew G. Knepley Output Parameter: 50767cd05799SMatthew G. Knepley . section - The PetscSection object 50777cd05799SMatthew G. Knepley 50787cd05799SMatthew G. Knepley Level: developer 50797cd05799SMatthew G. Knepley 5080db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()` 50817cd05799SMatthew G. Knepley @*/ 50820adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 50830adebc6cSBarry Smith { 5084552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5085552f7358SJed Brown 5086552f7358SJed Brown PetscFunctionBegin; 5087552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5088552f7358SJed Brown if (section) *section = mesh->coneSection; 5089552f7358SJed Brown PetscFunctionReturn(0); 5090552f7358SJed Brown } 5091552f7358SJed Brown 50927cd05799SMatthew G. Knepley /*@C 50937cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 50947cd05799SMatthew G. Knepley 50957cd05799SMatthew G. Knepley Not Collective 50967cd05799SMatthew G. Knepley 50977cd05799SMatthew G. Knepley Input Parameters: 50987cd05799SMatthew G. Knepley . dm - The DMPlex object 50997cd05799SMatthew G. Knepley 51007cd05799SMatthew G. Knepley Output Parameter: 51017cd05799SMatthew G. Knepley . section - The PetscSection object 51027cd05799SMatthew G. Knepley 51037cd05799SMatthew G. Knepley Level: developer 51047cd05799SMatthew G. Knepley 5105db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 51067cd05799SMatthew G. Knepley @*/ 51078cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 51088cb4d582SMatthew G. Knepley { 51098cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 51108cb4d582SMatthew G. Knepley 51118cb4d582SMatthew G. Knepley PetscFunctionBegin; 51128cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51138cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 51148cb4d582SMatthew G. Knepley PetscFunctionReturn(0); 51158cb4d582SMatthew G. Knepley } 51168cb4d582SMatthew G. Knepley 51177cd05799SMatthew G. Knepley /*@C 51187cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 51197cd05799SMatthew G. Knepley 51207cd05799SMatthew G. Knepley Not Collective 51217cd05799SMatthew G. Knepley 51227cd05799SMatthew G. Knepley Input Parameters: 51237cd05799SMatthew G. Knepley . dm - The DMPlex object 51247cd05799SMatthew G. Knepley 51257cd05799SMatthew G. Knepley Output Parameter: 51267cd05799SMatthew G. Knepley . cones - The cone for each point 51277cd05799SMatthew G. Knepley 51287cd05799SMatthew G. Knepley Level: developer 51297cd05799SMatthew G. Knepley 5130db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 51317cd05799SMatthew G. Knepley @*/ 5132a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5133a6dfd86eSKarl Rupp { 5134552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5135552f7358SJed Brown 5136552f7358SJed Brown PetscFunctionBegin; 5137552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5138552f7358SJed Brown if (cones) *cones = mesh->cones; 5139552f7358SJed Brown PetscFunctionReturn(0); 5140552f7358SJed Brown } 5141552f7358SJed Brown 51427cd05799SMatthew G. Knepley /*@C 51437cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 51447cd05799SMatthew G. Knepley 51457cd05799SMatthew G. Knepley Not Collective 51467cd05799SMatthew G. Knepley 51477cd05799SMatthew G. Knepley Input Parameters: 51487cd05799SMatthew G. Knepley . dm - The DMPlex object 51497cd05799SMatthew G. Knepley 51507cd05799SMatthew G. Knepley Output Parameter: 5151b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 51527cd05799SMatthew G. Knepley 51537cd05799SMatthew G. Knepley Level: developer 51547cd05799SMatthew G. Knepley 5155b5a892a1SMatthew G. Knepley Notes: 5156b5a892a1SMatthew G. Knepley The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5157b5a892a1SMatthew G. Knepley 5158b5a892a1SMatthew G. Knepley The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5159b5a892a1SMatthew G. Knepley 5160db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()` 51617cd05799SMatthew G. Knepley @*/ 5162a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5163a6dfd86eSKarl Rupp { 5164552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5165552f7358SJed Brown 5166552f7358SJed Brown PetscFunctionBegin; 5167552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5168552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5169552f7358SJed Brown PetscFunctionReturn(0); 5170552f7358SJed Brown } 5171552f7358SJed Brown 5172552f7358SJed Brown /******************************** FEM Support **********************************/ 5173552f7358SJed Brown 51749e8305c2SJed Brown /* 51759e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 51769e8305c2SJed Brown representing a line in the section. 51779e8305c2SJed Brown */ 51789e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 51799e8305c2SJed Brown { 51809e8305c2SJed Brown PetscFunctionBeginHot; 51819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5182a433471fSStefano Zampini if (line < 0) { 5183a433471fSStefano Zampini *k = 0; 5184a433471fSStefano Zampini *Nc = 0; 5185a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 51869e8305c2SJed Brown *k = 1; 51879e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 51889e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 51899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 51909e8305c2SJed Brown *k = *k / *Nc + 1; 51919e8305c2SJed Brown } 51929e8305c2SJed Brown PetscFunctionReturn(0); 51939e8305c2SJed Brown } 51949e8305c2SJed Brown 5195a4355906SMatthew Knepley /*@ 5196bc1eb3faSJed Brown 5197bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5198bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 51991bb6d2a8SBarry Smith section provided (or the section of the DM). 5200a4355906SMatthew Knepley 5201a4355906SMatthew Knepley Input Parameters: 5202a4355906SMatthew Knepley + dm - The DM 5203a4355906SMatthew Knepley . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5204a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section 5205a4355906SMatthew Knepley 5206a4355906SMatthew Knepley Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5207a4355906SMatthew Knepley degree of the basis. 5208a4355906SMatthew Knepley 5209bc1eb3faSJed Brown Example: 5210bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5211bc1eb3faSJed Brown .vb 5212bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5213bc1eb3faSJed Brown 5214bc1eb3faSJed Brown v4 -- e6 -- v3 5215bc1eb3faSJed Brown | | 5216bc1eb3faSJed Brown e7 c0 e8 5217bc1eb3faSJed Brown | | 5218bc1eb3faSJed Brown v1 -- e5 -- v2 5219bc1eb3faSJed Brown .ve 5220bc1eb3faSJed Brown 5221bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5222bc1eb3faSJed Brown dofs in the order of points, e.g., 5223bc1eb3faSJed Brown .vb 5224bc1eb3faSJed Brown c0 -> [0,1,2,3] 5225bc1eb3faSJed Brown v1 -> [4] 5226bc1eb3faSJed Brown ... 5227bc1eb3faSJed Brown e5 -> [8, 9] 5228bc1eb3faSJed Brown .ve 5229bc1eb3faSJed Brown 5230bc1eb3faSJed Brown which corresponds to the dofs 5231bc1eb3faSJed Brown .vb 5232bc1eb3faSJed Brown 6 10 11 7 5233bc1eb3faSJed Brown 13 2 3 15 5234bc1eb3faSJed Brown 12 0 1 14 5235bc1eb3faSJed Brown 4 8 9 5 5236bc1eb3faSJed Brown .ve 5237bc1eb3faSJed Brown 5238bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5239bc1eb3faSJed Brown .vb 5240bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5241bc1eb3faSJed Brown .ve 5242bc1eb3faSJed Brown 5243bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5244bc1eb3faSJed Brown .vb 5245bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5246bc1eb3faSJed Brown .ve 5247bc1eb3faSJed Brown 5248a4355906SMatthew Knepley Level: developer 5249a4355906SMatthew Knepley 5250db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5251a4355906SMatthew Knepley @*/ 5252bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 52533194fc30SMatthew G. Knepley { 52547391a63aSMatthew G. Knepley DMLabel label; 5255bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 52569e8305c2SJed Brown PetscBool vertexchart; 52573194fc30SMatthew G. Knepley 52583194fc30SMatthew G. Knepley PetscFunctionBegin; 52599566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5260a433471fSStefano Zampini if (dim < 1) PetscFunctionReturn(0); 5261a433471fSStefano Zampini if (point < 0) { 5262a433471fSStefano Zampini PetscInt sStart,sEnd; 5263a433471fSStefano Zampini 52649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5265a433471fSStefano Zampini point = sEnd-sStart ? sStart : point; 5266a433471fSStefano Zampini } 52679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52689566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 52699566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 52707391a63aSMatthew G. Knepley if (depth == 1) {eStart = point;} 52717391a63aSMatthew G. Knepley else if (depth == dim) { 52727391a63aSMatthew G. Knepley const PetscInt *cone; 52737391a63aSMatthew G. Knepley 52749566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5275d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5276d4e6627bSStefano Zampini else if (dim == 3) { 5277d4e6627bSStefano Zampini const PetscInt *cone2; 52789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5279d4e6627bSStefano Zampini eStart = cone2[0]; 528063a3b9bcSJacob 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); 528163a3b9bcSJacob 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); 52829e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 52839e8305c2SJed Brown PetscInt pStart,pEnd,cStart,cEnd; 52849566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd)); 52859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&cStart,&cEnd)); 5286796d0a68SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5287796d0a68SJed Brown else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5288796d0a68SJed Brown else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 52899e8305c2SJed Brown } 52909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5291bb197d40SJed Brown for (PetscInt d=1; d<=dim; d++) { 5292bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5293bb197d40SJed Brown PetscInt *perm; 5294bb197d40SJed Brown 52953194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 52969566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5297bb197d40SJed Brown size += PetscPowInt(k+1, d)*Nc; 52983194fc30SMatthew G. Knepley } 52999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 53003194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5301bb197d40SJed Brown switch (d) { 5302babf31e0SJed Brown case 1: 53039566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5304babf31e0SJed Brown /* 5305babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5306babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5307babf31e0SJed Brown */ 5308babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5309babf31e0SJed Brown for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5310babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5311babf31e0SJed Brown foffset = offset; 5312babf31e0SJed Brown break; 531389eabcffSMatthew G. Knepley case 2: 53143194fc30SMatthew 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} */ 53159566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 53163194fc30SMatthew G. Knepley /* The SEM order is 53173194fc30SMatthew G. Knepley 53183194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 531989eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 53203194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 53213194fc30SMatthew G. Knepley */ 53223194fc30SMatthew G. Knepley { 53233194fc30SMatthew G. Knepley const PetscInt of = 0; 53243194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k-1); 53253194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k-1); 53263194fc30SMatthew G. Knepley const PetscInt oet = oer + (k-1); 53273194fc30SMatthew G. Knepley const PetscInt oel = oet + (k-1); 53283194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k-1); 53293194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 53303194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 53313194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 53323194fc30SMatthew G. Knepley PetscInt o; 53333194fc30SMatthew G. Knepley 53343194fc30SMatthew G. Knepley /* bottom */ 53353194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 53363194fc30SMatthew G. Knepley for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53373194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 53383194fc30SMatthew G. Knepley /* middle */ 53393194fc30SMatthew G. Knepley for (i = 0; i < k-1; ++i) { 53403194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 53413194fc30SMatthew G. Knepley for (o = of+(k-1)*i; o < of+(k-1)*(i+1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53423194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 53433194fc30SMatthew G. Knepley } 53443194fc30SMatthew G. Knepley /* top */ 53453194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 53463194fc30SMatthew G. Knepley for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53473194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 53483194fc30SMatthew G. Knepley foffset = offset; 53493194fc30SMatthew G. Knepley } 535089eabcffSMatthew G. Knepley break; 535189eabcffSMatthew G. Knepley case 3: 535289eabcffSMatthew G. Knepley /* The original hex closure is 535389eabcffSMatthew G. Knepley 535489eabcffSMatthew G. Knepley {c, 535589eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 535689eabcffSMatthew 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, 535789eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 535889eabcffSMatthew G. Knepley */ 53599566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 536089eabcffSMatthew G. Knepley /* The SEM order is 536189eabcffSMatthew G. Knepley Bottom Slice 536289eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 536389eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 536489eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 536589eabcffSMatthew G. Knepley 536689eabcffSMatthew G. Knepley Middle Slice (j) 536789eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 536889eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 536989eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 537089eabcffSMatthew G. Knepley 537189eabcffSMatthew G. Knepley Top Slice 537289eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 537389eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 537489eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 537589eabcffSMatthew G. Knepley */ 537689eabcffSMatthew G. Knepley { 537789eabcffSMatthew G. Knepley const PetscInt oc = 0; 537889eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 537989eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k-1); 538089eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k-1); 538189eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k-1); 538289eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k-1); 538389eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k-1); 538489eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k-1); 538589eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k-1); 538689eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k-1); 538789eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k-1); 538889eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k-1); 538989eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k-1); 539089eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k-1); 539189eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k-1); 539289eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k-1); 539389eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k-1); 539489eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k-1); 539589eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k-1); 539689eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k-1); 539789eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 539889eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 539989eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 540089eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 540189eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 540289eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 540389eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 540489eabcffSMatthew G. Knepley PetscInt o, n; 540589eabcffSMatthew G. Knepley 540689eabcffSMatthew G. Knepley /* Bottom Slice */ 540789eabcffSMatthew G. Knepley /* bottom */ 540889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 540989eabcffSMatthew G. Knepley for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 541089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 541189eabcffSMatthew G. Knepley /* middle */ 541289eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 541389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5414316b7f87SMax Rietmann for (n = 0; n < k-1; ++n) {o = ofb+n*(k-1)+i; for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;} 541589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 54163194fc30SMatthew G. Knepley } 541789eabcffSMatthew G. Knepley /* top */ 541889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 541989eabcffSMatthew G. Knepley for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 542089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 542189eabcffSMatthew G. Knepley 542289eabcffSMatthew G. Knepley /* Middle Slice */ 542389eabcffSMatthew G. Knepley for (j = 0; j < k-1; ++j) { 542489eabcffSMatthew G. Knepley /* bottom */ 542589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 542689eabcffSMatthew G. Knepley for (o = off+j*(k-1); o < off+(j+1)*(k-1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 542789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 542889eabcffSMatthew G. Knepley /* middle */ 542989eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 543089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 543189eabcffSMatthew G. Knepley for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc+(j*(k-1)+i)*(k-1)+n)*Nc + c + foffset; 543289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 543389eabcffSMatthew G. Knepley } 543489eabcffSMatthew G. Knepley /* top */ 543589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 543689eabcffSMatthew G. Knepley for (o = ofk+j*(k-1)+(k-2); o >= ofk+j*(k-1); --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 543789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 543889eabcffSMatthew G. Knepley } 543989eabcffSMatthew G. Knepley 544089eabcffSMatthew G. Knepley /* Top Slice */ 544189eabcffSMatthew G. Knepley /* bottom */ 544289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 544389eabcffSMatthew G. Knepley for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 544489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 544589eabcffSMatthew G. Knepley /* middle */ 544689eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 544789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 544889eabcffSMatthew G. Knepley for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 544989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 545089eabcffSMatthew G. Knepley } 545189eabcffSMatthew G. Knepley /* top */ 545289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 545389eabcffSMatthew G. Knepley for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 545489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 545589eabcffSMatthew G. Knepley 545689eabcffSMatthew G. Knepley foffset = offset; 545789eabcffSMatthew G. Knepley } 545889eabcffSMatthew G. Knepley break; 545963a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 546089eabcffSMatthew G. Knepley } 546189eabcffSMatthew G. Knepley } 546263a3b9bcSJacob Faibussowitsch PetscCheck(offset == size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 54633194fc30SMatthew G. Knepley /* Check permutation */ 54643194fc30SMatthew G. Knepley { 54653194fc30SMatthew G. Knepley PetscInt *check; 54663194fc30SMatthew G. Knepley 54679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 54681dca8a05SBarry Smith for (i = 0; i < size; ++i) { 54691dca8a05SBarry Smith check[i] = -1; 54701dca8a05SBarry 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]); 54711dca8a05SBarry Smith } 54723194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 54731dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 54749566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 54753194fc30SMatthew G. Knepley } 54769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm)); 5477a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5478a05c9aa3SJed Brown PetscInt *loc_perm; 54799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size*2, &loc_perm)); 5480a05c9aa3SJed Brown for (PetscInt i=0; i<size; i++) { 5481a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5482a05c9aa3SJed Brown loc_perm[size+i] = size + perm[i]; 5483a05c9aa3SJed Brown } 54849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm)); 5485a05c9aa3SJed Brown } 5486bb197d40SJed Brown } 54873194fc30SMatthew G. Knepley PetscFunctionReturn(0); 54883194fc30SMatthew G. Knepley } 54893194fc30SMatthew G. Knepley 5490e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5491e071409bSToby Isaac { 5492e071409bSToby Isaac PetscDS prob; 5493e071409bSToby Isaac PetscInt depth, Nf, h; 5494e071409bSToby Isaac DMLabel label; 5495e071409bSToby Isaac 5496e071409bSToby Isaac PetscFunctionBeginHot; 54979566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 5498e071409bSToby Isaac Nf = prob->Nf; 5499e071409bSToby Isaac label = dm->depthLabel; 5500e071409bSToby Isaac *dspace = NULL; 5501e071409bSToby Isaac if (field < Nf) { 5502e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5503e071409bSToby Isaac 5504e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5505e071409bSToby Isaac PetscDualSpace dsp; 5506e071409bSToby Isaac 55079566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp)); 55089566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label,&depth)); 55099566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label,point,&h)); 5510e071409bSToby Isaac h = depth - 1 - h; 5511e071409bSToby Isaac if (h) { 55129566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp,h,dspace)); 5513e071409bSToby Isaac } else { 5514e071409bSToby Isaac *dspace = dsp; 5515e071409bSToby Isaac } 5516e071409bSToby Isaac } 5517e071409bSToby Isaac } 5518e071409bSToby Isaac PetscFunctionReturn(0); 5519e071409bSToby Isaac } 5520e071409bSToby Isaac 55219fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5522a6dfd86eSKarl Rupp { 5523552f7358SJed Brown PetscScalar *array, *vArray; 5524d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 55251a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5526552f7358SJed Brown 55271b406b76SMatthew G. Knepley PetscFunctionBeginHot; 55289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 55299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 55309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 55319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 55323f7cbbe7SMatthew G. Knepley if (!values || !*values) { 55339df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55349df71ca4SMatthew G. Knepley PetscInt dof; 5535d9917b9dSMatthew G. Knepley 55369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55379df71ca4SMatthew G. Knepley size += dof; 55389df71ca4SMatthew G. Knepley } 55399df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55409df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55412a3aaacfSMatthew G. Knepley PetscInt dof; 55425a1bb5cfSMatthew G. Knepley 55435a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55455a1bb5cfSMatthew G. Knepley size += dof; 55465a1bb5cfSMatthew G. Knepley } 55473f7cbbe7SMatthew G. Knepley if (!values) { 55483f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 55493f7cbbe7SMatthew G. Knepley PetscFunctionReturn(0); 55503f7cbbe7SMatthew G. Knepley } 55519566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 5552982e9ed1SMatthew G. Knepley } else { 5553982e9ed1SMatthew G. Knepley array = *values; 5554982e9ed1SMatthew G. Knepley } 55559df71ca4SMatthew G. Knepley size = 0; 55569566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &vArray)); 55579df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55589df71ca4SMatthew G. Knepley PetscInt dof, off, d; 55599df71ca4SMatthew G. Knepley PetscScalar *varr; 5560d9917b9dSMatthew G. Knepley 55619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 55639df71ca4SMatthew G. Knepley varr = &vArray[off]; 55641a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55651a271a75SMatthew G. Knepley array[offset] = varr[d]; 55669df71ca4SMatthew G. Knepley } 55679df71ca4SMatthew G. Knepley size += dof; 55689df71ca4SMatthew G. Knepley } 55699df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55709df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55719df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 55725a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 55735a1bb5cfSMatthew G. Knepley PetscScalar *varr; 55745a1bb5cfSMatthew G. Knepley 557552ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 55785a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 55795a1bb5cfSMatthew G. Knepley if (o >= 0) { 55801a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55811a271a75SMatthew G. Knepley array[offset] = varr[d]; 55825a1bb5cfSMatthew G. Knepley } 55835a1bb5cfSMatthew G. Knepley } else { 55841a271a75SMatthew G. Knepley for (d = dof-1; d >= 0; --d, ++offset) { 55851a271a75SMatthew G. Knepley array[offset] = varr[d]; 55865a1bb5cfSMatthew G. Knepley } 55875a1bb5cfSMatthew G. Knepley } 55889df71ca4SMatthew G. Knepley size += dof; 55895a1bb5cfSMatthew G. Knepley } 55909566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &vArray)); 55919df71ca4SMatthew G. Knepley if (!*values) { 55925a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 55935a1bb5cfSMatthew G. Knepley *values = array; 55949df71ca4SMatthew G. Knepley } else { 559563a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 55968c312ff3SMatthew G. Knepley *csize = size; 55979df71ca4SMatthew G. Knepley } 55985a1bb5cfSMatthew G. Knepley PetscFunctionReturn(0); 55995a1bb5cfSMatthew G. Knepley } 5600d9917b9dSMatthew G. Knepley 560127f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 56029fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 560327f02ce8SMatthew G. Knepley { 560427f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 560527f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 560627f02ce8SMatthew G. Knepley 56079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 560827f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 560927f02ce8SMatthew G. Knepley const PetscInt r = points[p*2]; 561027f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 561127f02ce8SMatthew G. Knepley points[q*2] = r; 561227f02ce8SMatthew G. Knepley points[q*2+1] = points[p*2+1]; 561327f02ce8SMatthew G. Knepley ++q; 561427f02ce8SMatthew G. Knepley } 561527f02ce8SMatthew G. Knepley } 561627f02ce8SMatthew G. Knepley *numPoints = q; 561727f02ce8SMatthew G. Knepley return 0; 561827f02ce8SMatthew G. Knepley } 561927f02ce8SMatthew G. Knepley 562097529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 56211dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5622923c78e0SToby Isaac { 562327f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 5624923c78e0SToby Isaac PetscInt np, *pts = NULL; 5625923c78e0SToby Isaac 5626923c78e0SToby Isaac PetscFunctionBeginHot; 56279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints)); 562827f02ce8SMatthew G. Knepley if (*clPoints) { 5629923c78e0SToby Isaac PetscInt dof, off; 5630923c78e0SToby Isaac 56319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 56329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 56339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 5634923c78e0SToby Isaac np = dof/2; 5635923c78e0SToby Isaac pts = (PetscInt *) &cla[off]; 563627f02ce8SMatthew G. Knepley } else { 56379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts)); 56389566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 5639923c78e0SToby Isaac } 5640923c78e0SToby Isaac *numPoints = np; 5641923c78e0SToby Isaac *points = pts; 5642923c78e0SToby Isaac *clp = cla; 5643923c78e0SToby Isaac PetscFunctionReturn(0); 5644923c78e0SToby Isaac } 5645923c78e0SToby Isaac 56461dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5647923c78e0SToby Isaac { 5648923c78e0SToby Isaac PetscFunctionBeginHot; 5649923c78e0SToby Isaac if (!*clPoints) { 56509566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 5651923c78e0SToby Isaac } else { 56529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 5653923c78e0SToby Isaac } 5654923c78e0SToby Isaac *numPoints = 0; 5655923c78e0SToby Isaac *points = NULL; 5656923c78e0SToby Isaac *clSec = NULL; 5657923c78e0SToby Isaac *clPoints = NULL; 5658923c78e0SToby Isaac *clp = NULL; 5659923c78e0SToby Isaac PetscFunctionReturn(0); 5660923c78e0SToby Isaac } 5661923c78e0SToby Isaac 56629fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 56631a271a75SMatthew G. Knepley { 56641a271a75SMatthew G. Knepley PetscInt offset = 0, p; 566597e99dd9SToby Isaac const PetscInt **perms = NULL; 566697e99dd9SToby Isaac const PetscScalar **flips = NULL; 56671a271a75SMatthew G. Knepley 56681a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5669fe02ba77SJed Brown *size = 0; 56709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 567197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 567297e99dd9SToby Isaac const PetscInt point = points[2*p]; 567397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 567497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 56751a271a75SMatthew G. Knepley PetscInt dof, off, d; 56761a271a75SMatthew G. Knepley const PetscScalar *varr; 56771a271a75SMatthew G. Knepley 56789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 56799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 56801a271a75SMatthew G. Knepley varr = &vArray[off]; 568197e99dd9SToby Isaac if (clperm) { 568297e99dd9SToby Isaac if (perm) { 568397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 56841a271a75SMatthew G. Knepley } else { 568597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 568697e99dd9SToby Isaac } 568797e99dd9SToby Isaac if (flip) { 568897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 568997e99dd9SToby Isaac } 569097e99dd9SToby Isaac } else { 569197e99dd9SToby Isaac if (perm) { 569297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 569397e99dd9SToby Isaac } else { 569497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 569597e99dd9SToby Isaac } 569697e99dd9SToby Isaac if (flip) { 569797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 56981a271a75SMatthew G. Knepley } 56991a271a75SMatthew G. Knepley } 570097e99dd9SToby Isaac offset += dof; 570197e99dd9SToby Isaac } 57029566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 57031a271a75SMatthew G. Knepley *size = offset; 57041a271a75SMatthew G. Knepley PetscFunctionReturn(0); 57051a271a75SMatthew G. Knepley } 57061a271a75SMatthew G. Knepley 57079fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Fields_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 57081a271a75SMatthew G. Knepley { 57091a271a75SMatthew G. Knepley PetscInt offset = 0, f; 57101a271a75SMatthew G. Knepley 57111a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5712fe02ba77SJed Brown *size = 0; 57131a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 571497e99dd9SToby Isaac PetscInt p; 571597e99dd9SToby Isaac const PetscInt **perms = NULL; 571697e99dd9SToby Isaac const PetscScalar **flips = NULL; 57171a271a75SMatthew G. Knepley 57189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 571997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 572097e99dd9SToby Isaac const PetscInt point = points[2*p]; 572197e99dd9SToby Isaac PetscInt fdof, foff, b; 57221a271a75SMatthew G. Knepley const PetscScalar *varr; 572397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 572497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 57251a271a75SMatthew G. Knepley 57269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 57279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 57281a271a75SMatthew G. Knepley varr = &vArray[foff]; 572997e99dd9SToby Isaac if (clperm) { 573097e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 573197e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 573297e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 57331a271a75SMatthew G. Knepley } else { 573497e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 573597e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 573697e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 57371a271a75SMatthew G. Knepley } 573897e99dd9SToby Isaac offset += fdof; 57391a271a75SMatthew G. Knepley } 57409566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 57411a271a75SMatthew G. Knepley } 57421a271a75SMatthew G. Knepley *size = offset; 57431a271a75SMatthew G. Knepley PetscFunctionReturn(0); 57441a271a75SMatthew G. Knepley } 57451a271a75SMatthew G. Knepley 5746552f7358SJed Brown /*@C 5747552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5748552f7358SJed Brown 5749552f7358SJed Brown Not collective 5750552f7358SJed Brown 5751552f7358SJed Brown Input Parameters: 5752552f7358SJed Brown + dm - The DM 5753552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section 5754552f7358SJed Brown . v - The local vector 57556b867d5aSJose E. Roman - point - The point in the DM 5756552f7358SJed Brown 57576b867d5aSJose E. Roman Input/Output Parameters: 57586b867d5aSJose E. Roman + csize - The size of the input values array, or NULL; on output the number of values in the closure 57596b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically; 57606b867d5aSJose E. Roman if the user provided NULL, it is a borrowed array and should not be freed 576122c1ee49SMatthew G. Knepley 576222c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 576322c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 576422c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation. 576522c1ee49SMatthew G. Knepley $ 576622c1ee49SMatthew G. Knepley $ A typical use could be 576722c1ee49SMatthew G. Knepley $ 576822c1ee49SMatthew G. Knepley $ values = NULL; 57699566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 577022c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 577122c1ee49SMatthew G. Knepley $ <Compute on closure> 577222c1ee49SMatthew G. Knepley $ } 57739566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 577422c1ee49SMatthew G. Knepley $ 577522c1ee49SMatthew G. Knepley $ or 577622c1ee49SMatthew G. Knepley $ 577722c1ee49SMatthew G. Knepley $ PetscMalloc1(clMaxSize, &values); 577822c1ee49SMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) { 577922c1ee49SMatthew G. Knepley $ clSize = clMaxSize; 57809566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 578122c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 578222c1ee49SMatthew G. Knepley $ <Compute on closure> 578322c1ee49SMatthew G. Knepley $ } 578422c1ee49SMatthew G. Knepley $ } 578522c1ee49SMatthew G. Knepley $ PetscFree(values); 5786552f7358SJed Brown 5787552f7358SJed Brown Fortran Notes: 5788552f7358SJed Brown Since it returns an array, this routine is only available in Fortran 90, and you must 5789552f7358SJed Brown include petsc.h90 in your code. 5790552f7358SJed Brown 5791552f7358SJed Brown The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5792552f7358SJed Brown 5793552f7358SJed Brown Level: intermediate 5794552f7358SJed Brown 5795db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5796552f7358SJed Brown @*/ 5797552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5798552f7358SJed Brown { 5799552f7358SJed Brown PetscSection clSection; 5800d9917b9dSMatthew G. Knepley IS clPoints; 5801552f7358SJed Brown PetscInt *points = NULL; 5802c459fbc1SJed Brown const PetscInt *clp, *perm; 5803c459fbc1SJed Brown PetscInt depth, numFields, numPoints, asize; 5804552f7358SJed Brown 5805d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 5806552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58079566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 58081a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 58091a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 58109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 58119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5812552f7358SJed Brown if (depth == 1 && numFields < 2) { 58139566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5814552f7358SJed Brown PetscFunctionReturn(0); 5815552f7358SJed Brown } 58161a271a75SMatthew G. Knepley /* Get points */ 58179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5818c459fbc1SJed Brown /* Get sizes */ 5819c459fbc1SJed Brown asize = 0; 5820c459fbc1SJed Brown for (PetscInt p = 0; p < numPoints*2; p += 2) { 5821c459fbc1SJed Brown PetscInt dof; 58229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 58231a271a75SMatthew G. Knepley asize += dof; 5824552f7358SJed Brown } 5825c459fbc1SJed Brown if (values) { 5826c459fbc1SJed Brown const PetscScalar *vArray; 5827c459fbc1SJed Brown PetscInt size; 5828c459fbc1SJed Brown 5829c459fbc1SJed Brown if (*values) { 583063a3b9bcSJacob 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); 58319566063dSJacob Faibussowitsch } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 58329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm)); 58339566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 58341a271a75SMatthew G. Knepley /* Get values */ 58359566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 58369566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 583763a3b9bcSJacob Faibussowitsch PetscCheck(asize == size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size); 58381a271a75SMatthew G. Knepley /* Cleanup array */ 58399566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5840d0f6b257SMatthew G. Knepley } 5841c459fbc1SJed Brown if (csize) *csize = asize; 5842c459fbc1SJed Brown /* Cleanup points */ 58439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5844552f7358SJed Brown PetscFunctionReturn(0); 5845552f7358SJed Brown } 5846552f7358SJed Brown 5847e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5848e5c487bfSMatthew G. Knepley { 5849e5c487bfSMatthew G. Knepley DMLabel depthLabel; 5850e5c487bfSMatthew G. Knepley PetscSection clSection; 5851e5c487bfSMatthew G. Knepley IS clPoints; 5852e5c487bfSMatthew G. Knepley PetscScalar *array; 5853e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 5854e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 5855c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 5856c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5857e5c487bfSMatthew G. Knepley 5858e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 5859e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58609566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 5861e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5862e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 58639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 58649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 58659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5866e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 58679566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5868e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5869e5c487bfSMatthew G. Knepley } 5870e5c487bfSMatthew G. Knepley /* Get points */ 58719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5872c459fbc1SJed Brown for (clsize=0,p=0; p<Np; p++) { 5873c459fbc1SJed Brown PetscInt dof; 58749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 5875c459fbc1SJed Brown clsize += dof; 5876c459fbc1SJed Brown } 58779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm)); 5878e5c487bfSMatthew G. Knepley /* Filter points */ 5879e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 5880e5c487bfSMatthew G. Knepley PetscInt dep; 5881e5c487bfSMatthew G. Knepley 58829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 5883e5c487bfSMatthew G. Knepley if (dep != depth) continue; 5884e5c487bfSMatthew G. Knepley points[Np*2+0] = points[p]; 5885e5c487bfSMatthew G. Knepley points[Np*2+1] = points[p+1]; 5886e5c487bfSMatthew G. Knepley ++Np; 5887e5c487bfSMatthew G. Knepley } 5888e5c487bfSMatthew G. Knepley /* Get array */ 5889e5c487bfSMatthew G. Knepley if (!values || !*values) { 5890e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 5891e5c487bfSMatthew G. Knepley 5892e5c487bfSMatthew G. Knepley for (p = 0; p < Np*2; p += 2) { 58939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 5894e5c487bfSMatthew G. Knepley asize += dof; 5895e5c487bfSMatthew G. Knepley } 5896e5c487bfSMatthew G. Knepley if (!values) { 58979566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5898e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 5899e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5900e5c487bfSMatthew G. Knepley } 59019566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 5902e5c487bfSMatthew G. Knepley } else { 5903e5c487bfSMatthew G. Knepley array = *values; 5904e5c487bfSMatthew G. Knepley } 59059566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 5906e5c487bfSMatthew G. Knepley /* Get values */ 59079566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 59089566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 5909e5c487bfSMatthew G. Knepley /* Cleanup points */ 59109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5911e5c487bfSMatthew G. Knepley /* Cleanup array */ 59129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5913e5c487bfSMatthew G. Knepley if (!*values) { 5914e5c487bfSMatthew G. Knepley if (csize) *csize = size; 5915e5c487bfSMatthew G. Knepley *values = array; 5916e5c487bfSMatthew G. Knepley } else { 591763a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 5918e5c487bfSMatthew G. Knepley *csize = size; 5919e5c487bfSMatthew G. Knepley } 5920e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5921e5c487bfSMatthew G. Knepley } 5922e5c487bfSMatthew G. Knepley 5923552f7358SJed Brown /*@C 5924552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5925552f7358SJed Brown 5926552f7358SJed Brown Not collective 5927552f7358SJed Brown 5928552f7358SJed Brown Input Parameters: 5929552f7358SJed Brown + dm - The DM 59300298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section 5931552f7358SJed Brown . v - The local vector 5932eaf898f9SPatrick Sanan . point - The point in the DM 59330298fd71SBarry Smith . csize - The number of values in the closure, or NULL 5934552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 5935552f7358SJed Brown 593622c1ee49SMatthew 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() 593722c1ee49SMatthew G. Knepley 59383813dfbdSMatthew G Knepley Fortran Notes: 59393813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 59403813dfbdSMatthew G Knepley include petsc.h90 in your code. 59413813dfbdSMatthew G Knepley 59423813dfbdSMatthew G Knepley The csize argument is not present in the Fortran 90 binding since it is internal to the array. 59433813dfbdSMatthew G Knepley 5944552f7358SJed Brown Level: intermediate 5945552f7358SJed Brown 5946db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5947552f7358SJed Brown @*/ 59487c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5949a6dfd86eSKarl Rupp { 5950552f7358SJed Brown PetscInt size = 0; 5951552f7358SJed Brown 5952552f7358SJed Brown PetscFunctionBegin; 5953552f7358SJed Brown /* Should work without recalculating size */ 59549566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values)); 5955c9fdaa05SMatthew G. Knepley *values = NULL; 5956552f7358SJed Brown PetscFunctionReturn(0); 5957552f7358SJed Brown } 5958552f7358SJed Brown 59599fbee547SJacob Faibussowitsch static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 59609fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5961552f7358SJed Brown 59629fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 5963552f7358SJed Brown { 5964552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 5965552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5966552f7358SJed Brown PetscScalar *a; 5967552f7358SJed Brown PetscInt off, cind = 0, k; 5968552f7358SJed Brown 5969552f7358SJed Brown PetscFunctionBegin; 59709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 59719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 5972552f7358SJed Brown a = &array[off]; 5973552f7358SJed Brown if (!cdof || setBC) { 597497e99dd9SToby Isaac if (clperm) { 597597e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 597697e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5977552f7358SJed Brown } else { 597897e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 597997e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5980552f7358SJed Brown } 5981552f7358SJed Brown } else { 59829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 598397e99dd9SToby Isaac if (clperm) { 598497e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) { 5985552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 598697e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5987552f7358SJed Brown } 5988552f7358SJed Brown } else { 5989552f7358SJed Brown for (k = 0; k < dof; ++k) { 5990552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 599197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 599297e99dd9SToby Isaac } 599397e99dd9SToby Isaac } 599497e99dd9SToby Isaac } else { 599597e99dd9SToby Isaac if (perm) { 599697e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 599797e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 599897e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 599997e99dd9SToby Isaac } 600097e99dd9SToby Isaac } else { 600197e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 600297e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 600397e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 600497e99dd9SToby Isaac } 6005552f7358SJed Brown } 6006552f7358SJed Brown } 6007552f7358SJed Brown } 6008552f7358SJed Brown PetscFunctionReturn(0); 6009552f7358SJed Brown } 6010552f7358SJed Brown 60119fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 6012a5e93ea8SMatthew G. Knepley { 6013a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6014a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6015a5e93ea8SMatthew G. Knepley PetscScalar *a; 6016a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6017a5e93ea8SMatthew G. Knepley 6018a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 60199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 60209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6021a5e93ea8SMatthew G. Knepley a = &array[off]; 6022a5e93ea8SMatthew G. Knepley if (cdof) { 60239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 602497e99dd9SToby Isaac if (clperm) { 602597e99dd9SToby Isaac if (perm) { 6026a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6027a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 602897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 602997e99dd9SToby Isaac cind++; 6030a5e93ea8SMatthew G. Knepley } 6031a5e93ea8SMatthew G. Knepley } 6032a5e93ea8SMatthew G. Knepley } else { 6033a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6034a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 603597e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 603697e99dd9SToby Isaac cind++; 603797e99dd9SToby Isaac } 603897e99dd9SToby Isaac } 603997e99dd9SToby Isaac } 604097e99dd9SToby Isaac } else { 604197e99dd9SToby Isaac if (perm) { 604297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 604397e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 604497e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 604597e99dd9SToby Isaac cind++; 604697e99dd9SToby Isaac } 604797e99dd9SToby Isaac } 604897e99dd9SToby Isaac } else { 604997e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 605097e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 605197e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 605297e99dd9SToby Isaac cind++; 605397e99dd9SToby Isaac } 6054a5e93ea8SMatthew G. Knepley } 6055a5e93ea8SMatthew G. Knepley } 6056a5e93ea8SMatthew G. Knepley } 6057a5e93ea8SMatthew G. Knepley } 6058a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6059a5e93ea8SMatthew G. Knepley } 6060a5e93ea8SMatthew G. Knepley 60619fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, const PetscInt *perm, const PetscScalar *flip, PetscInt f, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 6062a6dfd86eSKarl Rupp { 6063552f7358SJed Brown PetscScalar *a; 60641a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60651a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 606697e99dd9SToby Isaac PetscInt cind = 0, b; 6067552f7358SJed Brown 6068552f7358SJed Brown PetscFunctionBegin; 60699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 60709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 60719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 60721a271a75SMatthew G. Knepley a = &array[foff]; 6073552f7358SJed Brown if (!fcdof || setBC) { 607497e99dd9SToby Isaac if (clperm) { 607597e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 607697e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6077552f7358SJed Brown } else { 607897e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 607997e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6080552f7358SJed Brown } 6081552f7358SJed Brown } else { 60829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 608397e99dd9SToby Isaac if (clperm) { 608497e99dd9SToby Isaac if (perm) { 608597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 608697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 608797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6088552f7358SJed Brown } 6089552f7358SJed Brown } else { 609097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 609197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 609297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 609397e99dd9SToby Isaac } 609497e99dd9SToby Isaac } 609597e99dd9SToby Isaac } else { 609697e99dd9SToby Isaac if (perm) { 609797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 609897e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 609997e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 610097e99dd9SToby Isaac } 610197e99dd9SToby Isaac } else { 610297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 610397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 610497e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6105552f7358SJed Brown } 6106552f7358SJed Brown } 6107552f7358SJed Brown } 6108552f7358SJed Brown } 61091a271a75SMatthew G. Knepley *offset += fdof; 6110552f7358SJed Brown PetscFunctionReturn(0); 6111552f7358SJed Brown } 6112552f7358SJed Brown 61139fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, const PetscInt perm[], const PetscScalar flip[], PetscInt f, PetscInt Ncc, const PetscInt comps[], void (*fuse)(PetscScalar*, PetscScalar), const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 6114a5e93ea8SMatthew G. Knepley { 6115a5e93ea8SMatthew G. Knepley PetscScalar *a; 61161a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 61171a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 61185da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6119ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6120a5e93ea8SMatthew G. Knepley 6121a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 61229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 61239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 61249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 61259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 61261a271a75SMatthew G. Knepley a = &array[foff]; 6127a5e93ea8SMatthew G. Knepley if (fcdof) { 6128ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 61299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 613097e99dd9SToby Isaac if (clperm) { 613197e99dd9SToby Isaac if (perm) { 6132ba322698SMatthew G. Knepley if (comps) { 6133ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6134ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61355da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6136ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6137ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6138ba322698SMatthew G. Knepley } 6139ba322698SMatthew G. Knepley } else { 614097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 614197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 614297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6143a5e93ea8SMatthew G. Knepley ++cind; 6144a5e93ea8SMatthew G. Knepley } 6145a5e93ea8SMatthew G. Knepley } 6146ba322698SMatthew G. Knepley } 6147ba322698SMatthew G. Knepley } else { 6148ba322698SMatthew G. Knepley if (comps) { 6149ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6150ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61515da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6152ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6153ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6154ba322698SMatthew G. Knepley } 6155a5e93ea8SMatthew G. Knepley } else { 615697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 615797e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 615897e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 615997e99dd9SToby Isaac ++cind; 616097e99dd9SToby Isaac } 616197e99dd9SToby Isaac } 616297e99dd9SToby Isaac } 6163ba322698SMatthew G. Knepley } 616497e99dd9SToby Isaac } else { 616597e99dd9SToby Isaac if (perm) { 6166ba322698SMatthew G. Knepley if (comps) { 6167ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6168ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61695da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6170ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6171ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6172ba322698SMatthew G. Knepley } 6173ba322698SMatthew G. Knepley } else { 617497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 617597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 617697e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 617797e99dd9SToby Isaac ++cind; 617897e99dd9SToby Isaac } 617997e99dd9SToby Isaac } 6180ba322698SMatthew G. Knepley } 6181ba322698SMatthew G. Knepley } else { 6182ba322698SMatthew G. Knepley if (comps) { 6183ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6184ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61855da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6186ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6187ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6188ba322698SMatthew G. Knepley } 618997e99dd9SToby Isaac } else { 619097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 619197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 619297e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6193a5e93ea8SMatthew G. Knepley ++cind; 6194a5e93ea8SMatthew G. Knepley } 6195a5e93ea8SMatthew G. Knepley } 6196a5e93ea8SMatthew G. Knepley } 6197a5e93ea8SMatthew G. Knepley } 6198a5e93ea8SMatthew G. Knepley } 6199ba322698SMatthew G. Knepley } 62001a271a75SMatthew G. Knepley *offset += fdof; 6201a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6202a5e93ea8SMatthew G. Knepley } 6203a5e93ea8SMatthew G. Knepley 62049fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6205a6dfd86eSKarl Rupp { 6206552f7358SJed Brown PetscScalar *array; 62071b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 62081b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6209552f7358SJed Brown 62101b406b76SMatthew G. Knepley PetscFunctionBeginHot; 62119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 62129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 62139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 62149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 62159566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6216b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6217b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p-1]; 6218b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p-1]; 6219b6ebb6e6SMatthew G. Knepley 6220b6ebb6e6SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 62219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6222b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6223b6ebb6e6SMatthew G. Knepley { 6224b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6225b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6226b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6227b6ebb6e6SMatthew G. Knepley 62289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 62299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6230b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6231b6ebb6e6SMatthew G. Knepley if (!cdof) { 6232b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6233b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6234b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6235b6ebb6e6SMatthew G. Knepley } 6236b6ebb6e6SMatthew G. Knepley } else { 6237b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6238b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6239b6ebb6e6SMatthew G. Knepley } 6240b6ebb6e6SMatthew G. Knepley } 6241b6ebb6e6SMatthew G. Knepley } else { 62429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6243b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6244b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6245b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6246b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6247b6ebb6e6SMatthew G. Knepley } 6248b6ebb6e6SMatthew G. Knepley } else { 6249b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6250b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6251b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6252b6ebb6e6SMatthew G. Knepley } 6253b6ebb6e6SMatthew G. Knepley } 6254b6ebb6e6SMatthew G. Knepley } 6255b6ebb6e6SMatthew G. Knepley } 6256b6ebb6e6SMatthew G. Knepley } 62579566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6258b6ebb6e6SMatthew G. Knepley PetscFunctionReturn(0); 6259b6ebb6e6SMatthew G. Knepley } 62601b406b76SMatthew G. Knepley 62611b406b76SMatthew G. Knepley /*@C 62621b406b76SMatthew G. Knepley DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 62631b406b76SMatthew G. Knepley 62641b406b76SMatthew G. Knepley Not collective 62651b406b76SMatthew G. Knepley 62661b406b76SMatthew G. Knepley Input Parameters: 62671b406b76SMatthew G. Knepley + dm - The DM 62681b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 62691b406b76SMatthew G. Knepley . v - The local vector 6270eaf898f9SPatrick Sanan . point - The point in the DM 62711b406b76SMatthew G. Knepley . values - The array of values 627222c1ee49SMatthew 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, 627322c1ee49SMatthew G. Knepley where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 62741b406b76SMatthew G. Knepley 62751b406b76SMatthew G. Knepley Fortran Notes: 62761b406b76SMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 62771b406b76SMatthew G. Knepley 62781b406b76SMatthew G. Knepley Level: intermediate 62791b406b76SMatthew G. Knepley 6280db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 62811b406b76SMatthew G. Knepley @*/ 62821b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 62831b406b76SMatthew G. Knepley { 62841b406b76SMatthew G. Knepley PetscSection clSection; 62851b406b76SMatthew G. Knepley IS clPoints; 62861b406b76SMatthew G. Knepley PetscScalar *array; 62871b406b76SMatthew G. Knepley PetscInt *points = NULL; 628827f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6289c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 62901b406b76SMatthew G. Knepley 62911a271a75SMatthew G. Knepley PetscFunctionBeginHot; 62921b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62939566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 62941a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 62951a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 62969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 62979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 62981b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 62999566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 63001b406b76SMatthew G. Knepley PetscFunctionReturn(0); 63011b406b76SMatthew G. Knepley } 63021a271a75SMatthew G. Knepley /* Get points */ 63039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6304c459fbc1SJed Brown for (clsize=0,p=0; p<numPoints; p++) { 6305c459fbc1SJed Brown PetscInt dof; 63069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 6307c459fbc1SJed Brown clsize += dof; 6308c459fbc1SJed Brown } 63099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 63101a271a75SMatthew G. Knepley /* Get array */ 63119566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 63121a271a75SMatthew G. Knepley /* Get values */ 6313ef90cfe2SMatthew G. Knepley if (numFields > 0) { 631497e99dd9SToby Isaac PetscInt offset = 0, f; 6315552f7358SJed Brown for (f = 0; f < numFields; ++f) { 631697e99dd9SToby Isaac const PetscInt **perms = NULL; 631797e99dd9SToby Isaac const PetscScalar **flips = NULL; 631897e99dd9SToby Isaac 63199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6320552f7358SJed Brown switch (mode) { 6321552f7358SJed Brown case INSERT_VALUES: 632297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632397e99dd9SToby Isaac const PetscInt point = points[2*p]; 632497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 632697e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6327552f7358SJed Brown } break; 6328552f7358SJed Brown case INSERT_ALL_VALUES: 632997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 633097e99dd9SToby Isaac const PetscInt point = points[2*p]; 633197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 633297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 633397e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6334552f7358SJed Brown } break; 6335a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 633697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 633797e99dd9SToby Isaac const PetscInt point = points[2*p]; 633897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 633997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6340ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6341a5e93ea8SMatthew G. Knepley } break; 6342552f7358SJed Brown case ADD_VALUES: 634397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 634497e99dd9SToby Isaac const PetscInt point = points[2*p]; 634597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 634697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 634797e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6348552f7358SJed Brown } break; 6349552f7358SJed Brown case ADD_ALL_VALUES: 635097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 635197e99dd9SToby Isaac const PetscInt point = points[2*p]; 635297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 635397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 635497e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6355552f7358SJed Brown } break; 6356304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 635797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 635897e99dd9SToby Isaac const PetscInt point = points[2*p]; 635997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 636097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6361ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6362304ab55fSMatthew G. Knepley } break; 6363552f7358SJed Brown default: 636498921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6365552f7358SJed Brown } 63669566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 63671a271a75SMatthew G. Knepley } 6368552f7358SJed Brown } else { 63691a271a75SMatthew G. Knepley PetscInt dof, off; 637097e99dd9SToby Isaac const PetscInt **perms = NULL; 637197e99dd9SToby Isaac const PetscScalar **flips = NULL; 63721a271a75SMatthew G. Knepley 63739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 6374552f7358SJed Brown switch (mode) { 6375552f7358SJed Brown case INSERT_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_FALSE, perm, flip, clperm, values, off, array); 6382552f7358SJed Brown } break; 6383552f7358SJed Brown case INSERT_ALL_VALUES: 638497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 638597e99dd9SToby Isaac const PetscInt point = points[2*p]; 638697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 638797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 638997e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6390552f7358SJed Brown } break; 6391a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 639297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 639397e99dd9SToby Isaac const PetscInt point = points[2*p]; 639497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 639597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 639797e99dd9SToby Isaac updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6398a5e93ea8SMatthew G. Knepley } break; 6399552f7358SJed Brown case ADD_VALUES: 640097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 640197e99dd9SToby Isaac const PetscInt point = points[2*p]; 640297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 640397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 640597e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6406552f7358SJed Brown } break; 6407552f7358SJed Brown case ADD_ALL_VALUES: 640897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 640997e99dd9SToby Isaac const PetscInt point = points[2*p]; 641097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 641197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 641397e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6414552f7358SJed Brown } break; 6415304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 641697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 641797e99dd9SToby Isaac const PetscInt point = points[2*p]; 641897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 641997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 642197e99dd9SToby Isaac updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6422304ab55fSMatthew G. Knepley } break; 6423552f7358SJed Brown default: 642498921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6425552f7358SJed Brown } 64269566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 6427552f7358SJed Brown } 64281a271a75SMatthew G. Knepley /* Cleanup points */ 64299566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 64301a271a75SMatthew G. Knepley /* Cleanup array */ 64319566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6432552f7358SJed Brown PetscFunctionReturn(0); 6433552f7358SJed Brown } 6434552f7358SJed Brown 64355f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 64369fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 64375f790a90SMatthew G. Knepley { 64385f790a90SMatthew G. Knepley PetscFunctionBegin; 64395f790a90SMatthew G. Knepley if (label) { 6440d6177c40SToby Isaac PetscBool contains; 6441d6177c40SToby Isaac PetscInt fdof; 64425f790a90SMatthew G. Knepley 6443d6177c40SToby Isaac PetscCall(DMLabelStratumHasPoint(label, labelId, point, &contains)); 6444d6177c40SToby Isaac if (!contains) { 64459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 64465f790a90SMatthew G. Knepley *offset += fdof; 64475f790a90SMatthew G. Knepley PetscFunctionReturn(1); 64485f790a90SMatthew G. Knepley } 64495f790a90SMatthew G. Knepley } 64505f790a90SMatthew G. Knepley PetscFunctionReturn(0); 64515f790a90SMatthew G. Knepley } 64525f790a90SMatthew G. Knepley 645397529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 64545f790a90SMatthew G. Knepley 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) 6455e07394fbSMatthew G. Knepley { 6456e07394fbSMatthew G. Knepley PetscSection clSection; 6457e07394fbSMatthew G. Knepley IS clPoints; 6458e07394fbSMatthew G. Knepley PetscScalar *array; 6459e07394fbSMatthew G. Knepley PetscInt *points = NULL; 646097529cf3SJed Brown const PetscInt *clp; 6461e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 646297e99dd9SToby Isaac PetscInt offset = 0, f; 6463e07394fbSMatthew G. Knepley 6464e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 6465e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64669566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6467e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6468e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6470e07394fbSMatthew G. Knepley /* Get points */ 64719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6472e07394fbSMatthew G. Knepley /* Get array */ 64739566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6474e07394fbSMatthew G. Knepley /* Get values */ 6475e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 647697e99dd9SToby Isaac const PetscInt **perms = NULL; 647797e99dd9SToby Isaac const PetscScalar **flips = NULL; 647897e99dd9SToby Isaac 6479e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 6480e07394fbSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 6481e07394fbSMatthew G. Knepley PetscInt fdof; 64829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 6483e07394fbSMatthew G. Knepley offset += fdof; 6484e07394fbSMatthew G. Knepley } 6485e07394fbSMatthew G. Knepley continue; 6486e07394fbSMatthew G. Knepley } 64879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6488e07394fbSMatthew G. Knepley switch (mode) { 6489e07394fbSMatthew G. Knepley case INSERT_VALUES: 649097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649197e99dd9SToby Isaac const PetscInt point = points[2*p]; 649297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64945f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64959566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 6496e07394fbSMatthew G. Knepley } break; 6497e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 649897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649997e99dd9SToby Isaac const PetscInt point = points[2*p]; 650097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 650197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65025f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65039566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 6504e07394fbSMatthew G. Knepley } break; 6505e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 650697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 650797e99dd9SToby Isaac const PetscInt point = points[2*p]; 650897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 650997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65105f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65119566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 6512e07394fbSMatthew G. Knepley } break; 6513e07394fbSMatthew G. Knepley case ADD_VALUES: 651497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 651597e99dd9SToby Isaac const PetscInt point = points[2*p]; 651697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 651797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65185f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65199566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 6520e07394fbSMatthew G. Knepley } break; 6521e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 652297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 652397e99dd9SToby Isaac const PetscInt point = points[2*p]; 652497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 652597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65265f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65279566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 6528e07394fbSMatthew G. Knepley } break; 6529e07394fbSMatthew G. Knepley default: 653098921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6531e07394fbSMatthew G. Knepley } 65329566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6533e07394fbSMatthew G. Knepley } 6534e07394fbSMatthew G. Knepley /* Cleanup points */ 65359566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6536e07394fbSMatthew G. Knepley /* Cleanup array */ 65379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6538e07394fbSMatthew G. Knepley PetscFunctionReturn(0); 6539e07394fbSMatthew G. Knepley } 6540e07394fbSMatthew G. Knepley 65417cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6542552f7358SJed Brown { 6543552f7358SJed Brown PetscMPIInt rank; 6544552f7358SJed Brown PetscInt i, j; 6545552f7358SJed Brown 6546552f7358SJed Brown PetscFunctionBegin; 65479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 654863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 654963a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 655063a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 6551b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 6552557cf195SMatthew G. Knepley if (!values) PetscFunctionReturn(0); 6553b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 65549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 6555b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 6556519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 65579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]))); 6558552f7358SJed Brown #else 65599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j])); 6560552f7358SJed Brown #endif 6561552f7358SJed Brown } 65629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6563552f7358SJed Brown } 6564552f7358SJed Brown PetscFunctionReturn(0); 6565552f7358SJed Brown } 6566552f7358SJed Brown 656705586334SMatthew G. Knepley /* 656805586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 656905586334SMatthew G. Knepley 657005586334SMatthew G. Knepley Input Parameters: 657105586334SMatthew G. Knepley + section - The section for this data layout 657236fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 657305586334SMatthew G. Knepley . point - The point contributing dofs with these indices 657405586334SMatthew G. Knepley . off - The global offset of this point 657505586334SMatthew G. Knepley . loff - The local offset of each field 6576a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 657705586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 657805586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 657905586334SMatthew G. Knepley 658005586334SMatthew G. Knepley Output Parameter: 658105586334SMatthew G. Knepley . indices - Indices for dofs on this point 658205586334SMatthew G. Knepley 658305586334SMatthew G. Knepley Level: developer 658405586334SMatthew G. Knepley 658505586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 658605586334SMatthew G. Knepley */ 658736fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6588a6dfd86eSKarl Rupp { 6589e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 6590552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6591552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6592552f7358SJed Brown PetscInt cind = 0, k; 6593552f7358SJed Brown 6594552f7358SJed Brown PetscFunctionBegin; 659508401ef6SPierre Jolivet PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 65969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 65979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 6598552f7358SJed Brown if (!cdof || setBC) { 659905586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 660005586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 660105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 660205586334SMatthew G. Knepley 660305586334SMatthew G. Knepley indices[ind] = off + k; 6604552f7358SJed Brown } 6605552f7358SJed Brown } else { 66069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 66074acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 660805586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 660905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 661005586334SMatthew G. Knepley 66114acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 66124acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 661305586334SMatthew G. Knepley indices[ind] = -(off+k+1); 66144acb8e1eSToby Isaac ++cind; 66154acb8e1eSToby Isaac } else { 661636fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 6617552f7358SJed Brown } 6618552f7358SJed Brown } 6619552f7358SJed Brown } 6620e6ccafaeSMatthew G Knepley *loff += dof; 6621552f7358SJed Brown PetscFunctionReturn(0); 6622552f7358SJed Brown } 6623552f7358SJed Brown 66247e29afd2SMatthew G. Knepley /* 662536fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 66267e29afd2SMatthew G. Knepley 662736fa2b79SJed Brown Input Parameters: 662836fa2b79SJed Brown + section - a section (global or local) 662936fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 663036fa2b79SJed Brown . point - point within section 663136fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 663236fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 663336fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 663436fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 663536fa2b79SJed Brown . permsoff - offset 663636fa2b79SJed Brown - indperm - index permutation 663736fa2b79SJed Brown 663836fa2b79SJed Brown Output Parameter: 663936fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 664036fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 664136fa2b79SJed Brown 664236fa2b79SJed Brown Notes: 664336fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 664436fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 664536fa2b79SJed Brown in the local vector. 664636fa2b79SJed Brown 664736fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 664836fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 664936fa2b79SJed Brown 665036fa2b79SJed Brown Developer Note: 665136fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 665236fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 665336fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 665436fa2b79SJed Brown 665536fa2b79SJed Brown Example: 665636fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 665736fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 665836fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 665936fa2b79SJed 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. 666036fa2b79SJed Brown 666136fa2b79SJed Brown Level: developer 66627e29afd2SMatthew G. Knepley */ 666336fa2b79SJed Brown 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[]) 6664a6dfd86eSKarl Rupp { 6665552f7358SJed Brown PetscInt numFields, foff, f; 6666552f7358SJed Brown 6667552f7358SJed Brown PetscFunctionBegin; 666808401ef6SPierre Jolivet PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 66699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6670552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 66714acb8e1eSToby Isaac PetscInt fdof, cfdof; 6672552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 66734acb8e1eSToby Isaac PetscInt cind = 0, b; 66744acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6675552f7358SJed Brown 66769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 66779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 6678552f7358SJed Brown if (!cfdof || setBC) { 667905586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 668005586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 668105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 668205586334SMatthew G. Knepley 668305586334SMatthew G. Knepley indices[ind] = off+foff+b; 668405586334SMatthew G. Knepley } 6685552f7358SJed Brown } else { 66869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 668705586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 668805586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 668905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 669005586334SMatthew G. Knepley 66914acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 669205586334SMatthew G. Knepley indices[ind] = -(off+foff+b+1); 6693552f7358SJed Brown ++cind; 6694552f7358SJed Brown } else { 669536fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 6696552f7358SJed Brown } 6697552f7358SJed Brown } 6698552f7358SJed Brown } 669936fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6700552f7358SJed Brown foffs[f] += fdof; 6701552f7358SJed Brown } 6702552f7358SJed Brown PetscFunctionReturn(0); 6703552f7358SJed Brown } 6704552f7358SJed Brown 67057e29afd2SMatthew G. Knepley /* 67067e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 67077e29afd2SMatthew G. Knepley 67087e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 6709645102dcSJed Brown 6710645102dcSJed Brown Notes: 6711645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6712645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 67137e29afd2SMatthew G. Knepley */ 6714645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 67157e29afd2SMatthew G. Knepley { 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 67554acb8e1eSToby Isaac 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 { 6757d3d1a6afSToby Isaac Mat cMat; 6758d3d1a6afSToby Isaac PetscSection aSec, cSec; 6759d3d1a6afSToby Isaac IS aIS; 6760d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 6761d3d1a6afSToby Isaac const PetscInt *anchors; 6762e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 6763d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 6764d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 6765d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 6766d3d1a6afSToby Isaac PetscInt newOffsets[32]; 6767d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 6768d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 6769d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 67706ecaa68aSToby Isaac PetscScalar *newValues=NULL,*tmpValues; 6771d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 6772d3d1a6afSToby Isaac 6773d3d1a6afSToby Isaac PetscFunctionBegin; 6774d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6775d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 67769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6777d3d1a6afSToby Isaac 67789566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 6779d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 6780d3d1a6afSToby Isaac if (aSec) { 67819566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 67829566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 67839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd)); 6784d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 6785d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 6786d3d1a6afSToby Isaac * into the global matrix anyway) */ 6787d3d1a6afSToby Isaac for (p = 0; p < 2*numPoints; p+=2) { 6788d3d1a6afSToby Isaac PetscInt b = points[p]; 67894b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6790d3d1a6afSToby Isaac 67919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 67924b2f2278SToby Isaac if (!bSecDof) { 67934b2f2278SToby Isaac continue; 67944b2f2278SToby Isaac } 6795d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 67969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,b,&bDof)); 6797d3d1a6afSToby Isaac } 6798d3d1a6afSToby Isaac if (bDof) { 6799d3d1a6afSToby Isaac /* this point is constrained */ 6800d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 6801d3d1a6afSToby Isaac PetscInt bOff, q; 6802d3d1a6afSToby Isaac 6803d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 6804d3d1a6afSToby Isaac newNumPoints += bDof; 68059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,b,&bOff)); 6806d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6807d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6808d3d1a6afSToby Isaac PetscInt aDof; 6809d3d1a6afSToby Isaac 68109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 6811d3d1a6afSToby Isaac newNumIndices += aDof; 6812d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6813d3d1a6afSToby Isaac PetscInt fDof; 6814d3d1a6afSToby Isaac 68159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 6816d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6817d3d1a6afSToby Isaac } 6818d3d1a6afSToby Isaac } 6819d3d1a6afSToby Isaac } 6820d3d1a6afSToby Isaac else { 6821d3d1a6afSToby Isaac /* this point is not constrained */ 6822d3d1a6afSToby Isaac newNumPoints++; 68234b2f2278SToby Isaac newNumIndices += bSecDof; 6824d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6825d3d1a6afSToby Isaac PetscInt fDof; 6826d3d1a6afSToby Isaac 68279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6828d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6829d3d1a6afSToby Isaac } 6830d3d1a6afSToby Isaac } 6831d3d1a6afSToby Isaac } 6832d3d1a6afSToby Isaac } 6833d3d1a6afSToby Isaac if (!anyConstrained) { 683472b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 683572b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 683672b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 683772b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 68389566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors)); 6839d3d1a6afSToby Isaac PetscFunctionReturn(0); 6840d3d1a6afSToby Isaac } 6841d3d1a6afSToby Isaac 68426ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 68436ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 68446ecaa68aSToby Isaac 6845f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6846d3d1a6afSToby Isaac 68476ecaa68aSToby Isaac if (!outPoints && !outValues) { 68486ecaa68aSToby Isaac if (offsets) { 68496ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 68506ecaa68aSToby Isaac offsets[f] = newOffsets[f]; 68516ecaa68aSToby Isaac } 68526ecaa68aSToby Isaac } 68539566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors)); 68546ecaa68aSToby Isaac PetscFunctionReturn(0); 68556ecaa68aSToby Isaac } 68566ecaa68aSToby Isaac 68571dca8a05SBarry 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); 6858d3d1a6afSToby Isaac 68599566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 6860d3d1a6afSToby Isaac 6861d3d1a6afSToby Isaac /* workspaces */ 6862d3d1a6afSToby Isaac if (numFields) { 6863d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 68649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 68659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 6866d3d1a6afSToby Isaac } 6867d3d1a6afSToby Isaac } 6868d3d1a6afSToby Isaac else { 68699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 68709566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0])); 6871d3d1a6afSToby Isaac } 6872d3d1a6afSToby Isaac 6873d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 6874d3d1a6afSToby Isaac if (numFields) { 68754b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 68764b2f2278SToby Isaac 6877d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6878d3d1a6afSToby Isaac PetscInt b = points[2*p]; 68794b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6880d3d1a6afSToby Isaac 68819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 68824b2f2278SToby Isaac if (!bSecDof) { 68834b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 68844b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 68854b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 68864b2f2278SToby Isaac } 68874b2f2278SToby Isaac continue; 68884b2f2278SToby Isaac } 6889d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 68909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6891d3d1a6afSToby Isaac } 6892d3d1a6afSToby Isaac if (bDof) { 6893d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6894d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 6895d3d1a6afSToby Isaac 68969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 68979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6898d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6899d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6900d3d1a6afSToby Isaac PetscInt aFDof; 6901d3d1a6afSToby Isaac 69029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 6903d3d1a6afSToby Isaac allFDof += aFDof; 6904d3d1a6afSToby Isaac } 6905d3d1a6afSToby Isaac newPointOffsets[f][p+1] = allFDof; 6906d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = fDof * allFDof; 6907d3d1a6afSToby Isaac } 6908d3d1a6afSToby Isaac } 6909d3d1a6afSToby Isaac else { 6910d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6911d3d1a6afSToby Isaac PetscInt fDof; 6912d3d1a6afSToby Isaac 69139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6914d3d1a6afSToby Isaac newPointOffsets[f][p+1] = fDof; 6915d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = 0; 6916d3d1a6afSToby Isaac } 6917d3d1a6afSToby Isaac } 6918d3d1a6afSToby Isaac } 69194b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 69204b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 69214b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 6922d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6923d3d1a6afSToby Isaac newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6924d3d1a6afSToby Isaac pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6925d3d1a6afSToby Isaac } 692619f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 692719f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 69289566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 6929d3d1a6afSToby Isaac } 6930d3d1a6afSToby Isaac } 6931d3d1a6afSToby Isaac else { 6932d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6933d3d1a6afSToby Isaac PetscInt b = points[2*p]; 69344b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6935d3d1a6afSToby Isaac 69369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 69374b2f2278SToby Isaac if (!bSecDof) { 69384b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 69394b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 69404b2f2278SToby Isaac continue; 69414b2f2278SToby Isaac } 6942d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6944d3d1a6afSToby Isaac } 6945d3d1a6afSToby Isaac if (bDof) { 69464b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 6947d3d1a6afSToby Isaac 69489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6949d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6950d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 6951d3d1a6afSToby Isaac 69529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 6953d3d1a6afSToby Isaac allDof += aDof; 6954d3d1a6afSToby Isaac } 6955d3d1a6afSToby Isaac newPointOffsets[0][p+1] = allDof; 69564b2f2278SToby Isaac pointMatOffsets[0][p+1] = bSecDof * allDof; 6957d3d1a6afSToby Isaac } 6958d3d1a6afSToby Isaac else { 69594b2f2278SToby Isaac newPointOffsets[0][p+1] = bSecDof; 6960d3d1a6afSToby Isaac pointMatOffsets[0][p+1] = 0; 6961d3d1a6afSToby Isaac } 6962d3d1a6afSToby Isaac } 6963d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 6964d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 6965d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6966d3d1a6afSToby Isaac newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6967d3d1a6afSToby Isaac pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6968d3d1a6afSToby Isaac } 69699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 6970d3d1a6afSToby Isaac } 6971d3d1a6afSToby Isaac 69726ecaa68aSToby Isaac /* output arrays */ 69739566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 69746ecaa68aSToby Isaac 6975d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 69769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 69779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 69789566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices)); 69799566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 6980d3d1a6afSToby Isaac if (numFields) { 6981d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 6982d3d1a6afSToby Isaac PetscInt b = points[2*p]; 6983d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 69844b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6985d3d1a6afSToby Isaac 69869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 69874b2f2278SToby Isaac if (!bSecDof) { 69884b2f2278SToby Isaac continue; 69894b2f2278SToby Isaac } 6990d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6992d3d1a6afSToby Isaac } 6993d3d1a6afSToby Isaac if (bDof) { 6994d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6995d3d1a6afSToby Isaac 6996d3d1a6afSToby Isaac fStart[0] = 0; 6997d3d1a6afSToby Isaac fEnd[0] = 0; 6998d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6999d3d1a6afSToby Isaac PetscInt fDof; 7000d3d1a6afSToby Isaac 70019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7002d3d1a6afSToby Isaac fStart[f+1] = fStart[f] + fDof; 7003d3d1a6afSToby Isaac fEnd[f+1] = fStart[f+1]; 7004d3d1a6afSToby Isaac } 70059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 70069566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7007d3d1a6afSToby Isaac 7008d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7009d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7010d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7011d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7012d3d1a6afSToby Isaac 7013d3d1a6afSToby Isaac fAnchorStart[f+1] = fAnchorStart[f] + fDof; 7014d3d1a6afSToby Isaac fAnchorEnd[f+1] = fAnchorStart[f + 1]; 7015d3d1a6afSToby Isaac } 70169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7017d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7018d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7019d3d1a6afSToby Isaac 7020d3d1a6afSToby 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 */ 7021d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7022d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70249566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7025d3d1a6afSToby Isaac } 7026d3d1a6afSToby Isaac newP += bDof; 7027d3d1a6afSToby Isaac 70286ecaa68aSToby Isaac if (outValues) { 7029d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 7030d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 70319566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p])); 7032d3d1a6afSToby Isaac } 7033d3d1a6afSToby Isaac } 70346ecaa68aSToby Isaac } 7035d3d1a6afSToby Isaac else { 7036d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7037d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7038d3d1a6afSToby Isaac newP++; 7039d3d1a6afSToby Isaac } 7040d3d1a6afSToby Isaac } 7041d3d1a6afSToby Isaac } else { 7042d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7043d3d1a6afSToby Isaac PetscInt b = points[2*p]; 7044d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 70454b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7046d3d1a6afSToby Isaac 70479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 70484b2f2278SToby Isaac if (!bSecDof) { 70494b2f2278SToby Isaac continue; 70504b2f2278SToby Isaac } 7051d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 70529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7053d3d1a6afSToby Isaac } 7054d3d1a6afSToby Isaac if (bDof) { 7055d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7056d3d1a6afSToby Isaac 70579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 70589566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7059d3d1a6afSToby Isaac 70609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset (aSec, b, &bOff)); 7061d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7062d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7063d3d1a6afSToby Isaac 7064d3d1a6afSToby 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 */ 7065d3d1a6afSToby Isaac 7066d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7067d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70699566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7070d3d1a6afSToby Isaac } 7071d3d1a6afSToby Isaac newP += bDof; 7072d3d1a6afSToby Isaac 7073d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 70746ecaa68aSToby Isaac if (outValues) { 70759566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p])); 7076d3d1a6afSToby Isaac } 70776ecaa68aSToby Isaac } 7078d3d1a6afSToby Isaac else { 7079d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7080d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7081d3d1a6afSToby Isaac newP++; 7082d3d1a6afSToby Isaac } 7083d3d1a6afSToby Isaac } 7084d3d1a6afSToby Isaac } 7085d3d1a6afSToby Isaac 70866ecaa68aSToby Isaac if (outValues) { 70879566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 70889566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues,newNumIndices*numIndices)); 7089d3d1a6afSToby Isaac /* multiply constraints on the right */ 7090d3d1a6afSToby Isaac if (numFields) { 7091d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7092d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7093d3d1a6afSToby Isaac 7094d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7095d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7096d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7097d3d1a6afSToby Isaac PetscInt c, r, k; 7098d3d1a6afSToby Isaac PetscInt dof; 7099d3d1a6afSToby Isaac 71009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,b,f,&dof)); 71014b2f2278SToby Isaac if (!dof) { 71024b2f2278SToby Isaac continue; 71034b2f2278SToby Isaac } 7104d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7105d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7106d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7107d3d1a6afSToby Isaac 7108d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7109d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7110d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 71114acb8e1eSToby Isaac tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7112d3d1a6afSToby Isaac } 7113d3d1a6afSToby Isaac } 7114d3d1a6afSToby Isaac } 7115d3d1a6afSToby Isaac } 7116d3d1a6afSToby Isaac else { 7117d3d1a6afSToby Isaac /* copy this column as is */ 7118d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7119d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7120d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7121d3d1a6afSToby Isaac } 7122d3d1a6afSToby Isaac } 7123d3d1a6afSToby Isaac } 7124d3d1a6afSToby Isaac oldOff += dof; 7125d3d1a6afSToby Isaac } 7126d3d1a6afSToby Isaac } 7127d3d1a6afSToby Isaac } 7128d3d1a6afSToby Isaac else { 7129d3d1a6afSToby Isaac PetscInt oldOff = 0; 7130d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7131d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7132d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7133d3d1a6afSToby Isaac PetscInt c, r, k; 7134d3d1a6afSToby Isaac PetscInt dof; 7135d3d1a6afSToby Isaac 71369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&dof)); 71374b2f2278SToby Isaac if (!dof) { 71384b2f2278SToby Isaac continue; 71394b2f2278SToby Isaac } 7140d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7141d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7142d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7143d3d1a6afSToby Isaac 7144d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7145d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7146d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7147d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7148d3d1a6afSToby Isaac } 7149d3d1a6afSToby Isaac } 7150d3d1a6afSToby Isaac } 7151d3d1a6afSToby Isaac } 7152d3d1a6afSToby Isaac else { 7153d3d1a6afSToby Isaac /* copy this column as is */ 7154d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7155d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7156d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7157d3d1a6afSToby Isaac } 7158d3d1a6afSToby Isaac } 7159d3d1a6afSToby Isaac } 7160d3d1a6afSToby Isaac oldOff += dof; 7161d3d1a6afSToby Isaac } 7162d3d1a6afSToby Isaac } 7163d3d1a6afSToby Isaac 71646ecaa68aSToby Isaac if (multiplyLeft) { 71659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues)); 71669566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues,newNumIndices*newNumIndices)); 7167d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7168d3d1a6afSToby Isaac if (numFields) { 7169d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7170d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7171d3d1a6afSToby Isaac 7172d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7173d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7174d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7175d3d1a6afSToby Isaac PetscInt c, r, k; 7176d3d1a6afSToby Isaac PetscInt dof; 7177d3d1a6afSToby Isaac 71789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,b,f,&dof)); 7179d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7180d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7181d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7182d3d1a6afSToby Isaac 7183d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7184d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7185d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7186d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7187d3d1a6afSToby Isaac } 7188d3d1a6afSToby Isaac } 7189d3d1a6afSToby Isaac } 7190d3d1a6afSToby Isaac } 7191d3d1a6afSToby Isaac else { 7192d3d1a6afSToby Isaac /* copy this row as is */ 7193d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7194d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7195d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7196d3d1a6afSToby Isaac } 7197d3d1a6afSToby Isaac } 7198d3d1a6afSToby Isaac } 7199d3d1a6afSToby Isaac oldOff += dof; 7200d3d1a6afSToby Isaac } 7201d3d1a6afSToby Isaac } 7202d3d1a6afSToby Isaac } 7203d3d1a6afSToby Isaac else { 7204d3d1a6afSToby Isaac PetscInt oldOff = 0; 7205d3d1a6afSToby Isaac 7206d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7207d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7208d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7209d3d1a6afSToby Isaac PetscInt c, r, k; 7210d3d1a6afSToby Isaac PetscInt dof; 7211d3d1a6afSToby Isaac 72129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&dof)); 7213d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7214d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7215d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7216d3d1a6afSToby Isaac 7217d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7218d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7219d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7220d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7221d3d1a6afSToby Isaac } 7222d3d1a6afSToby Isaac } 7223d3d1a6afSToby Isaac } 7224d3d1a6afSToby Isaac } 7225d3d1a6afSToby Isaac else { 7226d3d1a6afSToby Isaac /* copy this row as is */ 72279fc93327SToby Isaac for (r = 0; r < dof; r++) { 7228d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7229d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7230d3d1a6afSToby Isaac } 7231d3d1a6afSToby Isaac } 7232d3d1a6afSToby Isaac } 7233d3d1a6afSToby Isaac oldOff += dof; 7234d3d1a6afSToby Isaac } 7235d3d1a6afSToby Isaac } 7236d3d1a6afSToby Isaac 72379566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 72386ecaa68aSToby Isaac } 72396ecaa68aSToby Isaac else { 72406ecaa68aSToby Isaac newValues = tmpValues; 72416ecaa68aSToby Isaac } 72426ecaa68aSToby Isaac } 72436ecaa68aSToby Isaac 7244d3d1a6afSToby Isaac /* clean up */ 72459566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices)); 72469566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 72476ecaa68aSToby Isaac 7248d3d1a6afSToby Isaac if (numFields) { 7249d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 72509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 72519566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 72529566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 7253d3d1a6afSToby Isaac } 7254d3d1a6afSToby Isaac } 7255d3d1a6afSToby Isaac else { 72569566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 72579566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 72589566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0])); 7259d3d1a6afSToby Isaac } 72609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 7261d3d1a6afSToby Isaac 7262d3d1a6afSToby Isaac /* output */ 72636ecaa68aSToby Isaac if (outPoints) { 7264d3d1a6afSToby Isaac *outPoints = newPoints; 72656ecaa68aSToby Isaac } 72666ecaa68aSToby Isaac else { 72679566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 72686ecaa68aSToby Isaac } 726931620726SToby Isaac if (outValues) { 7270d3d1a6afSToby Isaac *outValues = newValues; 72716ecaa68aSToby Isaac } 72726ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 7273d3d1a6afSToby Isaac offsets[f] = newOffsets[f]; 7274d3d1a6afSToby Isaac } 7275d3d1a6afSToby Isaac PetscFunctionReturn(0); 7276d3d1a6afSToby Isaac } 7277d3d1a6afSToby Isaac 72784a1e0b3eSMatthew G. Knepley /*@C 727971f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 72807cd05799SMatthew G. Knepley 72817cd05799SMatthew G. Knepley Not collective 72827cd05799SMatthew G. Knepley 72837cd05799SMatthew G. Knepley Input Parameters: 72847cd05799SMatthew G. Knepley + dm - The DM 728571f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 728671f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 728771f0bbf9SMatthew G. Knepley . point - The point defining the closure 728871f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 72897cd05799SMatthew G. Knepley 729071f0bbf9SMatthew G. Knepley Output Parameters: 729171f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 729271f0bbf9SMatthew G. Knepley . indices - The dof indices 729371f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 729471f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 72957cd05799SMatthew G. Knepley 729636fa2b79SJed Brown Notes: 729736fa2b79SJed Brown Must call DMPlexRestoreClosureIndices() to free allocated memory 729836fa2b79SJed Brown 729936fa2b79SJed Brown If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 730036fa2b79SJed Brown of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 730136fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 730236fa2b79SJed Brown indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 730336fa2b79SJed Brown indices (with the above semantics) are implied. 73047cd05799SMatthew G. Knepley 73057cd05799SMatthew G. Knepley Level: advanced 73067cd05799SMatthew G. Knepley 7307db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 73084a1e0b3eSMatthew G. Knepley @*/ 730971f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 731071f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 73117773e69fSMatthew G. Knepley { 731271f0bbf9SMatthew G. Knepley /* Closure ordering */ 73137773e69fSMatthew G. Knepley PetscSection clSection; 73147773e69fSMatthew G. Knepley IS clPoints; 731571f0bbf9SMatthew G. Knepley const PetscInt *clp; 731671f0bbf9SMatthew G. Knepley PetscInt *points; 731771f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 731871f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 73194acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 732071f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 732171f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 732271f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 732371f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 732471f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 732571f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 732671f0bbf9SMatthew G. Knepley 732771f0bbf9SMatthew G. Knepley PetscInt *idx; 732871f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 732971f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 73307773e69fSMatthew G. Knepley 733171f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 73327773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 73337773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 733436fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7335dadcf809SJacob Faibussowitsch if (numIndices) PetscValidIntPointer(numIndices, 6); 733671f0bbf9SMatthew G. Knepley if (indices) PetscValidPointer(indices, 7); 7337dadcf809SJacob Faibussowitsch if (outOffsets) PetscValidIntPointer(outOffsets, 8); 733871f0bbf9SMatthew G. Knepley if (values) PetscValidPointer(values, 9); 73399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 734063a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 73419566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 734271f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 73439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7344c459fbc1SJed Brown if (useClPerm) { 7345c459fbc1SJed Brown PetscInt depth, clsize; 73469566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7347c459fbc1SJed Brown for (clsize=0,p=0; p<Ncl; p++) { 7348c459fbc1SJed Brown PetscInt dof; 73499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 7350c459fbc1SJed Brown clsize += dof; 7351c459fbc1SJed Brown } 73529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 7353c459fbc1SJed Brown } 735471f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 735571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl*2; p += 2) { 73567773e69fSMatthew G. Knepley PetscInt dof, fdof; 73577773e69fSMatthew G. Knepley 73589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 73597773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 73609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 73617773e69fSMatthew G. Knepley offsets[f+1] += fdof; 73627773e69fSMatthew G. Knepley } 736371f0bbf9SMatthew G. Knepley Ni += dof; 73647773e69fSMatthew G. Knepley } 73657773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 73661dca8a05SBarry 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); 736771f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 736871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73699566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73709566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 737171f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 737271f0bbf9SMatthew G. Knepley if (values && flips[f]) { 737371f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 73746ecaa68aSToby Isaac 737571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 737671f0bbf9SMatthew G. Knepley PetscInt pnt = points[2*p], fdof; 737771f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 737871f0bbf9SMatthew G. Knepley 73799566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 73809566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 738171f0bbf9SMatthew G. Knepley if (flip) { 738271f0bbf9SMatthew G. Knepley PetscInt i, j, k; 738371f0bbf9SMatthew G. Knepley 738471f0bbf9SMatthew G. Knepley if (!valCopy) { 73859566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 738671f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 738771f0bbf9SMatthew G. Knepley *values = valCopy; 738871f0bbf9SMatthew G. Knepley } 738971f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 739071f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 739171f0bbf9SMatthew G. Knepley 739271f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 739371f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 739471f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 73956ecaa68aSToby Isaac } 73966ecaa68aSToby Isaac } 739771f0bbf9SMatthew G. Knepley } 739871f0bbf9SMatthew G. Knepley foffset += fdof; 739971f0bbf9SMatthew G. Knepley } 740071f0bbf9SMatthew G. Knepley } 740171f0bbf9SMatthew G. Knepley } 740271f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 74039566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 740471f0bbf9SMatthew G. Knepley if (NclC) { 74059566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 740671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74079566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 74089566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 740971f0bbf9SMatthew G. Knepley } 741071f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74119566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 74129566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 741371f0bbf9SMatthew G. Knepley } 74149566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 741571f0bbf9SMatthew G. Knepley Ncl = NclC; 741671f0bbf9SMatthew G. Knepley Ni = NiC; 741771f0bbf9SMatthew G. Knepley points = pointsC; 741871f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 741971f0bbf9SMatthew G. Knepley } 742071f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 74219566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 742271f0bbf9SMatthew G. Knepley if (Nf) { 742371f0bbf9SMatthew G. Knepley PetscInt idxOff; 742471f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 742571f0bbf9SMatthew G. Knepley 742671f0bbf9SMatthew G. Knepley if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 74279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 742871f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 742971f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 743071f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 743171f0bbf9SMatthew G. Knepley 74329566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 74337773e69fSMatthew G. Knepley } 74347773e69fSMatthew G. Knepley } else { 743571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 743671f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 743771f0bbf9SMatthew G. Knepley 74389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 743971f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 744071f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 744171f0bbf9SMatthew G. Knepley * global section. */ 74429566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 744371f0bbf9SMatthew G. Knepley } 744471f0bbf9SMatthew G. Knepley } 744571f0bbf9SMatthew G. Knepley } else { 744671f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 744771f0bbf9SMatthew G. Knepley 744871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 744971f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 74504acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 74514acb8e1eSToby Isaac 74529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 745371f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 745471f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 74559566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 74567773e69fSMatthew G. Knepley } 74577773e69fSMatthew G. Knepley } 745871f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 745971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74609566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 74619566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 74624acb8e1eSToby Isaac } 746371f0bbf9SMatthew G. Knepley if (NclC) { 74649566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC)); 74657773e69fSMatthew G. Knepley } else { 74669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 74677773e69fSMatthew G. Knepley } 746871f0bbf9SMatthew G. Knepley 746971f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 747071f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 74717773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74727773e69fSMatthew G. Knepley } 74737773e69fSMatthew G. Knepley 74747cd05799SMatthew G. Knepley /*@C 747571f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 74767cd05799SMatthew G. Knepley 74777cd05799SMatthew G. Knepley Not collective 74787cd05799SMatthew G. Knepley 74797cd05799SMatthew G. Knepley Input Parameters: 74807cd05799SMatthew G. Knepley + dm - The DM 748171f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 748271f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 748371f0bbf9SMatthew G. Knepley . point - The point defining the closure 748471f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 748571f0bbf9SMatthew G. Knepley 748671f0bbf9SMatthew G. Knepley Output Parameters: 748771f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 748871f0bbf9SMatthew G. Knepley . indices - The dof indices 748971f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 749071f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 749171f0bbf9SMatthew G. Knepley 749271f0bbf9SMatthew G. Knepley Notes: 749371f0bbf9SMatthew G. Knepley If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 749471f0bbf9SMatthew G. Knepley 749571f0bbf9SMatthew G. Knepley If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 749671f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 749771f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 749871f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 749971f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 75007cd05799SMatthew G. Knepley 75017cd05799SMatthew G. Knepley Level: advanced 75027cd05799SMatthew G. Knepley 7503db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 75047cd05799SMatthew G. Knepley @*/ 750571f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 750671f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 75077773e69fSMatthew G. Knepley { 75087773e69fSMatthew G. Knepley PetscFunctionBegin; 75097773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7510064a246eSJacob Faibussowitsch PetscValidPointer(indices, 7); 75119566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 75127773e69fSMatthew G. Knepley PetscFunctionReturn(0); 75137773e69fSMatthew G. Knepley } 75147773e69fSMatthew G. Knepley 75157f5d1fdeSMatthew G. Knepley /*@C 75167f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 75177f5d1fdeSMatthew G. Knepley 75187f5d1fdeSMatthew G. Knepley Not collective 75197f5d1fdeSMatthew G. Knepley 75207f5d1fdeSMatthew G. Knepley Input Parameters: 75217f5d1fdeSMatthew G. Knepley + dm - The DM 7522ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section 7523ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section 75247f5d1fdeSMatthew G. Knepley . A - The matrix 7525eaf898f9SPatrick Sanan . point - The point in the DM 75267f5d1fdeSMatthew G. Knepley . values - The array of values 75277f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75287f5d1fdeSMatthew G. Knepley 75297f5d1fdeSMatthew G. Knepley Fortran Notes: 75307f5d1fdeSMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 75317f5d1fdeSMatthew G. Knepley 75327f5d1fdeSMatthew G. Knepley Level: intermediate 75337f5d1fdeSMatthew G. Knepley 7534db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 75357f5d1fdeSMatthew G. Knepley @*/ 75367c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7537552f7358SJed Brown { 7538552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7539552f7358SJed Brown PetscInt *indices; 754071f0bbf9SMatthew G. Knepley PetscInt numIndices; 754171f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 7542552f7358SJed Brown PetscErrorCode ierr; 7543552f7358SJed Brown 7544552f7358SJed Brown PetscFunctionBegin; 7545552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 75469566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 75473dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 75489566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 75493dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 75503dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7551552f7358SJed Brown 75529566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75530d644c17SKarl Rupp 75549566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 7555d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 75564a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7557552f7358SJed Brown if (ierr) { 7558552f7358SJed Brown PetscMPIInt rank; 7559552f7358SJed Brown 75609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 75619566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 75629566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 75639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75649566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 7565c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7566552f7358SJed Brown } 75674a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 75684a1e0b3eSMatthew G. Knepley PetscInt i; 75699566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 757063a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 75719566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 75724a1e0b3eSMatthew G. Knepley } 757371f0bbf9SMatthew G. Knepley 75749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75759566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 757671f0bbf9SMatthew G. Knepley PetscFunctionReturn(0); 75774acb8e1eSToby Isaac } 757871f0bbf9SMatthew G. Knepley 75794a1e0b3eSMatthew G. Knepley /*@C 75804a1e0b3eSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 75814a1e0b3eSMatthew G. Knepley 75824a1e0b3eSMatthew G. Knepley Not collective 75834a1e0b3eSMatthew G. Knepley 75844a1e0b3eSMatthew G. Knepley Input Parameters: 75854a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields 75864a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 75874a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 75884a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields 75894a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 75904a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 75914a1e0b3eSMatthew G. Knepley . A - The matrix 75924a1e0b3eSMatthew G. Knepley . point - The point in the DMs 75934a1e0b3eSMatthew G. Knepley . values - The array of values 75944a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75954a1e0b3eSMatthew G. Knepley 75964a1e0b3eSMatthew G. Knepley Level: intermediate 75974a1e0b3eSMatthew G. Knepley 7598db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 75994a1e0b3eSMatthew G. Knepley @*/ 760071f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 760171f0bbf9SMatthew G. Knepley { 760271f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmRow->data; 760371f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 760471f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 760571f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 760671f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 760771f0bbf9SMatthew G. Knepley 760871f0bbf9SMatthew G. Knepley PetscFunctionBegin; 760971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 76109566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 761171f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 76129566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 761371f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 761471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 76159566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 761671f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 76179566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 761871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 761971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 762071f0bbf9SMatthew G. Knepley 76219566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76229566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 762371f0bbf9SMatthew G. Knepley 76249566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 7625d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 76264a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 762771f0bbf9SMatthew G. Knepley if (ierr) { 762871f0bbf9SMatthew G. Knepley PetscMPIInt rank; 762971f0bbf9SMatthew G. Knepley 76309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 76319566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 76329566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 76339566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values)); 76359566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7636d3d1a6afSToby Isaac } 763771f0bbf9SMatthew G. Knepley 76389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 76409566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7641552f7358SJed Brown PetscFunctionReturn(0); 7642552f7358SJed Brown } 7643552f7358SJed Brown 7644de41b84cSMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7645de41b84cSMatthew G. Knepley { 7646de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmf->data; 7647de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 7648de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 7649de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 765017c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7651de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 7652412e9a14SMatthew G. Knepley DMPolytopeType ct; 76534ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7654de41b84cSMatthew G. Knepley PetscErrorCode ierr; 7655de41b84cSMatthew G. Knepley 7656de41b84cSMatthew G. Knepley PetscFunctionBegin; 7657de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7658de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 76599566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 7660de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 76619566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 7662de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 76639566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 7664de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 76659566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 7666de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7667de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 76689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 766963a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 76709566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 76719566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 7672de41b84cSMatthew G. Knepley /* Column indices */ 76739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 76744ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 7675de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 7676de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 76779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 7678de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7679de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7680de41b84cSMatthew G. Knepley cpoints[q*2] = cpoints[p]; 7681de41b84cSMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 7682de41b84cSMatthew G. Knepley ++q; 7683de41b84cSMatthew G. Knepley } 7684de41b84cSMatthew G. Knepley } 7685de41b84cSMatthew G. Knepley numCPoints = q; 7686de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7687de41b84cSMatthew G. Knepley PetscInt fdof; 7688de41b84cSMatthew G. Knepley 76899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 76904ca5e9f5SMatthew G. Knepley if (!dof) continue; 7691de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 76929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 7693de41b84cSMatthew G. Knepley coffsets[f+1] += fdof; 7694de41b84cSMatthew G. Knepley } 7695de41b84cSMatthew G. Knepley numCIndices += dof; 7696de41b84cSMatthew G. Knepley } 7697de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7698de41b84cSMatthew G. Knepley /* Row indices */ 76999566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7700412e9a14SMatthew G. Knepley { 7701012bc364SMatthew G. Knepley DMPlexTransform tr; 7702012bc364SMatthew G. Knepley DMPolytopeType *rct; 7703012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7704012bc364SMatthew G. Knepley 77059566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 77069566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 77079566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7708012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 77099566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7710412e9a14SMatthew G. Knepley } 77119566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 7712de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 7713de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 77149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 7715de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 77169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 7717de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 7718de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 77199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 77204ca5e9f5SMatthew G. Knepley if (!dof) continue; 77214ca5e9f5SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 77224ca5e9f5SMatthew G. Knepley if (s < q) continue; 7723de41b84cSMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 7724de41b84cSMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 7725de41b84cSMatthew G. Knepley ++q; 7726de41b84cSMatthew G. Knepley } 7727de41b84cSMatthew G. Knepley } 77289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 7729de41b84cSMatthew G. Knepley } 7730de41b84cSMatthew G. Knepley numFPoints = q; 7731de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7732de41b84cSMatthew G. Knepley PetscInt fdof; 7733de41b84cSMatthew G. Knepley 77349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 77354ca5e9f5SMatthew G. Knepley if (!dof) continue; 7736de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 77379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 7738de41b84cSMatthew G. Knepley foffsets[f+1] += fdof; 7739de41b84cSMatthew G. Knepley } 7740de41b84cSMatthew G. Knepley numFIndices += dof; 7741de41b84cSMatthew G. Knepley } 7742de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7743de41b84cSMatthew G. Knepley 77441dca8a05SBarry 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); 77451dca8a05SBarry 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); 77469566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77479566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7748de41b84cSMatthew G. Knepley if (numFields) { 77494acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 77504acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 77514acb8e1eSToby Isaac 77524acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7755de41b84cSMatthew G. Knepley } 77564acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 77579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77589566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 77594acb8e1eSToby Isaac } 77604acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 77619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77629566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 77634acb8e1eSToby Isaac } 77644acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77659566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77669566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7767de41b84cSMatthew G. Knepley } 7768de41b84cSMatthew G. Knepley } else { 77694acb8e1eSToby Isaac const PetscInt **permsF = NULL; 77704acb8e1eSToby Isaac const PetscInt **permsC = NULL; 77714acb8e1eSToby Isaac 77729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 77744acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 77754acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 77764acb8e1eSToby Isaac 77779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77789566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 7779de41b84cSMatthew G. Knepley } 77804acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 77814acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 77824acb8e1eSToby Isaac 77839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77849566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 7785de41b84cSMatthew G. Knepley } 77869566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77879566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 7788de41b84cSMatthew G. Knepley } 77899566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77904acb8e1eSToby Isaac /* TODO: flips */ 7791d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 7792de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7793de41b84cSMatthew G. Knepley if (ierr) { 7794de41b84cSMatthew G. Knepley PetscMPIInt rank; 7795de41b84cSMatthew G. Knepley 77969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 77979566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 77989566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 78009566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7801de41b84cSMatthew G. Knepley } 78029566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 78039566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78049566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 78059566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7806de41b84cSMatthew G. Knepley PetscFunctionReturn(0); 7807de41b84cSMatthew G. Knepley } 7808de41b84cSMatthew G. Knepley 78097c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 78107c927364SMatthew G. Knepley { 78117c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 78127c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 78137c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 781417c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7815412e9a14SMatthew G. Knepley DMPolytopeType ct; 78167c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 78177c927364SMatthew G. Knepley 78187c927364SMatthew G. Knepley PetscFunctionBegin; 78197c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 78207c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 78219566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 78227c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 78239566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 78247c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 78259566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 78267c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 78279566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 78287c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 78299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 783063a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 78319566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 78329566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 78337c927364SMatthew G. Knepley /* Column indices */ 78349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78357c927364SMatthew G. Knepley maxFPoints = numCPoints; 78367c927364SMatthew G. Knepley /* Compress out points not in the section */ 78377c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 78389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 78397c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 78407c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 78417c927364SMatthew G. Knepley cpoints[q*2] = cpoints[p]; 78427c927364SMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 78437c927364SMatthew G. Knepley ++q; 78447c927364SMatthew G. Knepley } 78457c927364SMatthew G. Knepley } 78467c927364SMatthew G. Knepley numCPoints = q; 78477c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 78487c927364SMatthew G. Knepley PetscInt fdof; 78497c927364SMatthew G. Knepley 78509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 78517c927364SMatthew G. Knepley if (!dof) continue; 78527c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 78547c927364SMatthew G. Knepley coffsets[f+1] += fdof; 78557c927364SMatthew G. Knepley } 78567c927364SMatthew G. Knepley numCIndices += dof; 78577c927364SMatthew G. Knepley } 78587c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 78597c927364SMatthew G. Knepley /* Row indices */ 78609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7861412e9a14SMatthew G. Knepley { 7862012bc364SMatthew G. Knepley DMPlexTransform tr; 7863012bc364SMatthew G. Knepley DMPolytopeType *rct; 7864012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7865012bc364SMatthew G. Knepley 78669566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 78679566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 78689566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7869012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 78709566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7871412e9a14SMatthew G. Knepley } 78729566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 78737c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 78747c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 78759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 78767c927364SMatthew G. Knepley /* Compress out points not in the section */ 78779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 78787c927364SMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 78797c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 78809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 78817c927364SMatthew G. Knepley if (!dof) continue; 78827c927364SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 78837c927364SMatthew G. Knepley if (s < q) continue; 78847c927364SMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 78857c927364SMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 78867c927364SMatthew G. Knepley ++q; 78877c927364SMatthew G. Knepley } 78887c927364SMatthew G. Knepley } 78899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 78907c927364SMatthew G. Knepley } 78917c927364SMatthew G. Knepley numFPoints = q; 78927c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 78937c927364SMatthew G. Knepley PetscInt fdof; 78947c927364SMatthew G. Knepley 78959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 78967c927364SMatthew G. Knepley if (!dof) continue; 78977c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 78997c927364SMatthew G. Knepley foffsets[f+1] += fdof; 79007c927364SMatthew G. Knepley } 79017c927364SMatthew G. Knepley numFIndices += dof; 79027c927364SMatthew G. Knepley } 79037c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 79047c927364SMatthew G. Knepley 79051dca8a05SBarry 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); 79061dca8a05SBarry 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); 79077c927364SMatthew G. Knepley if (numFields) { 79084acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 79094acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 79104acb8e1eSToby Isaac 79114acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 79129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 79139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 79147c927364SMatthew G. Knepley } 79154acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 79169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 79179566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 79184acb8e1eSToby Isaac } 79194acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 79209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79219566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 79224acb8e1eSToby Isaac } 79234acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 79249566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 79259566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 79267c927364SMatthew G. Knepley } 79277c927364SMatthew G. Knepley } else { 79284acb8e1eSToby Isaac const PetscInt **permsF = NULL; 79294acb8e1eSToby Isaac const PetscInt **permsC = NULL; 79304acb8e1eSToby Isaac 79319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79334acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 79344acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 79354acb8e1eSToby Isaac 79369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 79379566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 79387c927364SMatthew G. Knepley } 79394acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 79404acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 79414acb8e1eSToby Isaac 79429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79439566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 79447c927364SMatthew G. Knepley } 79459566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79469566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79477c927364SMatthew G. Knepley } 79489566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 79499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 79507c927364SMatthew G. Knepley PetscFunctionReturn(0); 79517c927364SMatthew G. Knepley } 79527c927364SMatthew G. Knepley 79537cd05799SMatthew G. Knepley /*@C 79547cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 79557cd05799SMatthew G. Knepley 79567cd05799SMatthew G. Knepley Input Parameter: 79577cd05799SMatthew G. Knepley . dm - The DMPlex object 79587cd05799SMatthew G. Knepley 79597cd05799SMatthew G. Knepley Output Parameter: 79607cd05799SMatthew G. Knepley . cellHeight - The height of a cell 79617cd05799SMatthew G. Knepley 79627cd05799SMatthew G. Knepley Level: developer 79637cd05799SMatthew G. Knepley 7964db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()` 79657cd05799SMatthew G. Knepley @*/ 7966552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7967552f7358SJed Brown { 7968552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7969552f7358SJed Brown 7970552f7358SJed Brown PetscFunctionBegin; 7971552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7972dadcf809SJacob Faibussowitsch PetscValidIntPointer(cellHeight, 2); 7973552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 7974552f7358SJed Brown PetscFunctionReturn(0); 7975552f7358SJed Brown } 7976552f7358SJed Brown 79777cd05799SMatthew G. Knepley /*@C 79787cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 79797cd05799SMatthew G. Knepley 79807cd05799SMatthew G. Knepley Input Parameters: 79817cd05799SMatthew G. Knepley + dm - The DMPlex object 79827cd05799SMatthew G. Knepley - cellHeight - The height of a cell 79837cd05799SMatthew G. Knepley 79847cd05799SMatthew G. Knepley Level: developer 79857cd05799SMatthew G. Knepley 7986db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()` 79877cd05799SMatthew G. Knepley @*/ 7988552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7989552f7358SJed Brown { 7990552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7991552f7358SJed Brown 7992552f7358SJed Brown PetscFunctionBegin; 7993552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7994552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 7995552f7358SJed Brown PetscFunctionReturn(0); 7996552f7358SJed Brown } 7997552f7358SJed Brown 7998e6139122SMatthew G. Knepley /*@ 7999e6139122SMatthew G. Knepley DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 8000e6139122SMatthew G. Knepley 8001e6139122SMatthew G. Knepley Input Parameter: 8002e6139122SMatthew G. Knepley . dm - The DMPlex object 8003e6139122SMatthew G. Knepley 8004e6139122SMatthew G. Knepley Output Parameters: 80052a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL 80062a9f31c0SMatthew G. Knepley - gcEnd - The upper bound on ghost cells, or NULL 8007e6139122SMatthew G. Knepley 80082a9f31c0SMatthew G. Knepley Level: advanced 8009e6139122SMatthew G. Knepley 8010db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 8011e6139122SMatthew G. Knepley @*/ 8012e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 8013e6139122SMatthew G. Knepley { 8014412e9a14SMatthew G. Knepley DMLabel ctLabel; 8015e6139122SMatthew G. Knepley 8016e6139122SMatthew G. Knepley PetscFunctionBegin; 8017e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 80199566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd)); 8020e6139122SMatthew G. Knepley PetscFunctionReturn(0); 8021e6139122SMatthew G. Knepley } 8022e6139122SMatthew G. Knepley 80239886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8024552f7358SJed Brown { 8025552f7358SJed Brown PetscSection section, globalSection; 8026552f7358SJed Brown PetscInt *numbers, p; 8027552f7358SJed Brown 8028552f7358SJed Brown PetscFunctionBegin; 80296c1ef331SVaclav Hapla if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf)); 80309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 80319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8032552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, 1)); 8034552f7358SJed Brown } 80359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 80369566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 80379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8038552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart])); 8040ef48cebcSMatthew G. Knepley if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8041ef48cebcSMatthew G. Knepley else numbers[p-pStart] += shift; 8042552f7358SJed Brown } 80439566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8044ef48cebcSMatthew G. Knepley if (globalSize) { 8045ef48cebcSMatthew G. Knepley PetscLayout layout; 80469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout)); 80479566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 80489566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8049ef48cebcSMatthew G. Knepley } 80509566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 80519566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 8052552f7358SJed Brown PetscFunctionReturn(0); 8053552f7358SJed Brown } 8054552f7358SJed Brown 805581ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8056552f7358SJed Brown { 8057412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8058552f7358SJed Brown 8059552f7358SJed Brown PetscFunctionBegin; 80609566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 80619566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 80629566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 80639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 806481ed3555SMatthew G. Knepley PetscFunctionReturn(0); 8065552f7358SJed Brown } 806681ed3555SMatthew G. Knepley 80678dab3259SMatthew G. Knepley /*@ 80687cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 80697cd05799SMatthew G. Knepley 80707cd05799SMatthew G. Knepley Input Parameter: 80717cd05799SMatthew G. Knepley . dm - The DMPlex object 80727cd05799SMatthew G. Knepley 80737cd05799SMatthew G. Knepley Output Parameter: 80747cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 80757cd05799SMatthew G. Knepley 80767cd05799SMatthew G. Knepley Level: developer 80777cd05799SMatthew G. Knepley 8078db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()` 80797cd05799SMatthew G. Knepley @*/ 808081ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 808181ed3555SMatthew G. Knepley { 808281ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 808381ed3555SMatthew G. Knepley 808481ed3555SMatthew G. Knepley PetscFunctionBegin; 808581ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80869566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8087552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 8088552f7358SJed Brown PetscFunctionReturn(0); 8089552f7358SJed Brown } 8090552f7358SJed Brown 809181ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 809281ed3555SMatthew G. Knepley { 8093412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 809481ed3555SMatthew G. Knepley 809581ed3555SMatthew G. Knepley PetscFunctionBegin; 809681ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80979566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 80989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 809981ed3555SMatthew G. Knepley PetscFunctionReturn(0); 810081ed3555SMatthew G. Knepley } 810181ed3555SMatthew G. Knepley 81028dab3259SMatthew G. Knepley /*@ 81036aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 81047cd05799SMatthew G. Knepley 81057cd05799SMatthew G. Knepley Input Parameter: 81067cd05799SMatthew G. Knepley . dm - The DMPlex object 81077cd05799SMatthew G. Knepley 81087cd05799SMatthew G. Knepley Output Parameter: 81097cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 81107cd05799SMatthew G. Knepley 81117cd05799SMatthew G. Knepley Level: developer 81127cd05799SMatthew G. Knepley 8113db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 81147cd05799SMatthew G. Knepley @*/ 8115552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8116552f7358SJed Brown { 8117552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 8118552f7358SJed Brown 8119552f7358SJed Brown PetscFunctionBegin; 8120552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81219566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8122552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 8123552f7358SJed Brown PetscFunctionReturn(0); 8124552f7358SJed Brown } 8125552f7358SJed Brown 81268dab3259SMatthew G. Knepley /*@ 81277cd05799SMatthew G. Knepley DMPlexCreatePointNumbering - Create a global numbering for all points on this process 81287cd05799SMatthew G. Knepley 81297cd05799SMatthew G. Knepley Input Parameter: 81307cd05799SMatthew G. Knepley . dm - The DMPlex object 81317cd05799SMatthew G. Knepley 81327cd05799SMatthew G. Knepley Output Parameter: 81337cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 81347cd05799SMatthew G. Knepley 81357cd05799SMatthew G. Knepley Level: developer 81367cd05799SMatthew G. Knepley 8137db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 81387cd05799SMatthew G. Knepley @*/ 8139ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8140ef48cebcSMatthew G. Knepley { 8141ef48cebcSMatthew G. Knepley IS nums[4]; 8142862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8143ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 8144ef48cebcSMatthew G. Knepley 8145ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8146ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 81488abc87a0SMichael Lange /* For unstratified meshes use dim instead of depth */ 81499566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 8150862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8151862913ffSStefano Zampini PetscInt end; 8152862913ffSStefano Zampini 8153862913ffSStefano Zampini depths[d] = depth-d; 81549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 8155862913ffSStefano Zampini if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8156862913ffSStefano Zampini } 81579566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(depth+1, starts, depths)); 81581c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm))); 8159862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 81601dca8a05SBarry Smith 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]); 8161862913ffSStefano Zampini } 8162ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8163ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8164ef48cebcSMatthew G. Knepley 81659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 81669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8167ef48cebcSMatthew G. Knepley shift += gsize; 8168ef48cebcSMatthew G. Knepley } 81699566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers)); 81709566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 8171ef48cebcSMatthew G. Knepley PetscFunctionReturn(0); 8172ef48cebcSMatthew G. Knepley } 8173ef48cebcSMatthew G. Knepley 817408a22f4bSMatthew G. Knepley /*@ 817508a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 817608a22f4bSMatthew G. Knepley 817708a22f4bSMatthew G. Knepley Input Parameter: 817808a22f4bSMatthew G. Knepley . dm - The DMPlex object 817908a22f4bSMatthew G. Knepley 818008a22f4bSMatthew G. Knepley Output Parameter: 818108a22f4bSMatthew G. Knepley . ranks - The rank field 818208a22f4bSMatthew G. Knepley 818308a22f4bSMatthew G. Knepley Options Database Keys: 818408a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 818508a22f4bSMatthew G. Knepley 818608a22f4bSMatthew G. Knepley Level: intermediate 818708a22f4bSMatthew G. Knepley 8188db781477SPatrick Sanan .seealso: `DMView()` 818908a22f4bSMatthew G. Knepley @*/ 819008a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 819108a22f4bSMatthew G. Knepley { 819208a22f4bSMatthew G. Knepley DM rdm; 819308a22f4bSMatthew G. Knepley PetscFE fe; 819408a22f4bSMatthew G. Knepley PetscScalar *r; 819508a22f4bSMatthew G. Knepley PetscMPIInt rank; 8196a55f9a55SMatthew G. Knepley DMPolytopeType ct; 819708a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8198a55f9a55SMatthew G. Knepley PetscBool simplex; 819908a22f4bSMatthew G. Knepley 820008a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8201f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8202f95ace6aSMatthew G. Knepley PetscValidPointer(ranks, 2); 82039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 82049566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 82059566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 82069566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8208a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 82099566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 82109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) fe, "rank")); 82119566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 82129566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 82139566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 82149566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 82159566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *ranks, "partition")); 82169566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 821708a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 821808a22f4bSMatthew G. Knepley PetscScalar *lr; 821908a22f4bSMatthew G. Knepley 82209566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 822171f09efeSPierre Jolivet if (lr) *lr = rank; 822208a22f4bSMatthew G. Knepley } 82239566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 82249566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 822508a22f4bSMatthew G. Knepley PetscFunctionReturn(0); 822608a22f4bSMatthew G. Knepley } 822708a22f4bSMatthew G. Knepley 8228ca8062c8SMatthew G. Knepley /*@ 822918e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 823018e14f0cSMatthew G. Knepley 823118e14f0cSMatthew G. Knepley Input Parameters: 823218e14f0cSMatthew G. Knepley + dm - The DMPlex 823318e14f0cSMatthew G. Knepley - label - The DMLabel 823418e14f0cSMatthew G. Knepley 823518e14f0cSMatthew G. Knepley Output Parameter: 823618e14f0cSMatthew G. Knepley . val - The label value field 823718e14f0cSMatthew G. Knepley 823818e14f0cSMatthew G. Knepley Options Database Keys: 823918e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 824018e14f0cSMatthew G. Knepley 824118e14f0cSMatthew G. Knepley Level: intermediate 824218e14f0cSMatthew G. Knepley 8243db781477SPatrick Sanan .seealso: `DMView()` 824418e14f0cSMatthew G. Knepley @*/ 824518e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 824618e14f0cSMatthew G. Knepley { 824718e14f0cSMatthew G. Knepley DM rdm; 824818e14f0cSMatthew G. Knepley PetscFE fe; 824918e14f0cSMatthew G. Knepley PetscScalar *v; 825018e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 825118e14f0cSMatthew G. Knepley 825218e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 825318e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 825418e14f0cSMatthew G. Knepley PetscValidPointer(label, 2); 825518e14f0cSMatthew G. Knepley PetscValidPointer(val, 3); 82569566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 82579566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 82589566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 82599566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) fe, "label_value")); 82609566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 82619566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 82629566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 82639566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82649566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 82659566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *val, "label_value")); 82669566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 826718e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 826818e14f0cSMatthew G. Knepley PetscScalar *lv; 826918e14f0cSMatthew G. Knepley PetscInt cval; 827018e14f0cSMatthew G. Knepley 82719566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 82729566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 827318e14f0cSMatthew G. Knepley *lv = cval; 827418e14f0cSMatthew G. Knepley } 82759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 82769566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 827718e14f0cSMatthew G. Knepley PetscFunctionReturn(0); 827818e14f0cSMatthew G. Knepley } 827918e14f0cSMatthew G. Knepley 828018e14f0cSMatthew G. Knepley /*@ 8281ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8282ca8062c8SMatthew G. Knepley 828369916449SMatthew G. Knepley Input Parameter: 828469916449SMatthew G. Knepley . dm - The DMPlex object 8285ca8062c8SMatthew G. Knepley 828695eb5ee5SVaclav Hapla Notes: 828795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 828895eb5ee5SVaclav Hapla 828995eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8290ca8062c8SMatthew G. Knepley 8291ca8062c8SMatthew G. Knepley Level: developer 8292ca8062c8SMatthew G. Knepley 8293db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8294ca8062c8SMatthew G. Knepley @*/ 8295ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm) 8296ca8062c8SMatthew G. Knepley { 8297ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8298ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8299ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 830057beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 830157beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8302ca8062c8SMatthew G. Knepley 8303ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8304ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 83059566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 83069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 83079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8308ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 83099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8310ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 83119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 83129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8313ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 831442e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 831542e66dfaSMatthew G. Knepley PetscInt d; 831642e66dfaSMatthew G. Knepley for (d = c-1; d >= 0; --d) { 831742e66dfaSMatthew G. Knepley if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 831842e66dfaSMatthew G. Knepley } 83199566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 83209566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8321ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8322ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8323ca8062c8SMatthew G. Knepley } 832442e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s+1] != p))) { 832563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 8326ca8062c8SMatthew G. Knepley for (s = 0; s < coneSize; ++s) { 832763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 8328ca8062c8SMatthew G. Knepley } 83299566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 833063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 8331ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 833263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 8333ca8062c8SMatthew G. Knepley } 83349566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 833563a3b9bcSJacob 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]); 8336f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8337ca8062c8SMatthew G. Knepley } 833842e66dfaSMatthew G. Knepley } 83399566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 834057beb4faSStefano Zampini if (p != pp) { storagecheck = PETSC_FALSE; continue; } 83419566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 83429566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8343ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 83449566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 83459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8346ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 83479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 834857beb4faSStefano Zampini if (cone[c] != pp) { c = 0; break; } 8349ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8350ca8062c8SMatthew G. Knepley } 8351ca8062c8SMatthew G. Knepley if (c >= coneSize) { 835263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 8353ca8062c8SMatthew G. Knepley for (c = 0; c < supportSize; ++c) { 835463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 8355ca8062c8SMatthew G. Knepley } 83569566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 835763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 8358ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 835963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 8360ca8062c8SMatthew G. Knepley } 83619566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 836263a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8363ca8062c8SMatthew G. Knepley } 8364ca8062c8SMatthew G. Knepley } 8365ca8062c8SMatthew G. Knepley } 836657beb4faSStefano Zampini if (storagecheck) { 83679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 83689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 836963a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 837057beb4faSStefano Zampini } 8371ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8372ca8062c8SMatthew G. Knepley } 8373ca8062c8SMatthew G. Knepley 8374412e9a14SMatthew G. Knepley /* 8375412e9a14SMatthew 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. 8376412e9a14SMatthew G. Knepley */ 8377412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8378412e9a14SMatthew G. Knepley { 8379412e9a14SMatthew G. Knepley DMPolytopeType cct; 8380412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8381412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8382412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8383412e9a14SMatthew G. Knepley 8384412e9a14SMatthew G. Knepley PetscFunctionBegin; 8385412e9a14SMatthew G. Knepley *unsplit = 0; 8386412e9a14SMatthew G. Knepley switch (ct) { 8387b5a892a1SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 8388b5a892a1SMatthew G. Knepley ptpoints[npt++] = c; 8389b5a892a1SMatthew G. Knepley break; 8390412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 83919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 83929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8393412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 8395412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8396412e9a14SMatthew G. Knepley } 8397412e9a14SMatthew G. Knepley break; 8398412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8399412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 84009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 84019566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8402412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 84039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 84049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8405412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 84069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8407412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8408412e9a14SMatthew G. Knepley PetscInt p; 8409412e9a14SMatthew G. Knepley for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8410412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8411412e9a14SMatthew G. Knepley } 8412412e9a14SMatthew G. Knepley } 8413412e9a14SMatthew G. Knepley } 8414412e9a14SMatthew G. Knepley break; 8415412e9a14SMatthew G. Knepley default: break; 8416412e9a14SMatthew G. Knepley } 8417412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 84189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8419412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8420412e9a14SMatthew G. Knepley } 8421412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 8422412e9a14SMatthew G. Knepley } 8423412e9a14SMatthew G. Knepley 8424ca8062c8SMatthew G. Knepley /*@ 8425ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8426ca8062c8SMatthew G. Knepley 8427ca8062c8SMatthew G. Knepley Input Parameters: 8428ca8062c8SMatthew G. Knepley + dm - The DMPlex object 842958723a97SMatthew G. Knepley - cellHeight - Normally 0 8430ca8062c8SMatthew G. Knepley 843195eb5ee5SVaclav Hapla Notes: 843295eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 843325c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 8434ca8062c8SMatthew G. Knepley 843595eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 843695eb5ee5SVaclav Hapla 8437ca8062c8SMatthew G. Knepley Level: developer 8438ca8062c8SMatthew G. Knepley 8439db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8440ca8062c8SMatthew G. Knepley @*/ 844125c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8442ca8062c8SMatthew G. Knepley { 8443412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 8444412e9a14SMatthew G. Knepley DMPolytopeType ct; 8445412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 8446ca8062c8SMatthew G. Knepley 8447ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8448ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84499566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 84509566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 84519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8452412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8453412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 8454412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 845558723a97SMatthew G. Knepley 84569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 845763a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt) ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 8458412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 8459412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 84609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 846163a3b9bcSJacob 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)); 8462412e9a14SMatthew G. Knepley } 84639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 846458723a97SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 846558723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 8466412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 846758723a97SMatthew G. Knepley } 84689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8469412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 8470412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8471412e9a14SMatthew G. Knepley PetscInt unsplit; 847242363296SMatthew G. Knepley 84739566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8474412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 847542363296SMatthew G. Knepley } 847663a3b9bcSJacob 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)); 847742363296SMatthew G. Knepley } 8478ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8479ca8062c8SMatthew G. Knepley } 84809bf0dad6SMatthew G. Knepley 84819bf0dad6SMatthew G. Knepley /*@ 84829bf0dad6SMatthew 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 84839bf0dad6SMatthew G. Knepley 84848f6815adSVaclav Hapla Collective 8485899ea2b8SJacob Faibussowitsch 84869bf0dad6SMatthew G. Knepley Input Parameters: 84879bf0dad6SMatthew G. Knepley + dm - The DMPlex object 84889bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 84899bf0dad6SMatthew G. Knepley 849045da879fSVaclav Hapla Notes: 849145da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 849245da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 849345da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 849445da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 84959bf0dad6SMatthew G. Knepley 849695eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 849795eb5ee5SVaclav Hapla 84989bf0dad6SMatthew G. Knepley Level: developer 84999bf0dad6SMatthew G. Knepley 8500db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 85019bf0dad6SMatthew G. Knepley @*/ 850225c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 85039bf0dad6SMatthew G. Knepley { 8504ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8505899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 85069bf0dad6SMatthew G. Knepley 85079bf0dad6SMatthew G. Knepley PetscFunctionBegin; 85089bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85098f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 851045da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 85118f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 85128f6815adSVaclav Hapla PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"); 85138f6815adSVaclav Hapla PetscFunctionReturn(0); 8514899ea2b8SJacob Faibussowitsch } 8515899ea2b8SJacob Faibussowitsch 85169566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 85179566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 85189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8519ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 85209566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 85213554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8522412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 8523412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 8524ba2698f1SMatthew G. Knepley DMPolytopeType ct; 8525412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 8526412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 85279bf0dad6SMatthew G. Knepley 85289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 85299566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8530412e9a14SMatthew G. Knepley if (unsplit) continue; 85319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 85329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 85339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 85349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85359bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 85369bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 85379bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 85389bf0dad6SMatthew G. Knepley } 85399566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 854063a3b9bcSJacob 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); 85419bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 8542d4961f80SStefano Zampini DMPolytopeType fct; 85439bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 85449bf0dad6SMatthew G. Knepley 85459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 85469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 85479bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize*2; cl += 2) { 85489bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 85499bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 85509bf0dad6SMatthew G. Knepley } 855163a3b9bcSJacob 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]); 85529bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 8553b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff+v]) { 8554b5a892a1SMatthew G. Knepley PetscInt v1; 8555b5a892a1SMatthew G. Knepley 85569566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 855763a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 85589566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 855963a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff+v1])); 85609566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 856163a3b9bcSJacob 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]); 8562b5a892a1SMatthew G. Knepley } 85639bf0dad6SMatthew G. Knepley } 85649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 8565412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 85669bf0dad6SMatthew G. Knepley } 85679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 85689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85699bf0dad6SMatthew G. Knepley } 85703554e41dSMatthew G. Knepley } 8571552f7358SJed Brown PetscFunctionReturn(0); 8572552f7358SJed Brown } 85733913d7c8SMatthew G. Knepley 8574bb6a34a8SMatthew G. Knepley /*@ 8575bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 8576bb6a34a8SMatthew G. Knepley 8577bb6a34a8SMatthew G. Knepley Input Parameter: 8578bb6a34a8SMatthew G. Knepley . dm - The DMPlex object 8579bb6a34a8SMatthew G. Knepley 858095eb5ee5SVaclav Hapla Notes: 858195eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 858295eb5ee5SVaclav Hapla 858395eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8584bb6a34a8SMatthew G. Knepley 8585bb6a34a8SMatthew G. Knepley Level: developer 8586bb6a34a8SMatthew G. Knepley 8587db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8588bb6a34a8SMatthew G. Knepley @*/ 8589bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm) 8590bb6a34a8SMatthew G. Knepley { 8591a2a9e04cSMatthew G. Knepley Vec coordinates; 8592bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 8593bb6a34a8SMatthew G. Knepley PetscReal vol; 859451a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 8595bb6a34a8SMatthew G. Knepley 8596bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 85979566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 85989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 859951a74b61SMatthew G. Knepley if (dim != dE) PetscFunctionReturn(0); 86009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8601bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 86029566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8603a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 86049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8605412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8606412e9a14SMatthew G. Knepley DMPolytopeType ct; 8607412e9a14SMatthew G. Knepley PetscInt unsplit; 8608412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 8609412e9a14SMatthew G. Knepley 86109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 8611412e9a14SMatthew G. Knepley switch (ct) { 8612412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 8613412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8614412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8615412e9a14SMatthew G. Knepley ignoreZeroVol = PETSC_TRUE; break; 8616412e9a14SMatthew G. Knepley default: break; 8617412e9a14SMatthew G. Knepley } 8618412e9a14SMatthew G. Knepley switch (ct) { 8619412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 8620412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8621412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8622a2a9e04cSMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 8623412e9a14SMatthew G. Knepley continue; 8624412e9a14SMatthew G. Knepley default: break; 8625412e9a14SMatthew G. Knepley } 86269566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8627412e9a14SMatthew G. Knepley if (unsplit) continue; 86289566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 86291dca8a05SBarry 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); 863063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ*refVol))); 86316858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 86326858538eSMatthew G. Knepley if (depth > 1) { 86339566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 86341dca8a05SBarry 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); 863563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double) vol)); 8636bb6a34a8SMatthew G. Knepley } 8637bb6a34a8SMatthew G. Knepley } 8638bb6a34a8SMatthew G. Knepley PetscFunctionReturn(0); 8639bb6a34a8SMatthew G. Knepley } 8640bb6a34a8SMatthew G. Knepley 864103da9461SVaclav Hapla /*@ 86427726db96SVaclav Hapla DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex. 86437726db96SVaclav Hapla 86447726db96SVaclav Hapla Collective 864503da9461SVaclav Hapla 864603da9461SVaclav Hapla Input Parameters: 86477726db96SVaclav Hapla + dm - The DMPlex object 86487726db96SVaclav Hapla - pointSF - The Point SF, or NULL for Point SF attached to DM 864903da9461SVaclav Hapla 8650e83a0d2dSVaclav Hapla Notes: 8651e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 865203da9461SVaclav Hapla 865395eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 865495eb5ee5SVaclav Hapla 865503da9461SVaclav Hapla Level: developer 865603da9461SVaclav Hapla 8657db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()` 865803da9461SVaclav Hapla @*/ 86597726db96SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF) 866003da9461SVaclav Hapla { 86617726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 86627726db96SVaclav Hapla const PetscInt *locals; 86637726db96SVaclav Hapla const PetscSFNode *remotes; 8664f0cfc026SVaclav Hapla PetscBool distributed; 86657726db96SVaclav Hapla MPI_Comm comm; 86667726db96SVaclav Hapla PetscMPIInt rank; 866703da9461SVaclav Hapla 866803da9461SVaclav Hapla PetscFunctionBegin; 866903da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86707726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 86717726db96SVaclav Hapla else pointSF = dm->sf; 86727726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 86737726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 86747726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 86757726db96SVaclav Hapla { 86767726db96SVaclav Hapla PetscMPIInt mpiFlag; 86777726db96SVaclav Hapla 86787726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF),&mpiFlag)); 86797726db96SVaclav 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); 86807726db96SVaclav Hapla } 86817726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 86829566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 86837726db96SVaclav Hapla if (!distributed) { 86847726db96SVaclav 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); 86858918e3e2SVaclav Hapla PetscFunctionReturn(0); 86868918e3e2SVaclav Hapla } 86877726db96SVaclav 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); 86887726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 868903da9461SVaclav Hapla 86907726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 86917726db96SVaclav Hapla { 86927726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 86937726db96SVaclav Hapla 86947726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86957726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 86967726db96SVaclav Hapla PetscCheck(pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd-pStart, nroots); 86977726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 86987726db96SVaclav Hapla } 86997726db96SVaclav Hapla 87007726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 87017726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 87027726db96SVaclav 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); 87037726db96SVaclav Hapla } 87047726db96SVaclav Hapla 87057726db96SVaclav Hapla /* Check there are no cells in interface */ 87067726db96SVaclav Hapla if (!overlap) { 87077726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 87087726db96SVaclav Hapla 87099566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 8711f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 87127726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 8713f5869d18SMatthew G. Knepley 87147726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 87157726db96SVaclav Hapla } 871603da9461SVaclav Hapla } 8717ece87651SVaclav Hapla 87187726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 87197726db96SVaclav Hapla { 87207726db96SVaclav Hapla const PetscInt *rootdegree; 87217726db96SVaclav Hapla 87227726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 87237726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 8724f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 87257726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 8726f5869d18SMatthew G. Knepley const PetscInt *cone; 8727f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 8728f5869d18SMatthew G. Knepley 87299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 87309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 8731f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8732f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 87337726db96SVaclav Hapla if (locals) { 87349566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 87357726db96SVaclav Hapla } else { 87367726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 87377726db96SVaclav Hapla } 873863a3b9bcSJacob 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]); 8739f5869d18SMatthew G. Knepley } 8740f5869d18SMatthew G. Knepley } 8741ece87651SVaclav Hapla } 87427726db96SVaclav Hapla } 874303da9461SVaclav Hapla PetscFunctionReturn(0); 874403da9461SVaclav Hapla } 874503da9461SVaclav Hapla 87467f9d8d6cSVaclav Hapla /*@ 87477f9d8d6cSVaclav Hapla DMPlexCheck - Perform various checks of Plex sanity 87487f9d8d6cSVaclav Hapla 87497f9d8d6cSVaclav Hapla Input Parameter: 87507f9d8d6cSVaclav Hapla . dm - The DMPlex object 87517f9d8d6cSVaclav Hapla 87527f9d8d6cSVaclav Hapla Notes: 87537f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 87547f9d8d6cSVaclav Hapla 87557f9d8d6cSVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 87567f9d8d6cSVaclav Hapla 87577f9d8d6cSVaclav Hapla Currently does not include DMPlexCheckCellShape(). 87587f9d8d6cSVaclav Hapla 87597f9d8d6cSVaclav Hapla Level: developer 87607f9d8d6cSVaclav Hapla 87617f9d8d6cSVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 87627f9d8d6cSVaclav Hapla @*/ 87637f9d8d6cSVaclav Hapla PetscErrorCode DMPlexCheck(DM dm) 8764b5a892a1SMatthew G. Knepley { 87657f9d8d6cSVaclav Hapla PetscInt cellHeight; 87667f9d8d6cSVaclav Hapla 8767b5a892a1SMatthew G. Knepley PetscFunctionBegin; 87687f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87699566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 87709566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 87719566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 87729566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 87737726db96SVaclav Hapla PetscCall(DMPlexCheckPointSF(dm, NULL)); 87749566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 8775b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 8776b5a892a1SMatthew G. Knepley } 8777b5a892a1SMatthew G. Knepley 8778068a5610SStefano Zampini typedef struct cell_stats 8779068a5610SStefano Zampini { 8780068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 8781068a5610SStefano Zampini PetscInt count; 8782068a5610SStefano Zampini } cell_stats_t; 8783068a5610SStefano Zampini 878425befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8785068a5610SStefano Zampini { 8786068a5610SStefano Zampini PetscInt i, N = *len; 8787068a5610SStefano Zampini 8788068a5610SStefano Zampini for (i = 0; i < N; i++) { 8789068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *) a; 8790068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *) b; 8791068a5610SStefano Zampini 8792068a5610SStefano Zampini B->min = PetscMin(A->min,B->min); 8793068a5610SStefano Zampini B->max = PetscMax(A->max,B->max); 8794068a5610SStefano Zampini B->sum += A->sum; 8795068a5610SStefano Zampini B->squaresum += A->squaresum; 8796068a5610SStefano Zampini B->count += A->count; 8797068a5610SStefano Zampini } 8798068a5610SStefano Zampini } 8799068a5610SStefano Zampini 8800068a5610SStefano Zampini /*@ 880143fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8802068a5610SStefano Zampini 88038261a58bSMatthew G. Knepley Collective on dm 88048261a58bSMatthew G. Knepley 8805068a5610SStefano Zampini Input Parameters: 8806068a5610SStefano Zampini + dm - The DMPlex object 880743fa8764SMatthew G. Knepley . output - If true, statistics will be displayed on stdout 880843fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8809068a5610SStefano Zampini 881095eb5ee5SVaclav Hapla Notes: 881195eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 881295eb5ee5SVaclav Hapla 881395eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8814068a5610SStefano Zampini 8815068a5610SStefano Zampini Level: developer 8816068a5610SStefano Zampini 8817db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 8818068a5610SStefano Zampini @*/ 881943fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8820068a5610SStefano Zampini { 8821068a5610SStefano Zampini DM dmCoarse; 882243fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 882343fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 882443fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 882543fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8826412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 882743fa8764SMatthew G. Knepley PetscMPIInt rank,size; 8828068a5610SStefano Zampini 8829068a5610SStefano Zampini PetscFunctionBegin; 8830068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8831068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 8832068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 8833068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 8834068a5610SStefano Zampini stats.count = 0; 8835068a5610SStefano Zampini 88369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 88379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 88389566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm,&cdim)); 88399566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 88409566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd)); 88419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd)); 8842412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 8843068a5610SStefano Zampini PetscInt i; 8844068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8845068a5610SStefano Zampini 88469566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ)); 884763a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 884843fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 8849068a5610SStefano Zampini frobJ += J[i] * J[i]; 8850068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 8851068a5610SStefano Zampini } 8852068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 8853068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 8854068a5610SStefano Zampini 8855068a5610SStefano Zampini stats.min = PetscMin(stats.min,cond); 8856068a5610SStefano Zampini stats.max = PetscMax(stats.max,cond); 8857068a5610SStefano Zampini stats.sum += cond; 8858068a5610SStefano Zampini stats.squaresum += cond2; 8859068a5610SStefano Zampini stats.count++; 88608261a58bSMatthew G. Knepley if (output && cond > limit) { 886143fa8764SMatthew G. Knepley PetscSection coordSection; 886243fa8764SMatthew G. Knepley Vec coordsLocal; 886343fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 886443fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 886543fa8764SMatthew G. Knepley 88669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 88679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 88689566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 886963a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double) cond)); 887043fa8764SMatthew G. Knepley for (i = 0; i < Nv/cdim; ++i) { 887163a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 887243fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 88739566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 88749566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]))); 887543fa8764SMatthew G. Knepley } 88769566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 887743fa8764SMatthew G. Knepley } 88789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 887943fa8764SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) { 888043fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 888143fa8764SMatthew G. Knepley 888243fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 888343fa8764SMatthew G. Knepley PetscReal len; 888443fa8764SMatthew G. Knepley 88859566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 888663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double) len)); 888743fa8764SMatthew G. Knepley } 888843fa8764SMatthew G. Knepley } 88899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 88909566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 889143fa8764SMatthew G. Knepley } 8892068a5610SStefano Zampini } 88939566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 8894068a5610SStefano Zampini 8895068a5610SStefano Zampini if (size > 1) { 8896068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4,1}; 8897068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8898068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8899068a5610SStefano Zampini MPI_Op statReduce; 8900068a5610SStefano Zampini 89019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType)); 89029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 89039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 89049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm)); 89059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 89069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 8907068a5610SStefano Zampini } else { 89089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats,&stats,1)); 8909068a5610SStefano Zampini } 8910dd400576SPatrick Sanan if (rank == 0) { 8911068a5610SStefano Zampini count = globalStats.count; 8912068a5610SStefano Zampini min = globalStats.min; 8913068a5610SStefano Zampini max = globalStats.max; 8914068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 8915068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8916068a5610SStefano Zampini } 8917068a5610SStefano Zampini 8918068a5610SStefano Zampini if (output) { 891963a3b9bcSJacob Faibussowitsch 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)); 8920068a5610SStefano Zampini } 89219566063dSJacob Faibussowitsch PetscCall(PetscFree2(J,invJ)); 8922068a5610SStefano Zampini 89239566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm,&dmCoarse)); 8924068a5610SStefano Zampini if (dmCoarse) { 8925068a5610SStefano Zampini PetscBool isplex; 8926068a5610SStefano Zampini 89279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex)); 89281baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse,output,condLimit)); 8929068a5610SStefano Zampini } 8930068a5610SStefano Zampini PetscFunctionReturn(0); 8931068a5610SStefano Zampini } 8932068a5610SStefano Zampini 8933f108dbd7SJacob Faibussowitsch /*@ 8934f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8935f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 8936f108dbd7SJacob Faibussowitsch 89376ed19f2fSJacob Faibussowitsch Collective on dm 8938f108dbd7SJacob Faibussowitsch 8939f108dbd7SJacob Faibussowitsch Input Parameters: 8940f108dbd7SJacob Faibussowitsch + dm - The DMPlex object 8941f108dbd7SJacob Faibussowitsch . fv - Optional PetscFV object for pre-computed cell/face centroid information 8942f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 8943f108dbd7SJacob Faibussowitsch 8944f108dbd7SJacob Faibussowitsch Output Parameters: 8945f108dbd7SJacob Faibussowitsch + OrthQual - Vec containing orthogonal quality per cell 8946f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8947f108dbd7SJacob Faibussowitsch 8948f108dbd7SJacob Faibussowitsch Options Database Keys: 8949f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8950f108dbd7SJacob Faibussowitsch supported. 8951f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8952f108dbd7SJacob Faibussowitsch 8953f108dbd7SJacob Faibussowitsch Notes: 8954f108dbd7SJacob Faibussowitsch Orthogonal quality is given by the following formula: 8955f108dbd7SJacob Faibussowitsch 8956f108dbd7SJacob Faibussowitsch \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8957f108dbd7SJacob Faibussowitsch 8958f108dbd7SJacob 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 8959f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8960f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8961f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 8962f108dbd7SJacob Faibussowitsch 8963f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 8964f108dbd7SJacob Faibussowitsch 8965f108dbd7SJacob Faibussowitsch This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8966f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8967f108dbd7SJacob Faibussowitsch 8968f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8969f108dbd7SJacob Faibussowitsch 8970f108dbd7SJacob Faibussowitsch Level: intermediate 8971f108dbd7SJacob Faibussowitsch 8972db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()` 8973f108dbd7SJacob Faibussowitsch @*/ 8974f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8975f108dbd7SJacob Faibussowitsch { 89766ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 89776ed19f2fSJacob Faibussowitsch PetscInt *idx; 89786ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 8979f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 89806ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 8981f108dbd7SJacob Faibussowitsch MPI_Comm comm; 8982f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 8983f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 8984f108dbd7SJacob Faibussowitsch IS glob; 8985f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 8986f108dbd7SJacob Faibussowitsch PetscViewer vwr; 8987f108dbd7SJacob Faibussowitsch 8988f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 8989f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89906ed19f2fSJacob Faibussowitsch if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8991f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQual, 4); 89926bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 89939566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 89949566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 899563a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 89966ed19f2fSJacob Faibussowitsch { 89976ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 89986ed19f2fSJacob Faibussowitsch 89999566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9000f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9001f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9002f108dbd7SJacob Faibussowitsch 90039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 900498921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9005f108dbd7SJacob Faibussowitsch } 90066ed19f2fSJacob Faibussowitsch } 9007f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 9008f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQualLabel, 5); 90099566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 90109566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 90116ed19f2fSJacob Faibussowitsch } else {*OrthQualLabel = NULL;} 90129566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 90139566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 90149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 90159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 90169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 90179566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 90189566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 90199566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE)); 90209566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 90219566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 90229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 90239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 90249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 90259566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 90269566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 90279566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 90289566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 90299566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 90306ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++,cell++) { 90316ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9032f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9033f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9034898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9035f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9036f108dbd7SJacob Faibussowitsch 90376ed19f2fSJacob Faibussowitsch idx[cellIter] = cell-cStart; 9038f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9039f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 90409566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 90419566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9042f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 90439566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 90446ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 90456ed19f2fSJacob Faibussowitsch PetscInt i; 90466ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9047f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9048f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9049f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9050f108dbd7SJacob Faibussowitsch 9051f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9052f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 90539566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9054f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 90556ed19f2fSJacob Faibussowitsch { 90566ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 90576ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 90586ed19f2fSJacob Faibussowitsch 90599566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 90609566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 90619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 90626ed19f2fSJacob Faibussowitsch } 9063f108dbd7SJacob Faibussowitsch 9064f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9065f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9066f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9067f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9068f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9069addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9070addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9071addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9072f108dbd7SJacob Faibussowitsch } 9073addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9074addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9075addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9076f108dbd7SJacob Faibussowitsch 9077f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9078f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9079f108dbd7SJacob Faibussowitsch ci[i] = ci[i]/normci; 9080f108dbd7SJacob Faibussowitsch fi[i] = fi[i]/normfi; 9081f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i]/normai; 9082f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9083f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9084f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9085f108dbd7SJacob Faibussowitsch } 9086f108dbd7SJacob Faibussowitsch if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9087f108dbd7SJacob Faibussowitsch minvalc = PetscRealPart(cArr[cellneighiter]); 9088f108dbd7SJacob Faibussowitsch } 9089f108dbd7SJacob Faibussowitsch if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9090f108dbd7SJacob Faibussowitsch minvalf = PetscRealPart(fArr[cellneighiter]); 9091f108dbd7SJacob Faibussowitsch } 9092f108dbd7SJacob Faibussowitsch } 90939566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 90949566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9095f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 90966ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9097f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 90989566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9099f108dbd7SJacob Faibussowitsch } 9100f108dbd7SJacob Faibussowitsch } 91019566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES)); 91029566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 91039566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 91049566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 91059566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 91069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9107f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 91089566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9109f108dbd7SJacob Faibussowitsch } 91109566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 91119566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vwr)); 91129566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 9113f108dbd7SJacob Faibussowitsch PetscFunctionReturn(0); 9114f108dbd7SJacob Faibussowitsch } 9115f108dbd7SJacob Faibussowitsch 91161eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 91171eb70e55SToby Isaac * interpolator construction */ 91181eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 91191eb70e55SToby Isaac { 91201eb70e55SToby Isaac PetscSection section, newSection, gsection; 91211eb70e55SToby Isaac PetscSF sf; 91221eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 91231eb70e55SToby Isaac 91241eb70e55SToby Isaac PetscFunctionBegin; 91251eb70e55SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 91261eb70e55SToby Isaac PetscValidPointer(odm,2); 91279566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 91289566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 91299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm))); 91301eb70e55SToby Isaac if (!ghasConstraints) { 91319566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 91321eb70e55SToby Isaac *odm = dm; 91331eb70e55SToby Isaac PetscFunctionReturn(0); 91341eb70e55SToby Isaac } 91359566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 91369566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 91379566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 91389566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 91399566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 91409566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 91419566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 91421eb70e55SToby Isaac PetscFunctionReturn(0); 91431eb70e55SToby Isaac } 91441eb70e55SToby Isaac 91451eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 91461eb70e55SToby Isaac { 91471eb70e55SToby Isaac DM dmco, dmfo; 91481eb70e55SToby Isaac Mat interpo; 91491eb70e55SToby Isaac Vec rscale; 91501eb70e55SToby Isaac Vec cglobalo, clocal; 91511eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 91521eb70e55SToby Isaac PetscBool regular; 91531eb70e55SToby Isaac 91541eb70e55SToby Isaac PetscFunctionBegin; 91559566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 91569566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 91579566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 91589566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 91599566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 91609566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 91619566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 91629566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 91639566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 91649566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 91659566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 91669566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 91679566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 91689566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 91699566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 91709566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 91719566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 91729566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 91739566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 91749566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 91759566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 91769566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 91779566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 91789566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 91791eb70e55SToby Isaac *shift = fglobal; 91809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 91819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 91829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 91839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 91849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 91859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 91869566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 91879566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 91881eb70e55SToby Isaac PetscFunctionReturn(0); 91891eb70e55SToby Isaac } 91901eb70e55SToby Isaac 91911eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 91921eb70e55SToby Isaac { 91931eb70e55SToby Isaac PetscObject shifto; 91941eb70e55SToby Isaac Vec shift; 91951eb70e55SToby Isaac 91961eb70e55SToby Isaac PetscFunctionBegin; 91971eb70e55SToby Isaac if (!interp) { 91981eb70e55SToby Isaac Vec rscale; 91991eb70e55SToby Isaac 92009566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 92019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 92021eb70e55SToby Isaac } else { 92039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 92041eb70e55SToby Isaac } 92059566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 92061eb70e55SToby Isaac if (!shifto) { 92079566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 92089566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift)); 92091eb70e55SToby Isaac shifto = (PetscObject) shift; 92109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 92111eb70e55SToby Isaac } 92121eb70e55SToby Isaac shift = (Vec) shifto; 92139566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 92149566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 92159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 92161eb70e55SToby Isaac PetscFunctionReturn(0); 92171eb70e55SToby Isaac } 92181eb70e55SToby Isaac 9219bceba477SMatthew G. Knepley /* Pointwise interpolation 9220bceba477SMatthew G. Knepley Just code FEM for now 9221bceba477SMatthew G. Knepley u^f = I u^c 92224ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 92234ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 92244ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9225bceba477SMatthew G. Knepley */ 9226bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9227bceba477SMatthew G. Knepley { 9228bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9229bceba477SMatthew G. Knepley PetscInt m, n; 9230a063dac3SMatthew G. Knepley void *ctx; 923168132eb9SMatthew G. Knepley DM cdm; 9232cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9233bceba477SMatthew G. Knepley 9234bceba477SMatthew G. Knepley PetscFunctionBegin; 92359566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 92369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 92379566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 92389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 923968132eb9SMatthew G. Knepley 92409566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 92419566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation)); 92429566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 92439566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 92449566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 924568132eb9SMatthew G. Knepley 92469566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 92479566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 92489566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 92499566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 92509566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 92514db47ee9SStefano Zampini if (scaling) { 92525d1c2e58SMatthew G. Knepley /* Use naive scaling */ 92539566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 92544db47ee9SStefano Zampini } 9255a063dac3SMatthew G. Knepley PetscFunctionReturn(0); 9256a063dac3SMatthew G. Knepley } 9257bceba477SMatthew G. Knepley 92586dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9259a063dac3SMatthew G. Knepley { 92606dbf9973SLawrence Mitchell VecScatter ctx; 926190748bafSMatthew G. Knepley 9262a063dac3SMatthew G. Knepley PetscFunctionBegin; 92639566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 92649566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 92659566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 9266bceba477SMatthew G. Knepley PetscFunctionReturn(0); 9267bceba477SMatthew G. Knepley } 9268bceba477SMatthew G. Knepley 92693e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 92703e9753d6SMatthew G. Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 92713e9753d6SMatthew G. Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 92723e9753d6SMatthew G. Knepley PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 92733e9753d6SMatthew G. Knepley { 927400635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 927500635df3SMatthew G. Knepley PetscInt c; 927600635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 92773e9753d6SMatthew G. Knepley } 92783e9753d6SMatthew G. Knepley 9279b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9280b4937a87SMatthew G. Knepley { 9281b4937a87SMatthew G. Knepley DM dmc; 9282b4937a87SMatthew G. Knepley PetscDS ds; 9283b4937a87SMatthew G. Knepley Vec ones, locmass; 9284b4937a87SMatthew G. Knepley IS cellIS; 9285b4937a87SMatthew G. Knepley PetscFormKey key; 9286b4937a87SMatthew G. Knepley PetscInt depth; 9287b4937a87SMatthew G. Knepley 9288b4937a87SMatthew G. Knepley PetscFunctionBegin; 92899566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 92909566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 92919566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 92929566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92939566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 92949566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 92959566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 92969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 92979566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 92989566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 92999566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9300b4937a87SMatthew G. Knepley key.label = NULL; 9301b4937a87SMatthew G. Knepley key.value = 0; 9302b4937a87SMatthew G. Knepley key.field = 0; 9303b4937a87SMatthew G. Knepley key.part = 0; 93049566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 93059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 93069566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 93079566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 93089566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 93099566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 93109566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 93119566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 9312b4937a87SMatthew G. Knepley PetscFunctionReturn(0); 9313b4937a87SMatthew G. Knepley } 9314b4937a87SMatthew G. Knepley 9315bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9316bd041c0cSMatthew G. Knepley { 9317bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9318bd041c0cSMatthew G. Knepley PetscInt m, n; 9319bd041c0cSMatthew G. Knepley void *ctx; 9320bd041c0cSMatthew G. Knepley DM cdm; 9321bd041c0cSMatthew G. Knepley PetscBool regular; 9322bd041c0cSMatthew G. Knepley 9323bd041c0cSMatthew G. Knepley PetscFunctionBegin; 93243e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 93253e9753d6SMatthew G. Knepley DM dmc; 93263e9753d6SMatthew G. Knepley PetscDS ds; 9327b4937a87SMatthew G. Knepley PetscWeakForm wf; 93283e9753d6SMatthew G. Knepley Vec u; 93293e9753d6SMatthew G. Knepley IS cellIS; 933006ad1575SMatthew G. Knepley PetscFormKey key; 93313e9753d6SMatthew G. Knepley PetscInt depth; 93323e9753d6SMatthew G. Knepley 93339566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 93349566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 93359566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 93369566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 93379566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 93389566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 93399566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 93409566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmc, &u)); 93419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 93429566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 93439566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 93446528b96dSMatthew G. Knepley key.label = NULL; 93456528b96dSMatthew G. Knepley key.value = 0; 93466528b96dSMatthew G. Knepley key.field = 0; 934706ad1575SMatthew G. Knepley key.part = 0; 93489566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 93499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 93509566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmc, &u)); 93519566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 93523e9753d6SMatthew G. Knepley } else { 93539566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 93549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 93559566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 93569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9357bd041c0cSMatthew G. Knepley 93589566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass)); 93599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 93609566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 93619566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9362bd041c0cSMatthew G. Knepley 93639566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 93649566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 93659566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 93669566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 93673e9753d6SMatthew G. Knepley } 93689566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 9369bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 9370bd041c0cSMatthew G. Knepley } 9371bd041c0cSMatthew G. Knepley 93720aef6b92SMatthew G. Knepley /*@ 93730aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93740aef6b92SMatthew G. Knepley 93750aef6b92SMatthew G. Knepley Input Parameter: 93760aef6b92SMatthew G. Knepley . dm - The DMPlex object 93770aef6b92SMatthew G. Knepley 93780aef6b92SMatthew G. Knepley Output Parameter: 93790aef6b92SMatthew G. Knepley . regular - The flag 93800aef6b92SMatthew G. Knepley 93810aef6b92SMatthew G. Knepley Level: intermediate 93820aef6b92SMatthew G. Knepley 9383db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()` 93840aef6b92SMatthew G. Knepley @*/ 93850aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 93860aef6b92SMatthew G. Knepley { 93870aef6b92SMatthew G. Knepley PetscFunctionBegin; 93880aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9389dadcf809SJacob Faibussowitsch PetscValidBoolPointer(regular, 2); 93900aef6b92SMatthew G. Knepley *regular = ((DM_Plex *) dm->data)->regularRefinement; 93910aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93920aef6b92SMatthew G. Knepley } 93930aef6b92SMatthew G. Knepley 93940aef6b92SMatthew G. Knepley /*@ 93950aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93960aef6b92SMatthew G. Knepley 93970aef6b92SMatthew G. Knepley Input Parameters: 93980aef6b92SMatthew G. Knepley + dm - The DMPlex object 93990aef6b92SMatthew G. Knepley - regular - The flag 94000aef6b92SMatthew G. Knepley 94010aef6b92SMatthew G. Knepley Level: intermediate 94020aef6b92SMatthew G. Knepley 9403db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()` 94040aef6b92SMatthew G. Knepley @*/ 94050aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 94060aef6b92SMatthew G. Knepley { 94070aef6b92SMatthew G. Knepley PetscFunctionBegin; 94080aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94090aef6b92SMatthew G. Knepley ((DM_Plex *) dm->data)->regularRefinement = regular; 94100aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 94110aef6b92SMatthew G. Knepley } 94120aef6b92SMatthew G. Knepley 9413f7c74593SToby Isaac /* anchors */ 9414a68b90caSToby Isaac /*@ 9415f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9416ebdb1bfaSJed Brown call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9417a68b90caSToby Isaac 9418e228b242SToby Isaac not collective 9419a68b90caSToby Isaac 9420f899ff85SJose E. Roman Input Parameter: 9421a68b90caSToby Isaac . dm - The DMPlex object 9422a68b90caSToby Isaac 9423a68b90caSToby Isaac Output Parameters: 9424a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9425a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9426a68b90caSToby Isaac 9427a68b90caSToby Isaac Level: intermediate 9428a68b90caSToby Isaac 9429db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9430a68b90caSToby Isaac @*/ 9431a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9432a68b90caSToby Isaac { 9433a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9434a68b90caSToby Isaac 9435a68b90caSToby Isaac PetscFunctionBegin; 9436a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94379566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 9438a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 9439a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 9440a68b90caSToby Isaac PetscFunctionReturn(0); 9441a68b90caSToby Isaac } 9442a68b90caSToby Isaac 9443a68b90caSToby Isaac /*@ 9444f7c74593SToby Isaac DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9445f7c74593SToby Isaac when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9446a68b90caSToby Isaac point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9447a68b90caSToby Isaac 9448a17985deSToby Isaac After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9449ebdb1bfaSJed Brown DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9450a68b90caSToby Isaac 9451e228b242SToby Isaac collective on dm 9452a68b90caSToby Isaac 9453a68b90caSToby Isaac Input Parameters: 9454a68b90caSToby Isaac + dm - The DMPlex object 9455e228b242SToby 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). 9456e228b242SToby Isaac - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9457a68b90caSToby Isaac 9458a68b90caSToby Isaac The reference counts of anchorSection and anchorIS are incremented. 9459a68b90caSToby Isaac 9460a68b90caSToby Isaac Level: intermediate 9461a68b90caSToby Isaac 9462db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9463a68b90caSToby Isaac @*/ 9464a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9465a68b90caSToby Isaac { 9466a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9467e228b242SToby Isaac PetscMPIInt result; 9468a68b90caSToby Isaac 9469a68b90caSToby Isaac PetscFunctionBegin; 9470a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9471e228b242SToby Isaac if (anchorSection) { 9472e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 94739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result)); 94741dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9475e228b242SToby Isaac } 9476e228b242SToby Isaac if (anchorIS) { 9477e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 94789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result)); 94791dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9480e228b242SToby Isaac } 9481a68b90caSToby Isaac 94829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 94839566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 9484a68b90caSToby Isaac plex->anchorSection = anchorSection; 9485a68b90caSToby Isaac 94869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 94879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 9488a68b90caSToby Isaac plex->anchorIS = anchorIS; 9489a68b90caSToby Isaac 9490cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9491a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 9492a68b90caSToby Isaac const PetscInt *anchors; 9493a68b90caSToby Isaac 94949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 94959566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS,&size)); 94969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS,&anchors)); 9497a68b90caSToby Isaac for (a = 0; a < size; a++) { 9498a68b90caSToby Isaac PetscInt p; 9499a68b90caSToby Isaac 9500a68b90caSToby Isaac p = anchors[a]; 9501a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 9502a68b90caSToby Isaac PetscInt dof; 9503a68b90caSToby Isaac 95049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection,p,&dof)); 9505a68b90caSToby Isaac if (dof) { 9506a68b90caSToby Isaac 95079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS,&anchors)); 950863a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %" PetscInt_FMT " cannot be constrained and an anchor",p); 9509a68b90caSToby Isaac } 9510a68b90caSToby Isaac } 9511a68b90caSToby Isaac } 95129566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS,&anchors)); 9513a68b90caSToby Isaac } 9514f7c74593SToby Isaac /* reset the generic constraints */ 95159566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,NULL,NULL,NULL)); 9516a68b90caSToby Isaac PetscFunctionReturn(0); 9517a68b90caSToby Isaac } 9518a68b90caSToby Isaac 9519f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9520a68b90caSToby Isaac { 9521f7c74593SToby Isaac PetscSection anchorSection; 95226995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9523a68b90caSToby Isaac 9524a68b90caSToby Isaac PetscFunctionBegin; 9525a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95269566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL)); 95279566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,cSec)); 95289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numFields)); 95296995de1eSToby Isaac if (numFields) { 9530719ab38cSToby Isaac PetscInt f; 95319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec,numFields)); 9532719ab38cSToby Isaac 9533719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 9534719ab38cSToby Isaac PetscInt numComp; 9535719ab38cSToby Isaac 95369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section,f,&numComp)); 95379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec,f,numComp)); 9538719ab38cSToby Isaac } 95396995de1eSToby Isaac } 95409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 95419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&sStart,&sEnd)); 95426995de1eSToby Isaac pStart = PetscMax(pStart,sStart); 95436995de1eSToby Isaac pEnd = PetscMin(pEnd,sEnd); 95446995de1eSToby Isaac pEnd = PetscMax(pStart,pEnd); 95459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec,pStart,pEnd)); 9546a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 95479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection,p,&dof)); 9548a68b90caSToby Isaac if (dof) { 95499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,p,&dof)); 95509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec,p,dof)); 9551a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 95529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,p,f,&dof)); 95539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec,p,f,dof)); 9554a68b90caSToby Isaac } 9555a68b90caSToby Isaac } 9556a68b90caSToby Isaac } 95579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 95589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *cSec, "Constraint Section")); 9559a68b90caSToby Isaac PetscFunctionReturn(0); 9560a68b90caSToby Isaac } 9561a68b90caSToby Isaac 9562f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9563a68b90caSToby Isaac { 9564f7c74593SToby Isaac PetscSection aSec; 9565ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 95660ac89760SToby Isaac const PetscInt *anchors; 95670ac89760SToby Isaac PetscInt numFields, f; 956866ad2231SToby Isaac IS aIS; 9569e19f7ee6SMark Adams MatType mtype; 9570e19f7ee6SMark Adams PetscBool iscuda,iskokkos; 95710ac89760SToby Isaac 95720ac89760SToby Isaac PetscFunctionBegin; 95730ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 95759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 95769566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,cMat)); 95779566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat,m,n,m,n)); 95789566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda)); 95799566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda)); 95809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos)); 95819566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos)); 9582e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 9583e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9584e19f7ee6SMark Adams else mtype = MATSEQAIJ; 95859566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat,mtype)); 95869566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 95879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 95886995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 95899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec,&pStart,&pEnd)); 95909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&sStart,&sEnd)); 95919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&i)); 95920ac89760SToby Isaac i[0] = 0; 95939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numFields)); 95940ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 9595f19733c5SToby Isaac PetscInt rDof, rOff, r; 9596f19733c5SToby Isaac 95979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 9598f19733c5SToby Isaac if (!rDof) continue; 95999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96000ac89760SToby Isaac if (numFields) { 96010ac89760SToby Isaac for (f = 0; f < numFields; f++) { 96020ac89760SToby Isaac annz = 0; 9603f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 9604f19733c5SToby Isaac a = anchors[rOff + r]; 9605ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof)); 96070ac89760SToby Isaac annz += aDof; 96080ac89760SToby Isaac } 96099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof)); 96109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&off)); 96110ac89760SToby Isaac for (q = 0; q < dof; q++) { 96120ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 96130ac89760SToby Isaac } 96140ac89760SToby Isaac } 96152f7452b8SBarry Smith } else { 96160ac89760SToby Isaac annz = 0; 96179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96180ac89760SToby Isaac for (q = 0; q < dof; q++) { 9619ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 9620ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 96220ac89760SToby Isaac annz += aDof; 96230ac89760SToby Isaac } 96249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec,p,&off)); 96260ac89760SToby Isaac for (q = 0; q < dof; q++) { 96270ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 96280ac89760SToby Isaac } 96290ac89760SToby Isaac } 96300ac89760SToby Isaac } 96310ac89760SToby Isaac nnz = i[m]; 96329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&j)); 96330ac89760SToby Isaac offset = 0; 96340ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 96350ac89760SToby Isaac if (numFields) { 96360ac89760SToby Isaac for (f = 0; f < numFields; f++) { 96379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof)); 96380ac89760SToby Isaac for (q = 0; q < dof; q++) { 96390ac89760SToby Isaac PetscInt rDof, rOff, r; 96409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 96419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96420ac89760SToby Isaac for (r = 0; r < rDof; r++) { 96430ac89760SToby Isaac PetscInt s; 96440ac89760SToby Isaac 96450ac89760SToby Isaac a = anchors[rOff + r]; 9646ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof)); 96489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section,a,f,&aOff)); 96490ac89760SToby Isaac for (s = 0; s < aDof; s++) { 96500ac89760SToby Isaac j[offset++] = aOff + s; 96510ac89760SToby Isaac } 96520ac89760SToby Isaac } 96530ac89760SToby Isaac } 96540ac89760SToby Isaac } 96552f7452b8SBarry Smith } else { 96569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96570ac89760SToby Isaac for (q = 0; q < dof; q++) { 96580ac89760SToby Isaac PetscInt rDof, rOff, r; 96599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 96609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96610ac89760SToby Isaac for (r = 0; r < rDof; r++) { 96620ac89760SToby Isaac PetscInt s; 96630ac89760SToby Isaac 96640ac89760SToby Isaac a = anchors[rOff + r]; 9665ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 96679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,a,&aOff)); 96680ac89760SToby Isaac for (s = 0; s < aDof; s++) { 96690ac89760SToby Isaac j[offset++] = aOff + s; 96700ac89760SToby Isaac } 96710ac89760SToby Isaac } 96720ac89760SToby Isaac } 96730ac89760SToby Isaac } 96740ac89760SToby Isaac } 96759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL)); 96769566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 96779566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 96789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 96790ac89760SToby Isaac PetscFunctionReturn(0); 96800ac89760SToby Isaac } 96810ac89760SToby Isaac 968266ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 968366ad2231SToby Isaac { 9684f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9685f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 968666ad2231SToby Isaac Mat cMat; 968766ad2231SToby Isaac 968866ad2231SToby Isaac PetscFunctionBegin; 968966ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 96909566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL)); 969166ad2231SToby Isaac if (anchorSection) { 969244a7f3ddSMatthew G. Knepley PetscInt Nf; 9693e228b242SToby Isaac 96949566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm,§ion)); 96959566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec)); 96969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat)); 96979566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm,&Nf)); 96989566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm,section,cSec,cMat)); 96999566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,cSec,cMat,NULL)); 97009566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 97019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 970266ad2231SToby Isaac } 970366ad2231SToby Isaac PetscFunctionReturn(0); 970466ad2231SToby Isaac } 9705a93c429eSMatthew G. Knepley 9706a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9707a93c429eSMatthew G. Knepley { 9708a93c429eSMatthew G. Knepley IS subis; 9709a93c429eSMatthew G. Knepley PetscSection section, subsection; 9710a93c429eSMatthew G. Knepley 9711a93c429eSMatthew G. Knepley PetscFunctionBegin; 97129566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 971328b400f6SJacob Faibussowitsch PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 971428b400f6SJacob Faibussowitsch PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9715a93c429eSMatthew G. Knepley /* Create subdomain */ 97169566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 9717a93c429eSMatthew G. Knepley /* Create submodel */ 97189566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 97199566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 97209566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 97219566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 97229566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 9723a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 9724a93c429eSMatthew G. Knepley if (is) { 9725a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 9726a93c429eSMatthew G. Knepley IS spIS; 9727a93c429eSMatthew G. Knepley const PetscInt *spmap; 9728a93c429eSMatthew G. Knepley PetscInt *subIndices; 9729a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9730a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9731a93c429eSMatthew G. Knepley 97329566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 97339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 97349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 97359566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 97369566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 97379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 9738a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9739a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 9740a93c429eSMatthew G. Knepley 97419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 9742a93c429eSMatthew G. Knepley if (gdof > 0) { 9743a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9744a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 9745a93c429eSMatthew G. Knepley 97469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 97479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 9748a93c429eSMatthew G. Knepley pSubSize += fdof-fcdof; 9749a93c429eSMatthew G. Knepley } 9750a93c429eSMatthew G. Knepley subSize += pSubSize; 9751a93c429eSMatthew G. Knepley if (pSubSize) { 9752a93c429eSMatthew G. Knepley if (bs < 0) { 9753a93c429eSMatthew G. Knepley bs = pSubSize; 9754a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 9755a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 9756a93c429eSMatthew G. Knepley bs = 1; 9757a93c429eSMatthew G. Knepley } 9758a93c429eSMatthew G. Knepley } 9759a93c429eSMatthew G. Knepley } 9760a93c429eSMatthew G. Knepley } 9761a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 9762a93c429eSMatthew G. Knepley bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 97639566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 9764a93c429eSMatthew G. Knepley if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9765a93c429eSMatthew G. Knepley else {bs = bsMinMax[0];} 97669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 9767a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9768a93c429eSMatthew G. Knepley PetscInt gdof, goff; 9769a93c429eSMatthew G. Knepley 97709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 9771a93c429eSMatthew G. Knepley if (gdof > 0) { 9772a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 9773a93c429eSMatthew G. Knepley 97749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 9775a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9776a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 9777a93c429eSMatthew G. Knepley 9778a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 9779a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 97809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 97819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 9782a93c429eSMatthew G. Knepley poff += fdof-fcdof; 9783a93c429eSMatthew G. Knepley } 97849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 97859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 9786a93c429eSMatthew G. Knepley for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9787a93c429eSMatthew G. Knepley subIndices[subOff] = goff+poff+fc; 9788a93c429eSMatthew G. Knepley } 9789a93c429eSMatthew G. Knepley } 9790a93c429eSMatthew G. Knepley } 9791a93c429eSMatthew G. Knepley } 97929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 97939566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 9794a93c429eSMatthew G. Knepley if (bs > 1) { 9795a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 9796a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 9797a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 9798a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 9799a93c429eSMatthew G. Knepley if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9800a93c429eSMatthew G. Knepley } 9801a93c429eSMatthew G. Knepley } 98029566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 9803a93c429eSMatthew G. Knepley } 9804a93c429eSMatthew G. Knepley /* Attach nullspace */ 9805a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9806a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9807a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 9808a93c429eSMatthew G. Knepley } 9809a93c429eSMatthew G. Knepley if (f < Nf) { 9810a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 98119566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 98126823f3c5SBlaise Bourdin 98139566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace)); 98149566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 9815a93c429eSMatthew G. Knepley } 9816a93c429eSMatthew G. Knepley } 9817a93c429eSMatthew G. Knepley PetscFunctionReturn(0); 9818a93c429eSMatthew G. Knepley } 9819c0f0dcc3SMatthew G. Knepley 9820c0f0dcc3SMatthew G. Knepley /*@ 9821c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 9822c0f0dcc3SMatthew G. Knepley 9823c0f0dcc3SMatthew G. Knepley Input Parameter: 9824c0f0dcc3SMatthew G. Knepley - dm - The DM 9825c0f0dcc3SMatthew G. Knepley 9826c0f0dcc3SMatthew G. Knepley Level: developer 9827c0f0dcc3SMatthew G. Knepley 9828c0f0dcc3SMatthew G. Knepley Options Database Keys: 9829c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor 9830c0f0dcc3SMatthew G. Knepley 9831db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()` 9832c0f0dcc3SMatthew G. Knepley @*/ 9833c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9834c0f0dcc3SMatthew G. Knepley { 9835e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG) 9836c0f0dcc3SMatthew G. Knepley PetscStageLog stageLog; 9837c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 9838c0f0dcc3SMatthew G. Knepley PetscLogStage stage; 9839c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 9840c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 9841c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 9842c0f0dcc3SMatthew G. Knepley const char *name; 9843e5ed2c37SJose E. Roman #endif 9844c0f0dcc3SMatthew G. Knepley 9845c0f0dcc3SMatthew G. Knepley PetscFunctionBegin; 9846c0f0dcc3SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9847c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG) 98489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 98499566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 98509566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 98519566063dSJacob Faibussowitsch PetscCall(PetscLogGetStageLog(&stageLog)); 98529566063dSJacob Faibussowitsch PetscCall(PetscStageLogGetCurrent(stageLog, &stage)); 98539566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 98549566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 9855c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart)*Nf*eventInfo.count; 9856c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops/eventInfo.time; 9857c0f0dcc3SMatthew G. Knepley cellRate = N/eventInfo.time; 985863a3b9bcSJacob 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))); 9859c0f0dcc3SMatthew G. Knepley #else 9860c0f0dcc3SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9861c0f0dcc3SMatthew G. Knepley #endif 9862c0f0dcc3SMatthew G. Knepley PetscFunctionReturn(0); 9863c0f0dcc3SMatthew G. Knepley } 9864