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; 13552f7358SJed Brown 145a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 15552f7358SJed Brown 16e5337592SStefano Zampini /*@ 179318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 189318fe57SMatthew G. Knepley 199318fe57SMatthew G. Knepley Input Parameter: 209318fe57SMatthew G. Knepley . dm - The DMPlex object 219318fe57SMatthew G. Knepley 229318fe57SMatthew G. Knepley Output Parameter: 239318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 249318fe57SMatthew G. Knepley 259318fe57SMatthew 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. 269318fe57SMatthew G. Knepley If the mesh has no cells, this returns PETSC_FALSE. 279318fe57SMatthew G. Knepley 289318fe57SMatthew G. Knepley Level: intermediate 299318fe57SMatthew G. Knepley 30db781477SPatrick Sanan .seealso `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 319318fe57SMatthew G. Knepley @*/ 329318fe57SMatthew G. Knepley PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 339318fe57SMatthew G. Knepley { 349318fe57SMatthew G. Knepley DMPolytopeType ct; 359318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 369318fe57SMatthew G. Knepley 379318fe57SMatthew G. Knepley PetscFunctionBegin; 389566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 399318fe57SMatthew G. Knepley if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 419318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 429318fe57SMatthew G. Knepley PetscFunctionReturn(0); 439318fe57SMatthew G. Knepley } 449318fe57SMatthew G. Knepley 459318fe57SMatthew G. Knepley /*@ 46412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 47e5337592SStefano Zampini 48d8d19677SJose E. Roman Input Parameters: 49412e9a14SMatthew G. Knepley + dm - The DMPlex object 50412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 51e5337592SStefano Zampini 52e5337592SStefano Zampini Output Parameters: 53412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 54412e9a14SMatthew G. Knepley - cEnd - The upper bound on "normal"" cells 55e5337592SStefano Zampini 56412e9a14SMatthew 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. 57e5337592SStefano Zampini 58412e9a14SMatthew G. Knepley Level: developer 59e5337592SStefano Zampini 60db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 61e5337592SStefano Zampini @*/ 62412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 63e5337592SStefano Zampini { 64412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 65412e9a14SMatthew G. Knepley PetscInt cS, cE, c; 66e5337592SStefano Zampini 67e5337592SStefano Zampini PetscFunctionBegin; 689566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE)); 69412e9a14SMatthew G. Knepley for (c = cS; c < cE; ++c) { 70412e9a14SMatthew G. Knepley DMPolytopeType cct; 71412e9a14SMatthew G. Knepley 729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &cct)); 73412e9a14SMatthew G. Knepley if ((PetscInt) cct < 0) break; 74412e9a14SMatthew G. Knepley switch (cct) { 75ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 76ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 77ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 78ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 79ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 80ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 81412e9a14SMatthew G. Knepley ct = cct; 82e5337592SStefano Zampini break; 83412e9a14SMatthew G. Knepley default: break; 84e5337592SStefano Zampini } 85412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) break; 86e5337592SStefano Zampini } 87412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) { 88412e9a14SMatthew G. Knepley DMLabel ctLabel; 89412e9a14SMatthew G. Knepley 909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 919566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE)); 92e5337592SStefano Zampini } 93412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 94412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 95e5337592SStefano Zampini PetscFunctionReturn(0); 96e5337592SStefano Zampini } 97e5337592SStefano Zampini 987afe7537SMatthew G. Knepley PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 997e42fee7SMatthew G. Knepley { 100412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 101a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 1027e42fee7SMatthew G. Knepley 1037e42fee7SMatthew G. Knepley PetscFunctionBegin; 104e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 1059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 1089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1097e42fee7SMatthew G. Knepley if (field >= 0) { 1109566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 1119566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 1127e42fee7SMatthew G. Knepley } else { 1139566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 1149566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 1157e42fee7SMatthew G. Knepley } 1169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 117a99a26bcSAdrian Croucher if (globalvcdof[0]) { 1187e42fee7SMatthew G. Knepley *sStart = vStart; 1197e42fee7SMatthew G. Knepley *sEnd = vEnd; 120f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 1217e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 122a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 1237e42fee7SMatthew G. Knepley *sStart = cStart; 1247e42fee7SMatthew G. Knepley *sEnd = cEnd; 125f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 1267e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 127e630c359SToby Isaac } else { 128e630c359SToby Isaac if (field >= 0) { 129e630c359SToby Isaac const char *fieldname; 130e630c359SToby Isaac 1319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 13263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 133e630c359SToby Isaac } else { 13463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\n")); 135e630c359SToby Isaac } 136e630c359SToby Isaac } 1377e42fee7SMatthew G. Knepley PetscFunctionReturn(0); 1387e42fee7SMatthew G. Knepley } 1397e42fee7SMatthew G. Knepley 1406913077dSMatthew G. Knepley /*@ 1416913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 1426913077dSMatthew G. Knepley 1436913077dSMatthew G. Knepley Collective on dm 1446913077dSMatthew G. Knepley 1456913077dSMatthew G. Knepley Input Parameters: 1466913077dSMatthew G. Knepley + dm - The DMPlex 1476913077dSMatthew G. Knepley . n - The number of vectors 1486913077dSMatthew G. Knepley . u - The array of local vectors 1496913077dSMatthew G. Knepley - viewer - The Draw viewer 1506913077dSMatthew G. Knepley 1516913077dSMatthew G. Knepley Level: advanced 1526913077dSMatthew G. Knepley 153db781477SPatrick Sanan .seealso: `VecViewFromOptions()`, `VecView()` 1546913077dSMatthew G. Knepley @*/ 1556913077dSMatthew G. Knepley PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 1566913077dSMatthew G. Knepley { 1576913077dSMatthew G. Knepley PetscDS ds; 1586913077dSMatthew G. Knepley PetscDraw draw = NULL; 1596913077dSMatthew G. Knepley PetscDrawLG lg; 1606913077dSMatthew G. Knepley Vec coordinates; 1616913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 1626913077dSMatthew G. Knepley PetscReal *vals; 1636913077dSMatthew G. Knepley PetscInt *Nc; 1646913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 1656913077dSMatthew G. Knepley char **names; 1666913077dSMatthew G. Knepley 1676913077dSMatthew G. Knepley PetscFunctionBegin; 1689566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 1699566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 1709566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 1719566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 1726913077dSMatthew G. Knepley 1739566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 1746913077dSMatthew G. Knepley if (!draw) PetscFunctionReturn(0); 1759566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n*Nl, &lg)); 1766913077dSMatthew G. Knepley 1779566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n*Nl, &names, n*Nl, &vals)); 1786913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 1796913077dSMatthew G. Knepley const char *vname; 1806913077dSMatthew G. Knepley 1819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) u[i], &vname)); 1826913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1836913077dSMatthew G. Knepley PetscObject disc; 1846913077dSMatthew G. Knepley const char *fname; 1856913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 1866913077dSMatthew G. Knepley 1879566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 1886913077dSMatthew G. Knepley /* TODO Create names for components */ 1896913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 1909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 1919566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(tmpname, vname)); 1929566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN)); 1939566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN)); 1949566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 1956913077dSMatthew G. Knepley } 1966913077dSMatthew G. Knepley } 1976913077dSMatthew G. Knepley } 1989566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *) names)); 1996913077dSMatthew G. Knepley /* Just add P_1 support for now */ 2009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2029566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 2039566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 2046913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 2056913077dSMatthew G. Knepley PetscScalar *x, *svals; 2066913077dSMatthew G. Knepley 2079566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 2086913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 2099566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 2106913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i*Nl + l] = PetscRealPart(svals[l]); 2116913077dSMatthew G. Knepley } 2129566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 2136913077dSMatthew G. Knepley } 2149566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 2159566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 2169566063dSJacob Faibussowitsch for (l = 0; l < n*Nl; ++l) PetscCall(PetscFree(names[l])); 2179566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 2186913077dSMatthew G. Knepley 2199566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 2209566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 2216913077dSMatthew G. Knepley PetscFunctionReturn(0); 2226913077dSMatthew G. Knepley } 2236913077dSMatthew G. Knepley 2246913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 2256913077dSMatthew G. Knepley { 2266913077dSMatthew G. Knepley DM dm; 2276913077dSMatthew G. Knepley 2286913077dSMatthew G. Knepley PetscFunctionBegin; 2299566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 2309566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 2316913077dSMatthew G. Knepley PetscFunctionReturn(0); 2326913077dSMatthew G. Knepley } 2336913077dSMatthew G. Knepley 2346913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 235e412dcbdSMatthew G. Knepley { 236e412dcbdSMatthew G. Knepley DM dm; 237d1df6f1dSMatthew G. Knepley PetscSection s; 238e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 239e412dcbdSMatthew G. Knepley DM cdm; 240e412dcbdSMatthew G. Knepley PetscSection coordSection; 241e412dcbdSMatthew G. Knepley Vec coordinates; 242e412dcbdSMatthew G. Knepley const PetscScalar *coords, *array; 243e412dcbdSMatthew G. Knepley PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 244339e3443SMatthew G. Knepley PetscReal vbound[2], time; 2456913077dSMatthew G. Knepley PetscBool flg; 246d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 247e412dcbdSMatthew G. Knepley const char *name; 248339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 249e412dcbdSMatthew G. Knepley 250e412dcbdSMatthew G. Knepley PetscFunctionBegin; 2519566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2529566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 2539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 2549566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 2559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 2569566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 2579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 2589566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 2599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2619566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 262e412dcbdSMatthew G. Knepley 2639566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 2649566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 265e412dcbdSMatthew G. Knepley 2669566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 2679566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 268e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 2690c81f2a8SMatthew G. Knepley bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 2700c81f2a8SMatthew G. Knepley bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 271e412dcbdSMatthew G. Knepley } 2729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 2739566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 274e412dcbdSMatthew G. Knepley 275d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 276d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 277d1df6f1dSMatthew G. Knepley DM fdm = dm; 278d1df6f1dSMatthew G. Knepley Vec fv = v; 279d1df6f1dSMatthew G. Knepley IS fis; 280d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 281d1df6f1dSMatthew G. Knepley const char *fname; 282d1df6f1dSMatthew G. Knepley 2839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 2849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 285d1df6f1dSMatthew G. Knepley 2869566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix))); 287d1df6f1dSMatthew G. Knepley else {prefix[0] = '\0';} 288d1df6f1dSMatthew G. Knepley if (Nf > 1) { 2899566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 2909566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 2919566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname,sizeof(prefix))); 2929566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_",sizeof(prefix))); 293d1df6f1dSMatthew G. Knepley } 294d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 295d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 296d1df6f1dSMatthew G. Knepley 2979566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 29863a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 29963a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 3009566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 301d1df6f1dSMatthew G. Knepley 302d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 3039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 304339e3443SMatthew G. Knepley if (!flg) { 3059566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 3069566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 307d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 308339e3443SMatthew G. Knepley } 3099566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 3109566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 3119566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3])); 312e412dcbdSMatthew G. Knepley 3139566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 314e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 31599a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 316e56f9228SJed Brown PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 317e412dcbdSMatthew G. Knepley 3189566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 319339e3443SMatthew G. Knepley if (a) { 320d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 321339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 322339e3443SMatthew G. Knepley } else { 323339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 324339e3443SMatthew G. Knepley PetscInt numVals, va; 325339e3443SMatthew G. Knepley 3269566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 32763a3b9bcSJacob 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); 328d1df6f1dSMatthew G. Knepley switch (numVals/Nc) { 329d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 330d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 331d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 332339e3443SMatthew G. Knepley break; 333d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 334d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 335d1df6f1dSMatthew 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]); 336d1df6f1dSMatthew G. Knepley break; 33763a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals/Nc); 338339e3443SMatthew G. Knepley } 3399566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 340339e3443SMatthew G. Knepley } 3419566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 342e412dcbdSMatthew G. Knepley switch (numCoords) { 343e412dcbdSMatthew G. Knepley case 6: 3449edc3542SMatthew Knepley case 12: /* Localized triangle */ 3459566063dSJacob 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])); 346e412dcbdSMatthew G. Knepley break; 347e412dcbdSMatthew G. Knepley case 8: 3489edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 3499566063dSJacob 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])); 3509566063dSJacob 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])); 351e412dcbdSMatthew G. Knepley break; 35263a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 353e412dcbdSMatthew G. Knepley } 3549566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 355e412dcbdSMatthew G. Knepley } 3569566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 3579566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 3589566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 3599566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 360d1df6f1dSMatthew G. Knepley } 361d1df6f1dSMatthew G. Knepley if (Nf > 1) { 3629566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 3639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 3649566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 365d1df6f1dSMatthew G. Knepley } 366d1df6f1dSMatthew G. Knepley } 367e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 368e412dcbdSMatthew G. Knepley } 369e412dcbdSMatthew G. Knepley 3706913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 3716913077dSMatthew G. Knepley { 3726913077dSMatthew G. Knepley DM dm; 3736913077dSMatthew G. Knepley PetscDraw draw; 3746913077dSMatthew G. Knepley PetscInt dim; 3756913077dSMatthew G. Knepley PetscBool isnull; 3766913077dSMatthew G. Knepley 3776913077dSMatthew G. Knepley PetscFunctionBegin; 3789566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3799566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 3806913077dSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 3816913077dSMatthew G. Knepley 3829566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3846913077dSMatthew G. Knepley switch (dim) { 3859566063dSJacob Faibussowitsch case 1: PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));break; 3869566063dSJacob Faibussowitsch case 2: PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));break; 3875f80ce2aSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 3886913077dSMatthew G. Knepley } 3896913077dSMatthew G. Knepley PetscFunctionReturn(0); 3906913077dSMatthew G. Knepley } 3916913077dSMatthew G. Knepley 392684b87d9SLisandro Dalcin static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 393684b87d9SLisandro Dalcin { 394684b87d9SLisandro Dalcin DM dm; 395684b87d9SLisandro Dalcin Vec locv; 396684b87d9SLisandro Dalcin const char *name; 397684b87d9SLisandro Dalcin PetscSection section; 398684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 399e630c359SToby Isaac PetscInt numFields; 400684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 401684b87d9SLisandro Dalcin 402684b87d9SLisandro Dalcin PetscFunctionBegin; 4039566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4049566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 4059566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 4069566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) locv, name)); 4079566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4089566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 4099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 410e630c359SToby Isaac if (!numFields) { 4119566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 4129566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv)); 413e630c359SToby Isaac } else { 414e630c359SToby Isaac PetscInt f; 415e630c359SToby Isaac 416e630c359SToby Isaac for (f = 0; f < numFields; f++) { 4179566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 418e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 4199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 4209566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv)); 421e630c359SToby Isaac } 4229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 423e630c359SToby Isaac } 424684b87d9SLisandro Dalcin PetscFunctionReturn(0); 425684b87d9SLisandro Dalcin } 426684b87d9SLisandro Dalcin 427552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 428552f7358SJed Brown { 429552f7358SJed Brown DM dm; 430684b87d9SLisandro Dalcin PetscBool isvtk, ishdf5, isdraw, isglvis; 431552f7358SJed Brown 432552f7358SJed Brown PetscFunctionBegin; 4339566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 43428b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 4359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 4369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 4379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 4389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 439684b87d9SLisandro Dalcin if (isvtk || ishdf5 || isdraw || isglvis) { 440684b87d9SLisandro Dalcin PetscInt i,numFields; 441684b87d9SLisandro Dalcin PetscObject fe; 442ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 443684b87d9SLisandro Dalcin Vec locv = v; 444684b87d9SLisandro Dalcin const char *name; 445684b87d9SLisandro Dalcin PetscInt step; 446684b87d9SLisandro Dalcin PetscReal time; 447ef31f671SMatthew G. Knepley 4489566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 449684b87d9SLisandro Dalcin for (i=0; i<numFields; i++) { 4509566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 451684b87d9SLisandro Dalcin if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 452ef31f671SMatthew G. Knepley } 453684b87d9SLisandro Dalcin if (fem) { 454798534f6SMatthew G. Knepley PetscObject isZero; 455798534f6SMatthew G. Knepley 4569566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 4579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 4589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) locv, name)); 4599566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero)); 4609566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero)); 4619566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 4629566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 4639566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 464ef31f671SMatthew G. Knepley } 465552f7358SJed Brown if (isvtk) { 4669566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 467b136c2c9SMatthew G. Knepley } else if (ishdf5) { 468b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 4699566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 470b136c2c9SMatthew G. Knepley #else 471b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 472b136c2c9SMatthew G. Knepley #endif 473f13a32a3SMatthew G. Knepley } else if (isdraw) { 4749566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 475684b87d9SLisandro Dalcin } else if (isglvis) { 4769566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 4779566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 4789566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 479684b87d9SLisandro Dalcin } 480798534f6SMatthew G. Knepley if (fem) { 4819566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL)); 4829566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 483798534f6SMatthew G. Knepley } 484552f7358SJed Brown } else { 485684b87d9SLisandro Dalcin PetscBool isseq; 486684b87d9SLisandro Dalcin 4879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 4889566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 4899566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 490552f7358SJed Brown } 491552f7358SJed Brown PetscFunctionReturn(0); 492552f7358SJed Brown } 493552f7358SJed Brown 494552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 495552f7358SJed Brown { 496552f7358SJed Brown DM dm; 4976823f3c5SBlaise Bourdin PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 498552f7358SJed Brown 499552f7358SJed Brown PetscFunctionBegin; 5009566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 50128b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 5039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 5049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 5059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 5069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii)); 507684b87d9SLisandro Dalcin if (isvtk || isdraw || isglvis) { 508552f7358SJed Brown Vec locv; 509798534f6SMatthew G. Knepley PetscObject isZero; 510552f7358SJed Brown const char *name; 511552f7358SJed Brown 5129566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 5149566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) locv, name)); 5159566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 5169566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 5179566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero)); 5189566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero)); 5199566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 5209566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL)); 5219566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 522b136c2c9SMatthew G. Knepley } else if (ishdf5) { 523b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5249566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 525b136c2c9SMatthew G. Knepley #else 526b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 527b136c2c9SMatthew G. Knepley #endif 5286823f3c5SBlaise Bourdin } else if (isexodusii) { 5296823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 5309566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 5316823f3c5SBlaise Bourdin #else 5326823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 5336823f3c5SBlaise Bourdin #endif 534552f7358SJed Brown } else { 535684b87d9SLisandro Dalcin PetscBool isseq; 536684b87d9SLisandro Dalcin 5379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 5389566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5399566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 540552f7358SJed Brown } 541552f7358SJed Brown PetscFunctionReturn(0); 542552f7358SJed Brown } 543552f7358SJed Brown 544d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 545d930f514SMatthew G. Knepley { 546d930f514SMatthew G. Knepley DM dm; 547d930f514SMatthew G. Knepley MPI_Comm comm; 548d930f514SMatthew G. Knepley PetscViewerFormat format; 549d930f514SMatthew G. Knepley Vec v; 550d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 551d930f514SMatthew G. Knepley 552d930f514SMatthew G. Knepley PetscFunctionBegin; 5539566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 5549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) originalv, &comm)); 55528b400f6SJacob Faibussowitsch PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5569566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 559d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 560a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 561a8ad634aSStefano Zampini /* this need a better fix */ 562a8ad634aSStefano Zampini if (dm->useNatural) { 563a8ad634aSStefano Zampini if (dm->sfNatural) { 564d930f514SMatthew G. Knepley const char *vecname; 565d930f514SMatthew G. Knepley PetscInt n, nroots; 566d930f514SMatthew G. Knepley 5679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 5689566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 569d930f514SMatthew G. Knepley if (n == nroots) { 5709566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 5719566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 5729566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 5739566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname)); 5749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) v, vecname)); 575d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 576d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 577a8ad634aSStefano Zampini } else v = originalv; 578a8ad634aSStefano Zampini } else v = originalv; 579a8ad634aSStefano Zampini 580d930f514SMatthew G. Knepley if (ishdf5) { 581d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5829566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 583d930f514SMatthew G. Knepley #else 584d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 585d930f514SMatthew G. Knepley #endif 586d930f514SMatthew G. Knepley } else if (isvtk) { 587d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 588d930f514SMatthew G. Knepley } else { 589d930f514SMatthew G. Knepley PetscBool isseq; 590d930f514SMatthew G. Knepley 5919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 5929566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 5939566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 594d930f514SMatthew G. Knepley } 5959566063dSJacob Faibussowitsch if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v)); 596d930f514SMatthew G. Knepley PetscFunctionReturn(0); 597d930f514SMatthew G. Knepley } 598d930f514SMatthew G. Knepley 5992c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 6002c40f234SMatthew G. Knepley { 6012c40f234SMatthew G. Knepley DM dm; 6022c40f234SMatthew G. Knepley PetscBool ishdf5; 6032c40f234SMatthew G. Knepley 6042c40f234SMatthew G. Knepley PetscFunctionBegin; 6059566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 60628b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 6082c40f234SMatthew G. Knepley if (ishdf5) { 6092c40f234SMatthew G. Knepley DM dmBC; 6102c40f234SMatthew G. Knepley Vec gv; 6112c40f234SMatthew G. Knepley const char *name; 6122c40f234SMatthew G. Knepley 6139566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 6149566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 6159566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) v, &name)); 6169566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) gv, name)); 6179566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 6189566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 6199566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 6209566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 6211baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 6222c40f234SMatthew G. Knepley PetscFunctionReturn(0); 6232c40f234SMatthew G. Knepley } 6242c40f234SMatthew G. Knepley 6252c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 6262c40f234SMatthew G. Knepley { 6272c40f234SMatthew G. Knepley DM dm; 6286823f3c5SBlaise Bourdin PetscBool ishdf5,isexodusii; 6292c40f234SMatthew G. Knepley 6302c40f234SMatthew G. Knepley PetscFunctionBegin; 6319566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63228b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 6349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6352c40f234SMatthew G. Knepley if (ishdf5) { 636878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6379566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 638b136c2c9SMatthew G. Knepley #else 639b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 640878b459fSMatthew G. Knepley #endif 6416823f3c5SBlaise Bourdin } else if (isexodusii) { 6426823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6439566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 6446823f3c5SBlaise Bourdin #else 6456823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6466823f3c5SBlaise Bourdin #endif 6471baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 648552f7358SJed Brown PetscFunctionReturn(0); 649552f7358SJed Brown } 650552f7358SJed Brown 651d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 652d930f514SMatthew G. Knepley { 653d930f514SMatthew G. Knepley DM dm; 654d930f514SMatthew G. Knepley PetscViewerFormat format; 655d930f514SMatthew G. Knepley PetscBool ishdf5; 656d930f514SMatthew G. Knepley 657d930f514SMatthew G. Knepley PetscFunctionBegin; 6589566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 65928b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6609566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 662d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 663a8ad634aSStefano Zampini if (dm->useNatural) { 664d930f514SMatthew G. Knepley if (dm->sfNatural) { 665d930f514SMatthew G. Knepley if (ishdf5) { 666d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 667d930f514SMatthew G. Knepley Vec v; 668d930f514SMatthew G. Knepley const char *vecname; 669d930f514SMatthew G. Knepley 6709566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 6719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname)); 6729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) v, vecname)); 6739566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 6749566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 6759566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 6769566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dm, &v)); 677d930f514SMatthew G. Knepley #else 678d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 679d930f514SMatthew G. Knepley #endif 680d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 681d930f514SMatthew G. Knepley } 6821baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 683d930f514SMatthew G. Knepley } 684d930f514SMatthew G. Knepley PetscFunctionReturn(0); 685d930f514SMatthew G. Knepley } 686d930f514SMatthew G. Knepley 6877cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 688731e8ddeSMatthew G. Knepley { 689731e8ddeSMatthew G. Knepley PetscSection coordSection; 690731e8ddeSMatthew G. Knepley Vec coordinates; 691ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 692731e8ddeSMatthew G. Knepley const char *name[4]; 693731e8ddeSMatthew G. Knepley const PetscScalar *a; 694731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 695731e8ddeSMatthew G. Knepley 696731e8ddeSMatthew G. Knepley PetscFunctionBegin; 6979566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 6989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 6999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 7019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 7029566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 7039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 7049566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 705731e8ddeSMatthew G. Knepley name[0] = "vertex"; 706731e8ddeSMatthew G. Knepley name[1] = "edge"; 707731e8ddeSMatthew G. Knepley name[dim-1] = "face"; 708731e8ddeSMatthew G. Knepley name[dim] = "cell"; 709731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 710731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 711ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 712731e8ddeSMatthew G. Knepley 7139566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 71463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 7159566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 717731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 718731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 719731e8ddeSMatthew G. Knepley 720731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 7219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 722731e8ddeSMatthew G. Knepley if (!dof) continue; 7239566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 7249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 72563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 726731e8ddeSMatthew G. Knepley for (p = 0; p < dof/dim; ++p) { 7279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 728731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 7299566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 7309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]))); 731731e8ddeSMatthew G. Knepley } 7329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 733731e8ddeSMatthew G. Knepley } 7349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 735731e8ddeSMatthew G. Knepley } 7369566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 738731e8ddeSMatthew G. Knepley } 7399566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 740731e8ddeSMatthew G. Knepley PetscFunctionReturn(0); 741731e8ddeSMatthew G. Knepley } 742731e8ddeSMatthew G. Knepley 74319ad8254SMatthew G. Knepley typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem; 74419ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 74519ad8254SMatthew G. Knepley 74619ad8254SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 74719ad8254SMatthew G. Knepley { 74819ad8254SMatthew G. Knepley PetscInt i; 74919ad8254SMatthew G. Knepley 75019ad8254SMatthew G. Knepley PetscFunctionBegin; 75119ad8254SMatthew G. Knepley if (dim > 3) { 7529566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]))); 75319ad8254SMatthew G. Knepley } else { 754bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 75519ad8254SMatthew G. Knepley 75619ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 75719ad8254SMatthew G. Knepley switch (cs) { 75819ad8254SMatthew G. Knepley case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break; 75919ad8254SMatthew G. Knepley case CS_POLAR: 76063a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 76119ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 76219ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 76319ad8254SMatthew G. Knepley break; 76419ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 76563a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 76619ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 76719ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 76819ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 76919ad8254SMatthew G. Knepley break; 77019ad8254SMatthew G. Knepley case CS_SPHERICAL: 77163a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 77219ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 77319ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 77419ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 77519ad8254SMatthew G. Knepley break; 77619ad8254SMatthew G. Knepley } 7779566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i])); 77819ad8254SMatthew G. Knepley } 77919ad8254SMatthew G. Knepley PetscFunctionReturn(0); 78019ad8254SMatthew G. Knepley } 78119ad8254SMatthew G. Knepley 7827cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 783552f7358SJed Brown { 784552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 785*6858538eSMatthew G. Knepley DM cdm, cdmCell; 786*6858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 787*6858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 788552f7358SJed Brown PetscViewerFormat format; 789552f7358SJed Brown 790552f7358SJed Brown PetscFunctionBegin; 7919566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 792*6858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 794*6858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 795*6858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 796*6858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 7979566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 798552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 799552f7358SJed Brown const char *name; 800f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 8019318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 802552f7358SJed Brown PetscMPIInt rank, size; 803552f7358SJed Brown 8049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 8069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 8079566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8089566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 8099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8109566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 81163a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 81263a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 81363a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 81463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 8159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 81663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 817552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 818552f7358SJed Brown PetscInt dof, off, s; 819552f7358SJed Brown 8209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 822552f7358SJed Brown for (s = off; s < off+dof; ++s) { 82363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 824552f7358SJed Brown } 825552f7358SJed Brown } 8269566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 82763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 82863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 829552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 830552f7358SJed Brown PetscInt dof, off, c; 831552f7358SJed Brown 8329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 8339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 834552f7358SJed Brown for (c = off; c < off+dof; ++c) { 83563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c])); 836552f7358SJed Brown } 837552f7358SJed Brown } 8389566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8403d2e540fSStefano Zampini if (coordSection && coordinates) { 84119ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 842*6858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 843*6858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 84419ad8254SMatthew G. Knepley PetscMPIInt rank; 84519ad8254SMatthew G. Knepley const char *name; 84619ad8254SMatthew G. Knepley 8479566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL)); 8489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 8499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 85063a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 8519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 852*6858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 853*6858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 854*6858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 855*6858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 8569566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) coordinates, &name)); 85763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 85863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 8599566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 86019ad8254SMatthew G. Knepley 8619566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 862*6858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 8639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 8649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 86519ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 86619ad8254SMatthew G. Knepley PetscInt dof, off; 86719ad8254SMatthew G. Knepley 868*6858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 8699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 8709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 871*6858538eSMatthew G. Knepley if (dof) { 87263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 8739566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 8749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 87519ad8254SMatthew G. Knepley } 876*6858538eSMatthew G. Knepley } 877*6858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 878*6858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 879*6858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 880*6858538eSMatthew G. Knepley if (dof) { 881*6858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 882*6858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 883*6858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 884*6858538eSMatthew G. Knepley } 885*6858538eSMatthew G. Knepley } 886*6858538eSMatthew G. Knepley } 8879566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8899566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 890*6858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 8913d2e540fSStefano Zampini } 8929566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 8939566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 8949318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 8959318fe57SMatthew G. Knepley DMLabel label; 8969318fe57SMatthew G. Knepley PetscBool isdepth; 8979318fe57SMatthew G. Knepley const char *name; 8989318fe57SMatthew G. Knepley 8999566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 9009566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 9019318fe57SMatthew G. Knepley if (isdepth) continue; 9029566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 9039566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 9049318fe57SMatthew G. Knepley } 905552f7358SJed Brown if (size > 1) { 906552f7358SJed Brown PetscSF sf; 907552f7358SJed Brown 9089566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9099566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 910552f7358SJed Brown } 9119566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 912552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 9130588280cSMatthew G. Knepley const char *name, *color; 9140588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 9150588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 916fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 917552f7358SJed Brown PetscReal scale = 2.0; 91878081901SStefano Zampini PetscReal tikzscale = 1.0; 919b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 9200588280cSMatthew G. Knepley double tcoords[3]; 921552f7358SJed Brown PetscScalar *coords; 922b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 923552f7358SJed Brown PetscMPIInt rank, size; 9240588280cSMatthew G. Knepley char **names, **colors, **lcolors; 925b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 926fe1cc32dSStefano Zampini PetscBT wp = NULL; 927fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 928552f7358SJed Brown 9299566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9319566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 9320588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 9330588280cSMatthew G. Knepley numColors = 10; 9340588280cSMatthew G. Knepley numLColors = 10; 9359566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 9369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 9379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 9389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 939b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 940b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 941b7f6ffafSMatthew G. Knepley n = 4; 9429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 9431dca8a05SBarry 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); 9449566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 9451dca8a05SBarry 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); 9469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 9470588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 9489566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 9490588280cSMatthew G. Knepley if (!useColors) { 9500588280cSMatthew G. Knepley numColors = 3; 9519566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 9520588280cSMatthew G. Knepley } 9539566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 9540588280cSMatthew G. Knepley if (!useColors) { 9550588280cSMatthew G. Knepley numLColors = 4; 9569566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 9570588280cSMatthew G. Knepley } 9589566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 959b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 9609566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 9611dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 962202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 9639566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 964fe1cc32dSStefano Zampini 965fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 9669566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 970fe1cc32dSStefano Zampini if (lflg) { 971fe1cc32dSStefano Zampini DMLabel lbl; 972fe1cc32dSStefano Zampini 9739566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 974fe1cc32dSStefano Zampini if (lbl) { 975fe1cc32dSStefano Zampini PetscInt val, defval; 976fe1cc32dSStefano Zampini 9779566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 9789566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd-pStart, &wp)); 979fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 980fe1cc32dSStefano Zampini PetscInt *closure = NULL; 981fe1cc32dSStefano Zampini PetscInt closureSize; 982fe1cc32dSStefano Zampini 9839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 984fe1cc32dSStefano Zampini if (val == defval) continue; 985fe1cc32dSStefano Zampini 9869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 987fe1cc32dSStefano Zampini for (p = 0; p < closureSize*2; p += 2) { 9889566063dSJacob Faibussowitsch PetscCall(PetscBTSet(wp, closure[p] - pStart)); 989fe1cc32dSStefano Zampini } 9909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 991fe1cc32dSStefano Zampini } 992fe1cc32dSStefano Zampini } 993fe1cc32dSStefano Zampini } 994fe1cc32dSStefano Zampini 9959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 9989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 9990588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1000552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1001552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1002552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 10035f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 10040588280cSMatthew G. Knepley if (size > 1) { 10059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1006770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 100763a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size-1) ? ", and " : ", ")); 100863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p%numColors], p)); 1009770b213bSMatthew G Knepley } 10109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 10110588280cSMatthew G. Knepley } 1012b7f6ffafSMatthew G. Knepley if (drawHasse) { 1013b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 1014b7f6ffafSMatthew G. Knepley 101563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 101663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd-1)); 101763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd-vStart)); 10189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.)); 101963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 102063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd-1)); 10219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.)); 102263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd-eStart)); 102363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 102463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd-1)); 102563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd-cStart)); 10269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.)); 1027b7f6ffafSMatthew G. Knepley } 10289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale)); 1029fe1cc32dSStefano Zampini 1030552f7358SJed Brown /* Plot vertices */ 10319566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1033552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1034552f7358SJed Brown PetscInt off, dof, d; 10350588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1036552f7358SJed Brown 1037fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,v - pStart)) continue; 10389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 10399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 10409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 104163a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3",v,dof); 10420588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10430588280cSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1044c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 10450588280cSMatthew G. Knepley } 10460588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 10470588280cSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1048552f7358SJed Brown for (d = 0; d < dof; ++d) { 10499566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d])); 1051552f7358SJed Brown } 1052b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0%numColors]; 1053b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 10540588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10550588280cSMatthew G. Knepley PetscInt val; 10569566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 10570588280cSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 10580588280cSMatthew G. Knepley } 1059b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 106063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1061b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 106263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 10631baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1064552f7358SJed Brown } 10659566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 10669566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1067b7f6ffafSMatthew G. Knepley /* Plot edges */ 1068b7f6ffafSMatthew G. Knepley if (plotEdges) { 10699566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1071b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1072b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1073b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1074b7f6ffafSMatthew G. Knepley 1075b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp,e - pStart)) continue; 10769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 107763a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 10789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 10799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 10809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 10819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 10829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1083b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1084b7f6ffafSMatthew G. Knepley tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 1085b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1086b7f6ffafSMatthew G. Knepley } 1087b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1088b7f6ffafSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1089b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10909566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1092b7f6ffafSMatthew G. Knepley } 1093b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1%numColors]; 1094b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 1095b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1096b7f6ffafSMatthew G. Knepley PetscInt val; 10979566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 1098b7f6ffafSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 1099b7f6ffafSMatthew G. Knepley } 110063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1101b7f6ffafSMatthew G. Knepley } 11029566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 11039566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 11049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1105b7f6ffafSMatthew G. Knepley } 1106846a3e8bSMatthew G. Knepley /* Plot cells */ 1107b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1108846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1109846a3e8bSMatthew G. Knepley const PetscInt *cone; 1110846a3e8bSMatthew G. Knepley 1111fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1112846a3e8bSMatthew G. Knepley color = colors[rank%numColors]; 1113846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1114846a3e8bSMatthew G. Knepley PetscInt val; 11159566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 1116846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 1117846a3e8bSMatthew G. Knepley } 11189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 111963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1120846a3e8bSMatthew G. Knepley } 1121846a3e8bSMatthew G. Knepley } else { 1122b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1123846a3e8bSMatthew G. Knepley 1124b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1125b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1126fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 11279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1128b7f6ffafSMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1129b7f6ffafSMatthew G. Knepley ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1130b7f6ffafSMatthew G. Knepley ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1131b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1132b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1133b7f6ffafSMatthew G. Knepley 11349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 11359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1136b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1137b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1138b7f6ffafSMatthew G. Knepley 11399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 114063a3b9bcSJacob 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)); 1141b7f6ffafSMatthew G. Knepley } 1142b7f6ffafSMatthew G. Knepley } else { 1143b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1144b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1145b7f6ffafSMatthew G. Knepley 11469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1147846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 1148846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1149846a3e8bSMatthew G. Knepley 1150b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1151846a3e8bSMatthew G. Knepley } 11529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors])); 1153b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1154b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v%Nv]; 1155b7f6ffafSMatthew G. Knepley 1156b7f6ffafSMatthew G. Knepley if (v > 0) { 1157b7f6ffafSMatthew G. Knepley if (plotEdges) { 1158b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1159b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1160b7f6ffafSMatthew G. Knepley 1161b7f6ffafSMatthew G. Knepley endpoints[0] = closure[v-1]; endpoints[1] = vertex; 11629566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 116363a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 116463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 11659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 11661baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1167b7f6ffafSMatthew G. Knepley } 116863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1169b7f6ffafSMatthew G. Knepley } 11709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 11719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1172846a3e8bSMatthew G. Knepley } 1173846a3e8bSMatthew G. Knepley } 1174b7f6ffafSMatthew G. Knepley } 11759566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1176846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1177846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1178846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1179846a3e8bSMatthew G. Knepley PetscInt *closure = NULL; 1180846a3e8bSMatthew G. Knepley PetscInt closureSize, dof, d, n = 0; 1181846a3e8bSMatthew G. Knepley 1182fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,c - pStart)) continue; 11839566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 11849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1185846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 1186846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1187846a3e8bSMatthew G. Knepley PetscInt off; 1188846a3e8bSMatthew G. Knepley 1189846a3e8bSMatthew G. Knepley if ((point < vStart) || (point >= vEnd)) continue; 11909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 11919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 1192846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1193846a3e8bSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1194846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1195846a3e8bSMatthew G. Knepley } 1196846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1197846a3e8bSMatthew G. Knepley if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1198846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1199846a3e8bSMatthew G. Knepley ++n; 1200846a3e8bSMatthew G. Knepley } 1201846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 12029566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1203846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12049566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d])); 1206846a3e8bSMatthew G. Knepley } 1207b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth%numColors]; 1208b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 1209846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1210846a3e8bSMatthew G. Knepley PetscInt val; 12119566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 1212846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1213846a3e8bSMatthew G. Knepley } 1214b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 121563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1216b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 121763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 12181baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1219846a3e8bSMatthew G. Knepley } 12209566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 1221b7f6ffafSMatthew G. Knepley if (drawHasse) { 1222b7f6ffafSMatthew G. Knepley color = colors[depth%numColors]; 12239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 12249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 12259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 12279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1228552f7358SJed Brown 1229b7f6ffafSMatthew G. Knepley color = colors[1%numColors]; 12309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 12319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 12329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 12349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1235b7f6ffafSMatthew G. Knepley 1236b7f6ffafSMatthew G. Knepley color = colors[0%numColors]; 12379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 12389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 12399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 12419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1242b7f6ffafSMatthew G. Knepley 1243b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1244b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1245b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1246b7f6ffafSMatthew G. Knepley 12479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 12489566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1249b7f6ffafSMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 125063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank)); 1251552f7358SJed Brown } 12520588280cSMatthew G. Knepley } 12530588280cSMatthew G. Knepley } 12549566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 12569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 125763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 12589566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 12599566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 12609566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 12619566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 12629566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 12630f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 12640f7d6e4aSStefano Zampini Vec cown,acown; 12650f7d6e4aSStefano Zampini VecScatter sct; 12660f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 12670f7d6e4aSStefano Zampini IS gid,acis; 12680f7d6e4aSStefano Zampini MPI_Comm comm,ncomm = MPI_COMM_NULL; 12690f7d6e4aSStefano Zampini MPI_Group ggroup,ngroup; 12700f7d6e4aSStefano Zampini PetscScalar *array,nid; 12710f7d6e4aSStefano Zampini const PetscInt *idxs; 12720f7d6e4aSStefano Zampini PetscInt *idxs2,*start,*adjacency,*work; 12730f7d6e4aSStefano Zampini PetscInt64 lm[3],gm[3]; 12740f7d6e4aSStefano Zampini PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 12750f7d6e4aSStefano Zampini PetscMPIInt d1,d2,rank; 12760f7d6e4aSStefano Zampini 12779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm,&comm)); 12789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 1279b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 12809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm)); 12810f7d6e4aSStefano Zampini #endif 12820f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 12839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm,&ggroup)); 12849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm,&ngroup)); 12850f7d6e4aSStefano Zampini d1 = 0; 12869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2)); 12870f7d6e4aSStefano Zampini nid = d2; 12889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 12899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 12909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 12910f7d6e4aSStefano Zampini } else nid = 0.0; 12920f7d6e4aSStefano Zampini 12930f7d6e4aSStefano Zampini /* Get connectivity */ 12949566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm,&cellHeight)); 12959566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid)); 12960f7d6e4aSStefano Zampini 12970f7d6e4aSStefano Zampini /* filter overlapped local cells */ 12989566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd)); 12999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid,&idxs)); 13009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid,&cum)); 13019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum,&idxs2)); 13020f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 13030f7d6e4aSStefano Zampini if (idxs[c-cStart] < 0) continue; 13040f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c-cStart]; 13050f7d6e4aSStefano Zampini } 13069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid,&idxs)); 130763a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,numVertices,cum); 13089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13099566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid)); 13100f7d6e4aSStefano Zampini 13110f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 13129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis)); 13139566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown)); 13149566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown)); 13159566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown,&array)); 13160f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 13179566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown,&array)); 13189566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown,acis,acown,NULL,&sct)); 13199566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD)); 13209566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD)); 13219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 13229566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 13239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 13240f7d6e4aSStefano Zampini 13250f7d6e4aSStefano Zampini /* compute edgeCut */ 13260f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 13279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum,&work)); 13289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid,&g2l)); 13299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH)); 13309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13319566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown,&array)); 13320f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 13330f7d6e4aSStefano Zampini PetscInt totl; 13340f7d6e4aSStefano Zampini 13350f7d6e4aSStefano Zampini totl = start[c+1]-start[c]; 13369566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work)); 13370f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 13380f7d6e4aSStefano Zampini if (work[i] < 0) { 13390f7d6e4aSStefano Zampini ect += 1; 13400f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 13410f7d6e4aSStefano Zampini } 13420f7d6e4aSStefano Zampini } 13430f7d6e4aSStefano Zampini } 13449566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 13459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown,&array)); 13460f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 13470f7d6e4aSStefano Zampini lm[1] = -numVertices; 13481c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm)); 134963a3b9bcSJacob 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])); 13500f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 13510f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 13520f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 13531c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm)); 135463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,", empty %" PetscInt_FMT ")\n",(PetscInt)gm[2])); 1355b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 135663a3b9bcSJacob 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.)); 13570f7d6e4aSStefano Zampini #else 135863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Edge Cut: %" PetscInt_FMT " (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0)); 13590f7d6e4aSStefano Zampini #endif 13609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 13619566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 13629566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 13639566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1364552f7358SJed Brown } else { 1365412e9a14SMatthew G. Knepley const char *name; 1366d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1367412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1368d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1369ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 13709318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1371412e9a14SMatthew G. Knepley MPI_Comm comm; 1372412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1373552f7358SJed Brown 13749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 13759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 13769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 13779566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13789566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 13799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 138063a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 138163a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 138263a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 13839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 13841c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 13859566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd)); 1386d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 13879566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 13889566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1389412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1390412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1391412e9a14SMatthew G. Knepley 13929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 13939566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1394412e9a14SMatthew G. Knepley ict = ct0; 13959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1396412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType) ict; 1397412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1398412e9a14SMatthew G. Knepley DMPolytopeType ct; 1399412e9a14SMatthew G. Knepley 14009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1401412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1402412e9a14SMatthew G. Knepley else ++Nc[1]; 1403412e9a14SMatthew G. Knepley } 1404ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 14059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 14069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 14079566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 140863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1409834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1410dd400576SPatrick Sanan if (rank == 0) { 141163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]+hybsizes[p])); 141263a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 141363a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1414834065abSMatthew G. Knepley } 1415cbb7f117SMark Adams } 1416ca7bf7eeSMatthew G. Knepley } else { 1417ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1418ca7bf7eeSMatthew G. Knepley 1419ca7bf7eeSMatthew G. Knepley locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1]; 14209566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 1421ca7bf7eeSMatthew G. Knepley locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1]; 14229566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1423ca7bf7eeSMatthew G. Knepley if (d == depth) { 1424ca7bf7eeSMatthew G. Knepley locMinMax[0] = gcNum; locMinMax[1] = gcNum; 14259566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1426ca7bf7eeSMatthew G. Knepley } 142763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 14289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 14299566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 14309566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1431ca7bf7eeSMatthew G. Knepley } 14329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1433552f7358SJed Brown } 14349566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 14359318fe57SMatthew G. Knepley { 14369318fe57SMatthew G. Knepley const PetscReal *maxCell; 14379318fe57SMatthew G. Knepley const PetscReal *L; 1438*6858538eSMatthew G. Knepley PetscBool localized; 14399318fe57SMatthew G. Knepley 1440*6858538eSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &L)); 14419566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 1442*6858538eSMatthew G. Knepley if (L || localized) { 1443*6858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 14449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1445*6858538eSMatthew G. Knepley if (L) { 1446*6858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 14479318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 1448*6858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 1449*6858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 14509318fe57SMatthew G. Knepley } 1451*6858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 1452*6858538eSMatthew G. Knepley } 1453*6858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 14549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14559318fe57SMatthew G. Knepley } 14569318fe57SMatthew G. Knepley } 14579566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 14589566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1459a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1460a57dd577SMatthew G Knepley DMLabel label; 1461a57dd577SMatthew G Knepley const char *name; 1462a57dd577SMatthew G Knepley IS valueIS; 1463a57dd577SMatthew G Knepley const PetscInt *values; 1464a57dd577SMatthew G Knepley PetscInt numValues, v; 1465a57dd577SMatthew G Knepley 14669566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 14679566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 14689566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 146963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 14709566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 14719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 14729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1473a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1474a57dd577SMatthew G Knepley PetscInt size; 1475a57dd577SMatthew G Knepley 14769566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 14779566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 147863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1479a57dd577SMatthew G Knepley } 14809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 14819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14829566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 14839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1484a57dd577SMatthew G Knepley } 1485c1cad2e7SMatthew G. Knepley { 1486c1cad2e7SMatthew G. Knepley char **labelNames; 1487c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1488c1cad2e7SMatthew G. Knepley PetscBool flg; 1489c1cad2e7SMatthew G. Knepley 14909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 14919566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1492c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1493c1cad2e7SMatthew G. Knepley DMLabel label; 1494c1cad2e7SMatthew G. Knepley 14959566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1496c1cad2e7SMatthew G. Knepley if (flg) { 14979566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 14989566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1499c1cad2e7SMatthew G. Knepley } 15009566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1501c1cad2e7SMatthew G. Knepley } 15029566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1503c1cad2e7SMatthew G. Knepley } 150434aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 150534aa8a36SMatthew G. Knepley if (dm->Nf) { 150634aa8a36SMatthew G. Knepley PetscInt f; 150734aa8a36SMatthew G. Knepley 150834aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 150934aa8a36SMatthew G. Knepley const char *name; 151034aa8a36SMatthew G. Knepley 15119566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 15129566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 15139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15149566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 151534aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 15169566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 15179566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 151834aa8a36SMatthew G. Knepley } else { 15199566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 15209566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 152134aa8a36SMatthew G. Knepley } 15229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 152334aa8a36SMatthew G. Knepley } 152434aa8a36SMatthew G. Knepley } 15259566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 15268e7ff633SMatthew G. Knepley if (cdm) { 15279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15289566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 15299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 15308e7ff633SMatthew G. Knepley } 1531552f7358SJed Brown } 1532552f7358SJed Brown PetscFunctionReturn(0); 1533552f7358SJed Brown } 1534552f7358SJed Brown 1535e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1536e5c487bfSMatthew G. Knepley { 1537e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1538e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1539a12d352dSMatthew G. Knepley PetscInt cdim; 1540e5c487bfSMatthew G. Knepley 1541e5c487bfSMatthew G. Knepley PetscFunctionBegin; 15429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 15439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 15449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1545e5c487bfSMatthew G. Knepley switch (ct) { 1546a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1547a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1548a12d352dSMatthew G. Knepley switch (cdim) { 1549a12d352dSMatthew G. Knepley case 1: 1550a12d352dSMatthew G. Knepley { 1551a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1552a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1553a12d352dSMatthew G. Knepley 15549566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 15559566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK)); 15569566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK)); 1557a12d352dSMatthew G. Knepley } 1558a12d352dSMatthew G. Knepley break; 1559a12d352dSMatthew G. Knepley case 2: 1560a12d352dSMatthew G. Knepley { 1561a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1562a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1563a12d352dSMatthew G. Knepley const PetscReal l = 0.1/PetscSqrtReal(dx*dx + dy*dy); 1564a12d352dSMatthew G. Knepley 15659566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15669566063dSJacob 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)); 15679566063dSJacob 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)); 1568a12d352dSMatthew G. Knepley } 1569a12d352dSMatthew G. Knepley break; 157063a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1571a12d352dSMatthew G. Knepley } 1572a12d352dSMatthew G. Knepley break; 1573e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 15749566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1575e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1576e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15775f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15789566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15799566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15809566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1581e5c487bfSMatthew G. Knepley break; 1582e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 15839566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1584e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1585e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15865f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15879566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1588e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1589e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15905f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15919566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15929566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15939566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 15949566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1595e5c487bfSMatthew G. Knepley break; 159698921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1597e5c487bfSMatthew G. Knepley } 1598e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1599e5c487bfSMatthew G. Knepley } 1600e5c487bfSMatthew G. Knepley 1601e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1602e5c487bfSMatthew G. Knepley { 1603e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1604e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1605e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1606e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1607e5c487bfSMatthew G. Knepley 1608e5c487bfSMatthew G. Knepley PetscFunctionBegin; 16099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 16109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1611e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1612e5c487bfSMatthew G. Knepley switch (ct) { 1613e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 1614e5c487bfSMatthew G. Knepley { 1615e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1616e5c487bfSMatthew G. Knepley 1617e5c487bfSMatthew G. Knepley for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1618e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1619e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e*2+0]; 1620e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e*2+1]; 1621e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1622e5c487bfSMatthew G. Knepley refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1623e5c487bfSMatthew G. Knepley refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1624e5c487bfSMatthew G. Knepley } 16259566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords)); 1626e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 16279566063dSJacob 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)); 16289566063dSJacob 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)); 1629e5c487bfSMatthew G. Knepley } 1630e5c487bfSMatthew G. Knepley } 1631e5c487bfSMatthew G. Knepley } 1632e5c487bfSMatthew G. Knepley break; 163398921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1634e5c487bfSMatthew G. Knepley } 1635e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1636e5c487bfSMatthew G. Knepley } 1637e5c487bfSMatthew G. Knepley 16387cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1639e412dcbdSMatthew G. Knepley { 1640e412dcbdSMatthew G. Knepley PetscDraw draw; 1641e412dcbdSMatthew G. Knepley DM cdm; 1642e412dcbdSMatthew G. Knepley PetscSection coordSection; 1643e412dcbdSMatthew G. Knepley Vec coordinates; 1644e412dcbdSMatthew G. Knepley const PetscScalar *coords; 164529494db1SLisandro Dalcin PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1646e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1647e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1648e5c487bfSMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1649e412dcbdSMatthew G. Knepley 1650e412dcbdSMatthew G. Knepley PetscFunctionBegin; 16519566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 165263a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 16539566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 16549566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords)); 16559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 16569566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 16579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 16589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 16599566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1660e412dcbdSMatthew G. Knepley 16619566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 16629566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 1663e412dcbdSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 16649566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1665e412dcbdSMatthew G. Knepley 16669566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 16679566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 1668e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 16690c81f2a8SMatthew G. Knepley bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 16700c81f2a8SMatthew G. Knepley bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1671e412dcbdSMatthew G. Knepley } 16729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 16731c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm))); 16741c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm))); 16759566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 16769566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1677e412dcbdSMatthew G. Knepley 1678cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1679cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1680ba2698f1SMatthew G. Knepley PetscInt numCoords; 1681cf3064d3SMatthew G. Knepley 16829566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords)); 16831baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 16841baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 16859566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 1686cf3064d3SMatthew G. Knepley } 16879566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 16889566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 16899566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 16909566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 1691e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 1692e412dcbdSMatthew G. Knepley } 1693e412dcbdSMatthew G. Knepley 16941e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 16951e50132fSMatthew G. Knepley #include <exodusII.h> 16966823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 16971e50132fSMatthew G. Knepley #endif 16981e50132fSMatthew G. Knepley 1699552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1700552f7358SJed Brown { 17011e50132fSMatthew G. Knepley PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1702002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1703552f7358SJed Brown 1704552f7358SJed Brown PetscFunctionBegin; 1705552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1706552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii)); 17089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 17099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 17109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 17119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 17129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus)); 1713552f7358SJed Brown if (iascii) { 17148135c375SStefano Zampini PetscViewerFormat format; 17159566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 17161baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 17171baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1718c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1719c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 17209566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1721c6ccd67eSMatthew G. Knepley #else 1722c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1723552f7358SJed Brown #endif 1724e412dcbdSMatthew G. Knepley } else if (isvtk) { 17259566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject) dm,viewer)); 1726e412dcbdSMatthew G. Knepley } else if (isdraw) { 17279566063dSJacob Faibussowitsch PetscCall(DMPlexView_Draw(dm, viewer)); 17288135c375SStefano Zampini } else if (isglvis) { 17299566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 17301e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17311e50132fSMatthew G. Knepley } else if (isexodus) { 17326823f3c5SBlaise Bourdin /* 17336823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 17346823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 17356823f3c5SBlaise Bourdin with ID 1, containig all cells. 17366823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 17376823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 17386823f3c5SBlaise Bourdin */ 17396823f3c5SBlaise Bourdin PetscInt numCS; 17409566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm,"Cell Sets",&numCS)); 17416823f3c5SBlaise Bourdin if (!numCS) { 17421e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 17439566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 17449566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 17459566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 17466823f3c5SBlaise Bourdin } 17479566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 17481e50132fSMatthew G. Knepley #endif 17491baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 17501baa6e33SBarry Smith 1751cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 17529566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg)); 1753cb3ba0daSMatthew G. Knepley if (flg) { 1754cb3ba0daSMatthew G. Knepley Vec ranks; 17559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 17569566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 17579566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1758cb3ba0daSMatthew G. Knepley } 1759002a2709SMatthew G. Knepley /* Optionally view a label */ 17609566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1761002a2709SMatthew G. Knepley if (flg) { 1762002a2709SMatthew G. Knepley DMLabel label; 1763002a2709SMatthew G. Knepley Vec val; 1764002a2709SMatthew G. Knepley 17659566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 176628b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 17679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 17689566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 17699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1770002a2709SMatthew G. Knepley } 1771552f7358SJed Brown PetscFunctionReturn(0); 1772552f7358SJed Brown } 1773552f7358SJed Brown 17747f96f51bSksagiyam /*@ 17757f96f51bSksagiyam DMPlexTopologyView - Saves a DMPlex topology into a file 17767f96f51bSksagiyam 17777f96f51bSksagiyam Collective on DM 17787f96f51bSksagiyam 17797f96f51bSksagiyam Input Parameters: 17807f96f51bSksagiyam + dm - The DM whose topology is to be saved 17817f96f51bSksagiyam - viewer - The PetscViewer for saving 17827f96f51bSksagiyam 17837f96f51bSksagiyam Level: advanced 17847f96f51bSksagiyam 1785db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()` 17867f96f51bSksagiyam @*/ 17877f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 17887f96f51bSksagiyam { 17897f96f51bSksagiyam PetscBool ishdf5; 17907f96f51bSksagiyam 17917f96f51bSksagiyam PetscFunctionBegin; 17927f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17937f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 17959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0)); 17967f96f51bSksagiyam if (ishdf5) { 17977f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 17987f96f51bSksagiyam PetscViewerFormat format; 17999566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 18007f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18017f96f51bSksagiyam IS globalPointNumbering; 18027f96f51bSksagiyam 18039566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18049566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 180698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 18077f96f51bSksagiyam #else 18087f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 18097f96f51bSksagiyam #endif 18107f96f51bSksagiyam } 18119566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0)); 18127f96f51bSksagiyam PetscFunctionReturn(0); 18137f96f51bSksagiyam } 18147f96f51bSksagiyam 181577b8e257Sksagiyam /*@ 181677b8e257Sksagiyam DMPlexCoordinatesView - Saves DMPlex coordinates into a file 181777b8e257Sksagiyam 181877b8e257Sksagiyam Collective on DM 181977b8e257Sksagiyam 182077b8e257Sksagiyam Input Parameters: 182177b8e257Sksagiyam + dm - The DM whose coordinates are to be saved 182277b8e257Sksagiyam - viewer - The PetscViewer for saving 182377b8e257Sksagiyam 182477b8e257Sksagiyam Level: advanced 182577b8e257Sksagiyam 1826db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()` 182777b8e257Sksagiyam @*/ 182877b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 182977b8e257Sksagiyam { 183077b8e257Sksagiyam PetscBool ishdf5; 183177b8e257Sksagiyam 183277b8e257Sksagiyam PetscFunctionBegin; 183377b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 183477b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 18369566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0)); 183777b8e257Sksagiyam if (ishdf5) { 183877b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 183977b8e257Sksagiyam PetscViewerFormat format; 18409566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 184177b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18429566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 184398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 184477b8e257Sksagiyam #else 184577b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 184677b8e257Sksagiyam #endif 184777b8e257Sksagiyam } 18489566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0)); 184977b8e257Sksagiyam PetscFunctionReturn(0); 185077b8e257Sksagiyam } 185177b8e257Sksagiyam 1852bd6565f1Sksagiyam /*@ 1853bd6565f1Sksagiyam DMPlexLabelsView - Saves DMPlex labels into a file 1854bd6565f1Sksagiyam 1855bd6565f1Sksagiyam Collective on DM 1856bd6565f1Sksagiyam 1857bd6565f1Sksagiyam Input Parameters: 1858bd6565f1Sksagiyam + dm - The DM whose labels are to be saved 1859bd6565f1Sksagiyam - viewer - The PetscViewer for saving 1860bd6565f1Sksagiyam 1861bd6565f1Sksagiyam Level: advanced 1862bd6565f1Sksagiyam 1863db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()` 1864bd6565f1Sksagiyam @*/ 1865bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1866bd6565f1Sksagiyam { 1867bd6565f1Sksagiyam PetscBool ishdf5; 1868bd6565f1Sksagiyam 1869bd6565f1Sksagiyam PetscFunctionBegin; 1870bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1871bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 18739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0)); 1874bd6565f1Sksagiyam if (ishdf5) { 1875bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 1876bd6565f1Sksagiyam IS globalPointNumbering; 1877bd6565f1Sksagiyam PetscViewerFormat format; 1878bd6565f1Sksagiyam 18799566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 1880bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18819566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18829566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 188498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1885bd6565f1Sksagiyam #else 1886bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1887bd6565f1Sksagiyam #endif 1888bd6565f1Sksagiyam } 18899566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0)); 1890bd6565f1Sksagiyam PetscFunctionReturn(0); 1891bd6565f1Sksagiyam } 1892bd6565f1Sksagiyam 1893021affd3Sksagiyam /*@ 1894021affd3Sksagiyam DMPlexSectionView - Saves a section associated with a DMPlex 1895021affd3Sksagiyam 1896021affd3Sksagiyam Collective on DM 1897021affd3Sksagiyam 1898021affd3Sksagiyam Input Parameters: 1899021affd3Sksagiyam + dm - The DM that contains the topology on which the section to be saved is defined 1900021affd3Sksagiyam . viewer - The PetscViewer for saving 1901021affd3Sksagiyam - sectiondm - The DM that contains the section to be saved 1902021affd3Sksagiyam 1903021affd3Sksagiyam Level: advanced 1904021affd3Sksagiyam 1905021affd3Sksagiyam Notes: 1906021affd3Sksagiyam 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. 1907021affd3Sksagiyam 1908021affd3Sksagiyam 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. 1909021affd3Sksagiyam 1910db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()` 1911021affd3Sksagiyam @*/ 1912021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1913021affd3Sksagiyam { 1914021affd3Sksagiyam PetscBool ishdf5; 1915021affd3Sksagiyam 1916021affd3Sksagiyam PetscFunctionBegin; 1917021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1918021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1919021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 19219566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0)); 1922021affd3Sksagiyam if (ishdf5) { 1923021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 19249566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 1925021affd3Sksagiyam #else 1926021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1927021affd3Sksagiyam #endif 1928021affd3Sksagiyam } 19299566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0)); 1930021affd3Sksagiyam PetscFunctionReturn(0); 1931021affd3Sksagiyam } 1932021affd3Sksagiyam 19333e97647fSksagiyam /*@ 19343e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 19353e97647fSksagiyam 19363e97647fSksagiyam Collective on DM 19373e97647fSksagiyam 19383e97647fSksagiyam Input Parameters: 19393e97647fSksagiyam + dm - The DM that represents the topology 19403e97647fSksagiyam . viewer - The PetscViewer to save data with 19413e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined 19423e97647fSksagiyam - vec - The global vector to be saved 19433e97647fSksagiyam 19443e97647fSksagiyam Level: advanced 19453e97647fSksagiyam 19463e97647fSksagiyam Notes: 19473e97647fSksagiyam 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. 19483e97647fSksagiyam 19493e97647fSksagiyam Typical calling sequence 19503e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 19513e97647fSksagiyam $ DMSetType(dm, DMPLEX); 19523e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 19533e97647fSksagiyam $ DMClone(dm, §iondm); 19543e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 19553e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 19563e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 19573e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 19583e97647fSksagiyam $ PetscSectionSetUp(section); 19593e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 19603e97647fSksagiyam $ PetscSectionDestroy(§ion); 19613e97647fSksagiyam $ DMGetGlobalVector(sectiondm, &vec); 19623e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 19633e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 19643e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 19653e97647fSksagiyam $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 19663e97647fSksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 19673e97647fSksagiyam $ DMDestroy(§iondm); 19683e97647fSksagiyam $ DMDestroy(&dm); 19693e97647fSksagiyam 1970db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 19713e97647fSksagiyam @*/ 19723e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 19733e97647fSksagiyam { 19743e97647fSksagiyam PetscBool ishdf5; 19753e97647fSksagiyam 19763e97647fSksagiyam PetscFunctionBegin; 19773e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19783e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19793e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19803e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 19813e97647fSksagiyam /* Check consistency */ 19823e97647fSksagiyam { 19833e97647fSksagiyam PetscSection section; 19843e97647fSksagiyam PetscBool includesConstraints; 19853e97647fSksagiyam PetscInt m, m1; 19863e97647fSksagiyam 19879566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 19889566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 19899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 19909566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 19919566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 199263a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 19933e97647fSksagiyam } 19949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0)); 19963e97647fSksagiyam if (ishdf5) { 19973e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 19989566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 19993e97647fSksagiyam #else 20003e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20013e97647fSksagiyam #endif 20023e97647fSksagiyam } 20039566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0)); 20043e97647fSksagiyam PetscFunctionReturn(0); 20053e97647fSksagiyam } 20063e97647fSksagiyam 20073e97647fSksagiyam /*@ 20083e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 20093e97647fSksagiyam 20103e97647fSksagiyam Collective on DM 20113e97647fSksagiyam 20123e97647fSksagiyam Input Parameters: 20133e97647fSksagiyam + dm - The DM that represents the topology 20143e97647fSksagiyam . viewer - The PetscViewer to save data with 20153e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 20163e97647fSksagiyam - vec - The local vector to be saved 20173e97647fSksagiyam 20183e97647fSksagiyam Level: advanced 20193e97647fSksagiyam 20203e97647fSksagiyam Notes: 20213e97647fSksagiyam 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. 20223e97647fSksagiyam 20233e97647fSksagiyam Typical calling sequence 20243e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 20253e97647fSksagiyam $ DMSetType(dm, DMPLEX); 20263e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 20273e97647fSksagiyam $ DMClone(dm, §iondm); 20283e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 20293e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 20303e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 20313e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 20323e97647fSksagiyam $ PetscSectionSetUp(section); 20333e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 20343e97647fSksagiyam $ DMGetLocalVector(sectiondm, &vec); 20353e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 20363e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 20373e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 20383e97647fSksagiyam $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 20393e97647fSksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 20403e97647fSksagiyam $ DMDestroy(§iondm); 20413e97647fSksagiyam $ DMDestroy(&dm); 20423e97647fSksagiyam 2043db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 20443e97647fSksagiyam @*/ 20453e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 20463e97647fSksagiyam { 20473e97647fSksagiyam PetscBool ishdf5; 20483e97647fSksagiyam 20493e97647fSksagiyam PetscFunctionBegin; 20503e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20513e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20523e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 20533e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 20543e97647fSksagiyam /* Check consistency */ 20553e97647fSksagiyam { 20563e97647fSksagiyam PetscSection section; 20573e97647fSksagiyam PetscBool includesConstraints; 20583e97647fSksagiyam PetscInt m, m1; 20593e97647fSksagiyam 20609566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 20619566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 20629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 20639566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 20649566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 206563a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 20663e97647fSksagiyam } 20679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0)); 20693e97647fSksagiyam if (ishdf5) { 20703e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 20719566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20723e97647fSksagiyam #else 20733e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20743e97647fSksagiyam #endif 20753e97647fSksagiyam } 20769566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0)); 20773e97647fSksagiyam PetscFunctionReturn(0); 20783e97647fSksagiyam } 20793e97647fSksagiyam 20802c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 20812c40f234SMatthew G. Knepley { 2082d4f5a9a0SVaclav Hapla PetscBool ishdf5; 20832c40f234SMatthew G. Knepley 20842c40f234SMatthew G. Knepley PetscFunctionBegin; 20852c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20862c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 2088d4f5a9a0SVaclav Hapla if (ishdf5) { 20892c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 20909c48423bSVaclav Hapla PetscViewerFormat format; 20919566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20929c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 20939566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2094509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20959566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 209698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2097b458e8f1SJose E. Roman PetscFunctionReturn(0); 20982c40f234SMatthew G. Knepley #else 20992c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2100552f7358SJed Brown #endif 210198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2102552f7358SJed Brown } 2103552f7358SJed Brown 2104ea8e1828Sksagiyam /*@ 2105ea8e1828Sksagiyam DMPlexTopologyLoad - Loads a topology into a DMPlex 2106ea8e1828Sksagiyam 2107ea8e1828Sksagiyam Collective on DM 2108ea8e1828Sksagiyam 2109ea8e1828Sksagiyam Input Parameters: 2110ea8e1828Sksagiyam + dm - The DM into which the topology is loaded 2111ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology 2112ea8e1828Sksagiyam 2113dec9e869Sksagiyam Output Parameters: 2114f84dd6b4Sksagiyam . 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 2115dec9e869Sksagiyam 2116ea8e1828Sksagiyam Level: advanced 2117ea8e1828Sksagiyam 2118db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 2119ea8e1828Sksagiyam @*/ 2120f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2121ea8e1828Sksagiyam { 2122ea8e1828Sksagiyam PetscBool ishdf5; 2123ea8e1828Sksagiyam 2124ea8e1828Sksagiyam PetscFunctionBegin; 2125ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2126ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2127f84dd6b4Sksagiyam if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 21289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 21299566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0)); 2130ea8e1828Sksagiyam if (ishdf5) { 2131ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2132ea8e1828Sksagiyam PetscViewerFormat format; 21339566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2134ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21359566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 213698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2137ea8e1828Sksagiyam #else 2138ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2139ea8e1828Sksagiyam #endif 2140ea8e1828Sksagiyam } 21419566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0)); 2142ea8e1828Sksagiyam PetscFunctionReturn(0); 2143ea8e1828Sksagiyam } 2144ea8e1828Sksagiyam 21453e701f1cSksagiyam /*@ 21463e701f1cSksagiyam DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 21473e701f1cSksagiyam 21483e701f1cSksagiyam Collective on DM 21493e701f1cSksagiyam 21503e701f1cSksagiyam Input Parameters: 21513e701f1cSksagiyam + dm - The DM into which the coordinates are loaded 2152c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates 2153c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 21543e701f1cSksagiyam 21553e701f1cSksagiyam Level: advanced 21563e701f1cSksagiyam 2157db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 21583e701f1cSksagiyam @*/ 2159c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 21603e701f1cSksagiyam { 21613e701f1cSksagiyam PetscBool ishdf5; 21623e701f1cSksagiyam 21633e701f1cSksagiyam PetscFunctionBegin; 21643e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21653e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2166c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 21679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 21689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0)); 21693e701f1cSksagiyam if (ishdf5) { 21703e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 21713e701f1cSksagiyam PetscViewerFormat format; 21729566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 21733e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21749566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 217598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 21763e701f1cSksagiyam #else 21773e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21783e701f1cSksagiyam #endif 21793e701f1cSksagiyam } 21809566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0)); 21813e701f1cSksagiyam PetscFunctionReturn(0); 21823e701f1cSksagiyam } 21833e701f1cSksagiyam 2184b08ad5deSksagiyam /*@ 2185b08ad5deSksagiyam DMPlexLabelsLoad - Loads labels into a DMPlex 2186b08ad5deSksagiyam 2187b08ad5deSksagiyam Collective on DM 2188b08ad5deSksagiyam 2189b08ad5deSksagiyam Input Parameters: 2190b08ad5deSksagiyam + dm - The DM into which the labels are loaded 2191e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels 2192e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2193b08ad5deSksagiyam 2194b08ad5deSksagiyam Level: advanced 2195b08ad5deSksagiyam 2196e6368b79SVaclav Hapla Notes: 2197e6368b79SVaclav Hapla The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs. 2198e6368b79SVaclav Hapla 2199db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 2200b08ad5deSksagiyam @*/ 2201e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2202b08ad5deSksagiyam { 2203b08ad5deSksagiyam PetscBool ishdf5; 2204b08ad5deSksagiyam 2205b08ad5deSksagiyam PetscFunctionBegin; 2206b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2207b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2208e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 22109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0)); 2211b08ad5deSksagiyam if (ishdf5) { 2212b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2213b08ad5deSksagiyam PetscViewerFormat format; 2214b08ad5deSksagiyam 22159566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2216b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22179566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 221898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2219b08ad5deSksagiyam #else 2220b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2221b08ad5deSksagiyam #endif 2222b08ad5deSksagiyam } 22239566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0)); 2224b08ad5deSksagiyam PetscFunctionReturn(0); 2225b08ad5deSksagiyam } 2226b08ad5deSksagiyam 2227f84dd6b4Sksagiyam /*@ 2228f84dd6b4Sksagiyam DMPlexSectionLoad - Loads section into a DMPlex 2229f84dd6b4Sksagiyam 2230f84dd6b4Sksagiyam Collective on DM 2231f84dd6b4Sksagiyam 2232f84dd6b4Sksagiyam Input Parameters: 2233f84dd6b4Sksagiyam + dm - The DM that represents the topology 2234f84dd6b4Sksagiyam . viewer - The PetscViewer that represents the on-disk section (sectionA) 2235f84dd6b4Sksagiyam . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2236f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2237f84dd6b4Sksagiyam 2238f84dd6b4Sksagiyam Output Parameters 2239f84dd6b4Sksagiyam + 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) 2240f84dd6b4Sksagiyam - 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) 2241f84dd6b4Sksagiyam 2242f84dd6b4Sksagiyam Level: advanced 2243f84dd6b4Sksagiyam 2244f84dd6b4Sksagiyam Notes: 2245f84dd6b4Sksagiyam 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. 2246f84dd6b4Sksagiyam 2247f84dd6b4Sksagiyam 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. 2248f84dd6b4Sksagiyam 2249f84dd6b4Sksagiyam 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. 2250f84dd6b4Sksagiyam 2251f84dd6b4Sksagiyam Example using 2 processes: 2252f84dd6b4Sksagiyam $ NX (number of points on dm): 4 2253f84dd6b4Sksagiyam $ sectionA : the on-disk section 2254f84dd6b4Sksagiyam $ vecA : a vector associated with sectionA 2255f84dd6b4Sksagiyam $ sectionB : sectiondm's local section constructed in this function 2256f84dd6b4Sksagiyam $ vecB (local) : a vector associated with sectiondm's local section 2257f84dd6b4Sksagiyam $ vecB (global) : a vector associated with sectiondm's global section 2258f84dd6b4Sksagiyam $ 2259f84dd6b4Sksagiyam $ rank 0 rank 1 2260f84dd6b4Sksagiyam $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2261f84dd6b4Sksagiyam $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2262f84dd6b4Sksagiyam $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2263f84dd6b4Sksagiyam $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2264f84dd6b4Sksagiyam $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2265f84dd6b4Sksagiyam $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2266f84dd6b4Sksagiyam $ sectionB->atlasDof : 1 0 1 | 1 3 2267f84dd6b4Sksagiyam $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2268f84dd6b4Sksagiyam $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2269f84dd6b4Sksagiyam $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2270f84dd6b4Sksagiyam $ 2271f84dd6b4Sksagiyam $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2272f84dd6b4Sksagiyam 2273db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()` 2274f84dd6b4Sksagiyam @*/ 2275f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2276f84dd6b4Sksagiyam { 2277f84dd6b4Sksagiyam PetscBool ishdf5; 2278f84dd6b4Sksagiyam 2279f84dd6b4Sksagiyam PetscFunctionBegin; 2280f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2281f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2282f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2283f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2284f84dd6b4Sksagiyam if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2285f84dd6b4Sksagiyam if (localDofSF) PetscValidPointer(localDofSF, 6); 22869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 22879566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0)); 2288f84dd6b4Sksagiyam if (ishdf5) { 2289f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 22909566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2291f84dd6b4Sksagiyam #else 2292f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2293f84dd6b4Sksagiyam #endif 2294f84dd6b4Sksagiyam } 22959566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0)); 2296f84dd6b4Sksagiyam PetscFunctionReturn(0); 2297f84dd6b4Sksagiyam } 2298f84dd6b4Sksagiyam 22998be3dfe1Sksagiyam /*@ 23008be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 23018be3dfe1Sksagiyam 23028be3dfe1Sksagiyam Collective on DM 23038be3dfe1Sksagiyam 23048be3dfe1Sksagiyam Input Parameters: 23058be3dfe1Sksagiyam + dm - The DM that represents the topology 23068be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23078be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined 23088be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23098be3dfe1Sksagiyam - vec - The global vector to set values of 23108be3dfe1Sksagiyam 23118be3dfe1Sksagiyam Level: advanced 23128be3dfe1Sksagiyam 23138be3dfe1Sksagiyam Notes: 23148be3dfe1Sksagiyam 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. 23158be3dfe1Sksagiyam 23168be3dfe1Sksagiyam Typical calling sequence 23178be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23188be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23198be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23208be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23218be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23228be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23238be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 23248be3dfe1Sksagiyam $ DMGetGlobalVector(sectiondm, &vec); 23258be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23268be3dfe1Sksagiyam $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 23278be3dfe1Sksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 23288be3dfe1Sksagiyam $ PetscSFDestroy(&gsf); 23298be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 23308be3dfe1Sksagiyam $ DMDestroy(§iondm); 23318be3dfe1Sksagiyam $ DMDestroy(&dm); 23328be3dfe1Sksagiyam 2333db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()` 23348be3dfe1Sksagiyam @*/ 23358be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 23368be3dfe1Sksagiyam { 23378be3dfe1Sksagiyam PetscBool ishdf5; 23388be3dfe1Sksagiyam 23398be3dfe1Sksagiyam PetscFunctionBegin; 23408be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23418be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23428be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 23438be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 23448be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 23458be3dfe1Sksagiyam /* Check consistency */ 23468be3dfe1Sksagiyam { 23478be3dfe1Sksagiyam PetscSection section; 23488be3dfe1Sksagiyam PetscBool includesConstraints; 23498be3dfe1Sksagiyam PetscInt m, m1; 23508be3dfe1Sksagiyam 23519566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 23529566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 23539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 23549566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 23559566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 235663a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 23578be3dfe1Sksagiyam } 23589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 23599566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0)); 23608be3dfe1Sksagiyam if (ishdf5) { 23618be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 23629566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 23638be3dfe1Sksagiyam #else 23648be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23658be3dfe1Sksagiyam #endif 23668be3dfe1Sksagiyam } 23679566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0)); 23688be3dfe1Sksagiyam PetscFunctionReturn(0); 23698be3dfe1Sksagiyam } 23708be3dfe1Sksagiyam 23718be3dfe1Sksagiyam /*@ 23728be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 23738be3dfe1Sksagiyam 23748be3dfe1Sksagiyam Collective on DM 23758be3dfe1Sksagiyam 23768be3dfe1Sksagiyam Input Parameters: 23778be3dfe1Sksagiyam + dm - The DM that represents the topology 23788be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23798be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined 23808be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23818be3dfe1Sksagiyam - vec - The local vector to set values of 23828be3dfe1Sksagiyam 23838be3dfe1Sksagiyam Level: advanced 23848be3dfe1Sksagiyam 23858be3dfe1Sksagiyam Notes: 23868be3dfe1Sksagiyam 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. 23878be3dfe1Sksagiyam 23888be3dfe1Sksagiyam Typical calling sequence 23898be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23908be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23918be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23928be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23938be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23948be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23958be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 23968be3dfe1Sksagiyam $ DMGetLocalVector(sectiondm, &vec); 23978be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23988be3dfe1Sksagiyam $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 23998be3dfe1Sksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 24008be3dfe1Sksagiyam $ PetscSFDestroy(&lsf); 24018be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 24028be3dfe1Sksagiyam $ DMDestroy(§iondm); 24038be3dfe1Sksagiyam $ DMDestroy(&dm); 24048be3dfe1Sksagiyam 2405db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()` 24068be3dfe1Sksagiyam @*/ 24078be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 24088be3dfe1Sksagiyam { 24098be3dfe1Sksagiyam PetscBool ishdf5; 24108be3dfe1Sksagiyam 24118be3dfe1Sksagiyam PetscFunctionBegin; 24128be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24138be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24148be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24158be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24168be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24178be3dfe1Sksagiyam /* Check consistency */ 24188be3dfe1Sksagiyam { 24198be3dfe1Sksagiyam PetscSection section; 24208be3dfe1Sksagiyam PetscBool includesConstraints; 24218be3dfe1Sksagiyam PetscInt m, m1; 24228be3dfe1Sksagiyam 24239566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 24249566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 24259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24269566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 24279566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 242863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 24298be3dfe1Sksagiyam } 24309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 24319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0)); 24328be3dfe1Sksagiyam if (ishdf5) { 24338be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 24349566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 24358be3dfe1Sksagiyam #else 24368be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24378be3dfe1Sksagiyam #endif 24388be3dfe1Sksagiyam } 24399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0)); 24408be3dfe1Sksagiyam PetscFunctionReturn(0); 24418be3dfe1Sksagiyam } 24428be3dfe1Sksagiyam 2443552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm) 2444552f7358SJed Brown { 2445552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2446552f7358SJed Brown 2447552f7358SJed Brown PetscFunctionBegin; 24489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL)); 24499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL)); 24509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL)); 24519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL)); 24522e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C", NULL)); 24532e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C", NULL)); 24542e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C", NULL)); 24552e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C", NULL)); 24562e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",NULL)); 24576bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderGetDefault_C", NULL)); 24586bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderSetDefault_C", NULL)); 2459c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",NULL)); 2460c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexSetOverlap_C",NULL)); 24610d644c17SKarl Rupp if (--mesh->refct > 0) PetscFunctionReturn(0); 24629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 24639566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 24649566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 24659566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 24669566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 24679566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 24689566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->facesTmp)); 24699566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 24709566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 24719566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 24729566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 24739566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 24749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 24759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 24769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 24779566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 24789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 24799566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 24809566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 24819566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 24829566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 24839566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 24849566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 24859566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 24869566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 24879566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2488552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 24899566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 2490552f7358SJed Brown PetscFunctionReturn(0); 2491552f7358SJed Brown } 2492552f7358SJed Brown 2493b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2494552f7358SJed Brown { 24958d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2496acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 24979fca9976SJed Brown PetscInt localSize, localStart = 0; 2498837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2499b412c318SBarry Smith MatType mtype; 25001428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2501552f7358SJed Brown 2502552f7358SJed Brown PetscFunctionBegin; 25039566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2504b412c318SBarry Smith mtype = dm->mattype; 25059566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 25069566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 25079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 25089fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm))); 25099566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 25109566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 25119566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 25129566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 25139566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2514acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 25159566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 25169566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 25179566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 25189566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 25199566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 25209566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 25219566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 25229566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2523552f7358SJed Brown if (!isShell) { 2524837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 25259fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2526fad22124SMatthew G Knepley PetscInt pStart, pEnd, p, dof, cdof; 2527552f7358SJed Brown 25289566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm,<og)); 25299fca9976SJed Brown 25309fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 25319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2532e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 25339fca9976SJed Brown PetscInt bdof, offset; 2534a9d99c84SMatthew G. Knepley 25359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 25369fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 25379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 25389fca9976SJed Brown for (PetscInt i=0; i < dof - cdof; i++) 25399fca9976SJed Brown pblocks[offset - localStart + i] = dof - cdof; 25401d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof+1) : dof; 25411d17a0a3SMatthew G. Knepley bdof = cdof && (dof-cdof) ? 1 : dof; 25421d17a0a3SMatthew G. Knepley if (dof) { 25431d17a0a3SMatthew G. Knepley if (bs < 0) {bs = bdof;} 25449fca9976SJed Brown else if (bs != bdof) {bs = 1;} 2545552f7358SJed Brown } 25462a28c762SMatthew G Knepley } 25472a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2548e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2549e432b41dSStefano Zampini bsLocal[1] = bs; 25509566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 2551e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2552e432b41dSStefano Zampini else bs = bsMinMax[0]; 25536fd5c86aSStefano Zampini bs = PetscMax(1,bs); 25549566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J,ltog,ltog)); 25550682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 25569566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 25579566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 25580682b8bbSJed Brown } else { 25599566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu)); 25609566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 25619566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2562552f7358SJed Brown } 25639fca9976SJed Brown { // Consolidate blocks 25649fca9976SJed Brown PetscInt nblocks = 0; 25659fca9976SJed Brown for (PetscInt i=0; i<localSize; i += PetscMax(1, pblocks[i])) { 25669fca9976SJed Brown if (pblocks[i] == 0) continue; 25679fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 25689fca9976SJed Brown for (PetscInt j=1; j<pblocks[i]; j++) { 25699fca9976SJed 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]); 25709fca9976SJed Brown } 25719fca9976SJed Brown } 25729fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 25739fca9976SJed Brown } 25749fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2575aa0f6e3cSJed Brown } 25769566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 2577552f7358SJed Brown PetscFunctionReturn(0); 2578552f7358SJed Brown } 2579552f7358SJed Brown 25807cd05799SMatthew G. Knepley /*@ 2581a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2582be36d101SStefano Zampini 2583be36d101SStefano Zampini Not collective 2584be36d101SStefano Zampini 2585be36d101SStefano Zampini Input Parameter: 2586be36d101SStefano Zampini . mesh - The DMPlex 2587be36d101SStefano Zampini 2588be36d101SStefano Zampini Output Parameters: 2589be36d101SStefano Zampini . subsection - The subdomain section 2590be36d101SStefano Zampini 2591be36d101SStefano Zampini Level: developer 2592be36d101SStefano Zampini 2593be36d101SStefano Zampini .seealso: 25947cd05799SMatthew G. Knepley @*/ 2595be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2596be36d101SStefano Zampini { 2597be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex*) dm->data; 2598be36d101SStefano Zampini 2599be36d101SStefano Zampini PetscFunctionBegin; 2600be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2601be36d101SStefano Zampini if (!mesh->subdomainSection) { 2602be36d101SStefano Zampini PetscSection section; 2603be36d101SStefano Zampini PetscSF sf; 2604be36d101SStefano Zampini 26059566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sf)); 26069566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm,§ion)); 26079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection)); 26089566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2609be36d101SStefano Zampini } 2610be36d101SStefano Zampini *subsection = mesh->subdomainSection; 2611be36d101SStefano Zampini PetscFunctionReturn(0); 2612be36d101SStefano Zampini } 2613be36d101SStefano Zampini 2614552f7358SJed Brown /*@ 2615552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2616552f7358SJed Brown 2617552f7358SJed Brown Not collective 2618552f7358SJed Brown 2619552f7358SJed Brown Input Parameter: 2620552f7358SJed Brown . mesh - The DMPlex 2621552f7358SJed Brown 2622552f7358SJed Brown Output Parameters: 2623552f7358SJed Brown + pStart - The first mesh point 2624552f7358SJed Brown - pEnd - The upper bound for mesh points 2625552f7358SJed Brown 2626552f7358SJed Brown Level: beginner 2627552f7358SJed Brown 2628db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()` 2629552f7358SJed Brown @*/ 2630552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2631552f7358SJed Brown { 2632552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2633552f7358SJed Brown 2634552f7358SJed Brown PetscFunctionBegin; 2635552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 2637552f7358SJed Brown PetscFunctionReturn(0); 2638552f7358SJed Brown } 2639552f7358SJed Brown 2640552f7358SJed Brown /*@ 2641552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2642552f7358SJed Brown 2643552f7358SJed Brown Not collective 2644552f7358SJed Brown 2645552f7358SJed Brown Input Parameters: 2646552f7358SJed Brown + mesh - The DMPlex 2647552f7358SJed Brown . pStart - The first mesh point 2648552f7358SJed Brown - pEnd - The upper bound for mesh points 2649552f7358SJed Brown 2650552f7358SJed Brown Output Parameters: 2651552f7358SJed Brown 2652552f7358SJed Brown Level: beginner 2653552f7358SJed Brown 2654db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()` 2655552f7358SJed Brown @*/ 2656552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2657552f7358SJed Brown { 2658552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2659552f7358SJed Brown 2660552f7358SJed Brown PetscFunctionBegin; 2661552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 26639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 2664552f7358SJed Brown PetscFunctionReturn(0); 2665552f7358SJed Brown } 2666552f7358SJed Brown 2667552f7358SJed Brown /*@ 2668eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2669552f7358SJed Brown 2670552f7358SJed Brown Not collective 2671552f7358SJed Brown 2672552f7358SJed Brown Input Parameters: 2673552f7358SJed Brown + mesh - The DMPlex 2674eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2675552f7358SJed Brown 2676552f7358SJed Brown Output Parameter: 2677552f7358SJed Brown . size - The cone size for point p 2678552f7358SJed Brown 2679552f7358SJed Brown Level: beginner 2680552f7358SJed Brown 2681db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2682552f7358SJed Brown @*/ 2683552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2684552f7358SJed Brown { 2685552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2686552f7358SJed Brown 2687552f7358SJed Brown PetscFunctionBegin; 2688552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2689dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 26909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 2691552f7358SJed Brown PetscFunctionReturn(0); 2692552f7358SJed Brown } 2693552f7358SJed Brown 2694552f7358SJed Brown /*@ 2695eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2696552f7358SJed Brown 2697552f7358SJed Brown Not collective 2698552f7358SJed Brown 2699552f7358SJed Brown Input Parameters: 2700552f7358SJed Brown + mesh - The DMPlex 2701eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2702552f7358SJed Brown - size - The cone size for point p 2703552f7358SJed Brown 2704552f7358SJed Brown Output Parameter: 2705552f7358SJed Brown 2706552f7358SJed Brown Note: 2707552f7358SJed Brown This should be called after DMPlexSetChart(). 2708552f7358SJed Brown 2709552f7358SJed Brown Level: beginner 2710552f7358SJed Brown 2711db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2712552f7358SJed Brown @*/ 2713552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2714552f7358SJed Brown { 2715552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2716552f7358SJed Brown 2717552f7358SJed Brown PetscFunctionBegin; 2718552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 2720552f7358SJed Brown PetscFunctionReturn(0); 2721552f7358SJed Brown } 2722552f7358SJed Brown 2723f5a469b9SMatthew G. Knepley /*@ 2724eaf898f9SPatrick Sanan DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2725f5a469b9SMatthew G. Knepley 2726f5a469b9SMatthew G. Knepley Not collective 2727f5a469b9SMatthew G. Knepley 2728f5a469b9SMatthew G. Knepley Input Parameters: 2729f5a469b9SMatthew G. Knepley + mesh - The DMPlex 2730eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2731f5a469b9SMatthew G. Knepley - size - The additional cone size for point p 2732f5a469b9SMatthew G. Knepley 2733f5a469b9SMatthew G. Knepley Output Parameter: 2734f5a469b9SMatthew G. Knepley 2735f5a469b9SMatthew G. Knepley Note: 2736f5a469b9SMatthew G. Knepley This should be called after DMPlexSetChart(). 2737f5a469b9SMatthew G. Knepley 2738f5a469b9SMatthew G. Knepley Level: beginner 2739f5a469b9SMatthew G. Knepley 2740db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2741f5a469b9SMatthew G. Knepley @*/ 2742f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2743f5a469b9SMatthew G. Knepley { 2744f5a469b9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 2745f5a469b9SMatthew G. Knepley PetscFunctionBegin; 2746f5a469b9SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27479566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->coneSection, p, size)); 2748f5a469b9SMatthew G. Knepley PetscFunctionReturn(0); 2749f5a469b9SMatthew G. Knepley } 2750f5a469b9SMatthew G. Knepley 2751552f7358SJed Brown /*@C 2752eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2753552f7358SJed Brown 2754552f7358SJed Brown Not collective 2755552f7358SJed Brown 2756552f7358SJed Brown Input Parameters: 2757833c876bSVaclav Hapla + dm - The DMPlex 2758eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2759552f7358SJed Brown 2760552f7358SJed Brown Output Parameter: 2761552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 2762552f7358SJed Brown 2763552f7358SJed Brown Level: beginner 2764552f7358SJed Brown 27653813dfbdSMatthew G Knepley Fortran Notes: 27663813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 27673813dfbdSMatthew G Knepley include petsc.h90 in your code. 2768922102d1SVaclav Hapla You must also call DMPlexRestoreCone() after you finish using the returned array. 2769922102d1SVaclav Hapla DMPlexRestoreCone() is not needed/available in C. 27703813dfbdSMatthew G Knepley 2771db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()` 2772552f7358SJed Brown @*/ 2773552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2774552f7358SJed Brown { 2775552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2776552f7358SJed Brown PetscInt off; 2777552f7358SJed Brown 2778552f7358SJed Brown PetscFunctionBegin; 2779552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2780552f7358SJed Brown PetscValidPointer(cone, 3); 27819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 2782552f7358SJed Brown *cone = &mesh->cones[off]; 2783552f7358SJed Brown PetscFunctionReturn(0); 2784552f7358SJed Brown } 2785552f7358SJed Brown 27860ce7577fSVaclav Hapla /*@C 27870ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 27880ce7577fSVaclav Hapla 27890ce7577fSVaclav Hapla Not collective 27900ce7577fSVaclav Hapla 27910ce7577fSVaclav Hapla Input Parameters: 27920ce7577fSVaclav Hapla + dm - The DMPlex 27930ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 27940ce7577fSVaclav Hapla 2795d8d19677SJose E. Roman Output Parameters: 27960ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones 27970ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p 27980ce7577fSVaclav Hapla 27990ce7577fSVaclav Hapla Level: intermediate 28000ce7577fSVaclav Hapla 2801db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()` 28020ce7577fSVaclav Hapla @*/ 28030ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 28040ce7577fSVaclav Hapla { 28050ce7577fSVaclav Hapla PetscSection cs, newcs; 28060ce7577fSVaclav Hapla PetscInt *cones; 28070ce7577fSVaclav Hapla PetscInt *newarr=NULL; 28080ce7577fSVaclav Hapla PetscInt n; 28090ce7577fSVaclav Hapla 28100ce7577fSVaclav Hapla PetscFunctionBegin; 28119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 28129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 28139566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL)); 28140ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 28150ce7577fSVaclav Hapla if (pCones) { 28169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 28179566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 28180ce7577fSVaclav Hapla } 28190ce7577fSVaclav Hapla PetscFunctionReturn(0); 28200ce7577fSVaclav Hapla } 28210ce7577fSVaclav Hapla 2822af9eab45SVaclav Hapla /*@ 2823af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2824d4636a37SVaclav Hapla 2825d4636a37SVaclav Hapla Not collective 2826d4636a37SVaclav Hapla 2827d4636a37SVaclav Hapla Input Parameters: 2828d4636a37SVaclav Hapla + dm - The DMPlex 2829af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2830d4636a37SVaclav Hapla 2831d4636a37SVaclav Hapla Output Parameter: 2832af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 2833d4636a37SVaclav Hapla 2834d4636a37SVaclav Hapla Level: advanced 2835d4636a37SVaclav Hapla 2836af9eab45SVaclav Hapla Notes: 2837af9eab45SVaclav Hapla Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2838af9eab45SVaclav Hapla There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2839af9eab45SVaclav Hapla 2840db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()` 2841d4636a37SVaclav Hapla @*/ 2842af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2843d4636a37SVaclav Hapla { 2844af9eab45SVaclav Hapla IS *expandedPointsAll; 2845af9eab45SVaclav Hapla PetscInt depth; 2846d4636a37SVaclav Hapla 2847d4636a37SVaclav Hapla PetscFunctionBegin; 2848af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2849af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2850af9eab45SVaclav Hapla PetscValidPointer(expandedPoints, 3); 28519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2852af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 28539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 28549566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2855af9eab45SVaclav Hapla PetscFunctionReturn(0); 2856af9eab45SVaclav Hapla } 2857af9eab45SVaclav Hapla 2858af9eab45SVaclav Hapla /*@ 2859af9eab45SVaclav 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). 2860af9eab45SVaclav Hapla 2861af9eab45SVaclav Hapla Not collective 2862af9eab45SVaclav Hapla 2863af9eab45SVaclav Hapla Input Parameters: 2864af9eab45SVaclav Hapla + dm - The DMPlex 2865af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2866af9eab45SVaclav Hapla 2867d8d19677SJose E. Roman Output Parameters: 2868af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2869af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 2870af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2871af9eab45SVaclav Hapla 2872af9eab45SVaclav Hapla Level: advanced 2873af9eab45SVaclav Hapla 2874af9eab45SVaclav Hapla Notes: 2875af9eab45SVaclav Hapla Like DMPlexGetConeTuple() but recursive. 2876af9eab45SVaclav Hapla 2877af9eab45SVaclav 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. 2878af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2879af9eab45SVaclav Hapla 2880af9eab45SVaclav 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: 2881af9eab45SVaclav Hapla (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2882af9eab45SVaclav Hapla (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2883af9eab45SVaclav Hapla 2884db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2885af9eab45SVaclav Hapla @*/ 2886af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2887af9eab45SVaclav Hapla { 2888af9eab45SVaclav Hapla const PetscInt *arr0=NULL, *cone=NULL; 2889af9eab45SVaclav Hapla PetscInt *arr=NULL, *newarr=NULL; 2890af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 2891af9eab45SVaclav Hapla IS *expandedPoints_; 2892af9eab45SVaclav Hapla PetscSection *sections_; 2893af9eab45SVaclav Hapla 2894af9eab45SVaclav Hapla PetscFunctionBegin; 2895af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2896af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2897af9eab45SVaclav Hapla if (depth) PetscValidIntPointer(depth, 3); 2898af9eab45SVaclav Hapla if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2899af9eab45SVaclav Hapla if (sections) PetscValidPointer(sections, 5); 29009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 29019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 29029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29039566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 29049566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 2905af9eab45SVaclav Hapla arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2906af9eab45SVaclav Hapla for (d=depth_-1; d>=0; d--) { 29079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 29089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 2909af9eab45SVaclav Hapla for (i=0; i<n; i++) { 29109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d+1, &start, &end)); 2911af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 29129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 29139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 2914af9eab45SVaclav Hapla } else { 29159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 2916af9eab45SVaclav Hapla } 2917af9eab45SVaclav Hapla } 29189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 29199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 29209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 2921af9eab45SVaclav Hapla for (i=0; i<n; i++) { 29229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 29239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 2924af9eab45SVaclav Hapla if (cn > 1) { 29259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 29269566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt))); 2927af9eab45SVaclav Hapla } else { 2928af9eab45SVaclav Hapla newarr[co] = arr[i]; 2929af9eab45SVaclav Hapla } 2930af9eab45SVaclav Hapla } 29319566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 2932af9eab45SVaclav Hapla arr = newarr; 2933af9eab45SVaclav Hapla n = newn; 2934af9eab45SVaclav Hapla } 29359566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 2936af9eab45SVaclav Hapla *depth = depth_; 2937af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 2938af9eab45SVaclav Hapla else { 29399566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 29409566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 2941af9eab45SVaclav Hapla } 2942af9eab45SVaclav Hapla if (sections) *sections = sections_; 2943af9eab45SVaclav Hapla else { 29449566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 29459566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 2946af9eab45SVaclav Hapla } 2947af9eab45SVaclav Hapla PetscFunctionReturn(0); 2948af9eab45SVaclav Hapla } 2949af9eab45SVaclav Hapla 2950af9eab45SVaclav Hapla /*@ 2951af9eab45SVaclav Hapla DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2952af9eab45SVaclav Hapla 2953af9eab45SVaclav Hapla Not collective 2954af9eab45SVaclav Hapla 2955af9eab45SVaclav Hapla Input Parameters: 2956af9eab45SVaclav Hapla + dm - The DMPlex 2957af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2958af9eab45SVaclav Hapla 2959d8d19677SJose E. Roman Output Parameters: 2960af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2961af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 2962af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2963af9eab45SVaclav Hapla 2964af9eab45SVaclav Hapla Level: advanced 2965af9eab45SVaclav Hapla 2966af9eab45SVaclav Hapla Notes: 2967af9eab45SVaclav Hapla See DMPlexGetConeRecursive() for details. 2968af9eab45SVaclav Hapla 2969db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2970af9eab45SVaclav Hapla @*/ 2971af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2972af9eab45SVaclav Hapla { 2973af9eab45SVaclav Hapla PetscInt d, depth_; 2974af9eab45SVaclav Hapla 2975af9eab45SVaclav Hapla PetscFunctionBegin; 29769566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29771dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2978af9eab45SVaclav Hapla if (depth) *depth = 0; 2979af9eab45SVaclav Hapla if (expandedPoints) { 29809566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 29819566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 2982af9eab45SVaclav Hapla } 2983af9eab45SVaclav Hapla if (sections) { 29849566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 29859566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 2986af9eab45SVaclav Hapla } 2987d4636a37SVaclav Hapla PetscFunctionReturn(0); 2988d4636a37SVaclav Hapla } 2989d4636a37SVaclav Hapla 2990552f7358SJed Brown /*@ 299192371b87SBarry 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 2992552f7358SJed Brown 2993552f7358SJed Brown Not collective 2994552f7358SJed Brown 2995552f7358SJed Brown Input Parameters: 2996552f7358SJed Brown + mesh - The DMPlex 2997eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2998552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 2999552f7358SJed Brown 3000552f7358SJed Brown Output Parameter: 3001552f7358SJed Brown 3002552f7358SJed Brown Note: 3003552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3004552f7358SJed Brown 3005552f7358SJed Brown Level: beginner 3006552f7358SJed Brown 3007db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3008552f7358SJed Brown @*/ 3009552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3010552f7358SJed Brown { 3011552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3012552f7358SJed Brown PetscInt pStart, pEnd; 3013552f7358SJed Brown PetscInt dof, off, c; 3014552f7358SJed Brown 3015552f7358SJed Brown PetscFunctionBegin; 3016552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 30189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3019dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(cone, 3); 30209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 302163a3b9bcSJacob 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); 3022552f7358SJed Brown for (c = 0; c < dof; ++c) { 302363a3b9bcSJacob 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); 3024552f7358SJed Brown mesh->cones[off+c] = cone[c]; 3025552f7358SJed Brown } 3026552f7358SJed Brown PetscFunctionReturn(0); 3027552f7358SJed Brown } 3028552f7358SJed Brown 3029552f7358SJed Brown /*@C 3030eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3031552f7358SJed Brown 3032552f7358SJed Brown Not collective 3033552f7358SJed Brown 3034552f7358SJed Brown Input Parameters: 3035552f7358SJed Brown + mesh - The DMPlex 3036eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3037552f7358SJed Brown 3038552f7358SJed Brown Output Parameter: 3039552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 3040b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3041552f7358SJed Brown 3042552f7358SJed Brown Level: beginner 3043552f7358SJed Brown 3044b5a892a1SMatthew G. Knepley Notes: 3045b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3046b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3047b5a892a1SMatthew G. Knepley of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 3048b5a892a1SMatthew G. Knepley with the identity. 3049b5a892a1SMatthew G. Knepley 30503813dfbdSMatthew G Knepley Fortran Notes: 30513813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 30523813dfbdSMatthew G Knepley include petsc.h90 in your code. 30533b12b3d8SVaclav Hapla You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 3054922102d1SVaclav Hapla DMPlexRestoreConeOrientation() is not needed/available in C. 30553813dfbdSMatthew G Knepley 3056db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3057552f7358SJed Brown @*/ 3058552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3059552f7358SJed Brown { 3060552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3061552f7358SJed Brown PetscInt off; 3062552f7358SJed Brown 3063552f7358SJed Brown PetscFunctionBegin; 3064552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 306576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3066552f7358SJed Brown PetscInt dof; 30679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3068552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 3069552f7358SJed Brown } 30709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30710d644c17SKarl Rupp 3072552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 3073552f7358SJed Brown PetscFunctionReturn(0); 3074552f7358SJed Brown } 3075552f7358SJed Brown 3076552f7358SJed Brown /*@ 3077eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3078552f7358SJed Brown 3079552f7358SJed Brown Not collective 3080552f7358SJed Brown 3081552f7358SJed Brown Input Parameters: 3082552f7358SJed Brown + mesh - The DMPlex 3083eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3084b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3085552f7358SJed Brown Output Parameter: 3086552f7358SJed Brown 3087b5a892a1SMatthew G. Knepley Notes: 3088552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3089552f7358SJed Brown 3090b5a892a1SMatthew G. Knepley The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3091b5a892a1SMatthew G. Knepley 3092552f7358SJed Brown Level: beginner 3093552f7358SJed Brown 3094db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3095552f7358SJed Brown @*/ 3096552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3097552f7358SJed Brown { 3098552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3099552f7358SJed Brown PetscInt pStart, pEnd; 3100552f7358SJed Brown PetscInt dof, off, c; 3101552f7358SJed Brown 3102552f7358SJed Brown PetscFunctionBegin; 3103552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 31059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3106dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(coneOrientation, 3); 31079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 310863a3b9bcSJacob 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); 3109552f7358SJed Brown for (c = 0; c < dof; ++c) { 3110552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3111552f7358SJed Brown 31129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof)); 31131dca8a05SBarry 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); 3114552f7358SJed Brown mesh->coneOrientations[off+c] = o; 3115552f7358SJed Brown } 3116552f7358SJed Brown PetscFunctionReturn(0); 3117552f7358SJed Brown } 3118552f7358SJed Brown 31197cd05799SMatthew G. Knepley /*@ 3120eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 31217cd05799SMatthew G. Knepley 31227cd05799SMatthew G. Knepley Not collective 31237cd05799SMatthew G. Knepley 31247cd05799SMatthew G. Knepley Input Parameters: 31257cd05799SMatthew G. Knepley + mesh - The DMPlex 3126eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31277cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31287cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 31297cd05799SMatthew G. Knepley 31307cd05799SMatthew G. Knepley Level: beginner 31317cd05799SMatthew G. Knepley 3132db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31337cd05799SMatthew G. Knepley @*/ 3134552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3135552f7358SJed Brown { 3136552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3137552f7358SJed Brown PetscInt pStart, pEnd; 3138552f7358SJed Brown PetscInt dof, off; 3139552f7358SJed Brown 3140552f7358SJed Brown PetscFunctionBegin; 3141552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 314363a3b9bcSJacob 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); 314463a3b9bcSJacob 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); 31459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 314763a3b9bcSJacob 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); 3148552f7358SJed Brown mesh->cones[off+conePos] = conePoint; 3149552f7358SJed Brown PetscFunctionReturn(0); 3150552f7358SJed Brown } 3151552f7358SJed Brown 31527cd05799SMatthew G. Knepley /*@ 3153eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 31547cd05799SMatthew G. Knepley 31557cd05799SMatthew G. Knepley Not collective 31567cd05799SMatthew G. Knepley 31577cd05799SMatthew G. Knepley Input Parameters: 31587cd05799SMatthew G. Knepley + mesh - The DMPlex 3159eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31607cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31617cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 31627cd05799SMatthew G. Knepley 31637cd05799SMatthew G. Knepley Level: beginner 31647cd05799SMatthew G. Knepley 3165b5a892a1SMatthew G. Knepley Notes: 3166b5a892a1SMatthew G. Knepley The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3167b5a892a1SMatthew G. Knepley 3168db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31697cd05799SMatthew G. Knepley @*/ 317077c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 317177c88f5bSMatthew G Knepley { 317277c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 317377c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 317477c88f5bSMatthew G Knepley PetscInt dof, off; 317577c88f5bSMatthew G Knepley 317677c88f5bSMatthew G Knepley PetscFunctionBegin; 317777c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 317963a3b9bcSJacob 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); 31809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 318263a3b9bcSJacob 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); 318377c88f5bSMatthew G Knepley mesh->coneOrientations[off+conePos] = coneOrientation; 318477c88f5bSMatthew G Knepley PetscFunctionReturn(0); 318577c88f5bSMatthew G Knepley } 318677c88f5bSMatthew G Knepley 3187552f7358SJed Brown /*@ 3188eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3189552f7358SJed Brown 3190552f7358SJed Brown Not collective 3191552f7358SJed Brown 3192552f7358SJed Brown Input Parameters: 3193552f7358SJed Brown + mesh - The DMPlex 3194eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3195552f7358SJed Brown 3196552f7358SJed Brown Output Parameter: 3197552f7358SJed Brown . size - The support size for point p 3198552f7358SJed Brown 3199552f7358SJed Brown Level: beginner 3200552f7358SJed Brown 3201db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3202552f7358SJed Brown @*/ 3203552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3204552f7358SJed Brown { 3205552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3206552f7358SJed Brown 3207552f7358SJed Brown PetscFunctionBegin; 3208552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3209dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 32109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 3211552f7358SJed Brown PetscFunctionReturn(0); 3212552f7358SJed Brown } 3213552f7358SJed Brown 3214552f7358SJed Brown /*@ 3215eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3216552f7358SJed Brown 3217552f7358SJed Brown Not collective 3218552f7358SJed Brown 3219552f7358SJed Brown Input Parameters: 3220552f7358SJed Brown + mesh - The DMPlex 3221eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3222552f7358SJed Brown - size - The support size for point p 3223552f7358SJed Brown 3224552f7358SJed Brown Output Parameter: 3225552f7358SJed Brown 3226552f7358SJed Brown Note: 3227552f7358SJed Brown This should be called after DMPlexSetChart(). 3228552f7358SJed Brown 3229552f7358SJed Brown Level: beginner 3230552f7358SJed Brown 3231db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3232552f7358SJed Brown @*/ 3233552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3234552f7358SJed Brown { 3235552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3236552f7358SJed Brown 3237552f7358SJed Brown PetscFunctionBegin; 3238552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 3240552f7358SJed Brown PetscFunctionReturn(0); 3241552f7358SJed Brown } 3242552f7358SJed Brown 3243552f7358SJed Brown /*@C 3244eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3245552f7358SJed Brown 3246552f7358SJed Brown Not collective 3247552f7358SJed Brown 3248552f7358SJed Brown Input Parameters: 3249552f7358SJed Brown + mesh - The DMPlex 3250eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3251552f7358SJed Brown 3252552f7358SJed Brown Output Parameter: 3253552f7358SJed Brown . support - An array of points which are on the out-edges for point p 3254552f7358SJed Brown 3255552f7358SJed Brown Level: beginner 3256552f7358SJed Brown 32573813dfbdSMatthew G Knepley Fortran Notes: 32583813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 32593813dfbdSMatthew G Knepley include petsc.h90 in your code. 32603b12b3d8SVaclav Hapla You must also call DMPlexRestoreSupport() after you finish using the returned array. 3261922102d1SVaclav Hapla DMPlexRestoreSupport() is not needed/available in C. 32623813dfbdSMatthew G Knepley 3263db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3264552f7358SJed Brown @*/ 3265552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3266552f7358SJed Brown { 3267552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3268552f7358SJed Brown PetscInt off; 3269552f7358SJed Brown 3270552f7358SJed Brown PetscFunctionBegin; 3271552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3272552f7358SJed Brown PetscValidPointer(support, 3); 32739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3274552f7358SJed Brown *support = &mesh->supports[off]; 3275552f7358SJed Brown PetscFunctionReturn(0); 3276552f7358SJed Brown } 3277552f7358SJed Brown 3278552f7358SJed Brown /*@ 327992371b87SBarry 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 3280552f7358SJed Brown 3281552f7358SJed Brown Not collective 3282552f7358SJed Brown 3283552f7358SJed Brown Input Parameters: 3284552f7358SJed Brown + mesh - The DMPlex 3285eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 328692371b87SBarry Smith - support - An array of points which are on the out-edges for point p 3287552f7358SJed Brown 3288552f7358SJed Brown Output Parameter: 3289552f7358SJed Brown 3290552f7358SJed Brown Note: 3291552f7358SJed Brown This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3292552f7358SJed Brown 3293552f7358SJed Brown Level: beginner 3294552f7358SJed Brown 3295db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3296552f7358SJed Brown @*/ 3297552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3298552f7358SJed Brown { 3299552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3300552f7358SJed Brown PetscInt pStart, pEnd; 3301552f7358SJed Brown PetscInt dof, off, c; 3302552f7358SJed Brown 3303552f7358SJed Brown PetscFunctionBegin; 3304552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 3307dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(support, 3); 33089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 330963a3b9bcSJacob 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); 3310552f7358SJed Brown for (c = 0; c < dof; ++c) { 331163a3b9bcSJacob 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); 3312552f7358SJed Brown mesh->supports[off+c] = support[c]; 3313552f7358SJed Brown } 3314552f7358SJed Brown PetscFunctionReturn(0); 3315552f7358SJed Brown } 3316552f7358SJed Brown 33177cd05799SMatthew G. Knepley /*@ 3318eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 33197cd05799SMatthew G. Knepley 33207cd05799SMatthew G. Knepley Not collective 33217cd05799SMatthew G. Knepley 33227cd05799SMatthew G. Knepley Input Parameters: 33237cd05799SMatthew G. Knepley + mesh - The DMPlex 3324eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 33257cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 33267cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 33277cd05799SMatthew G. Knepley 33287cd05799SMatthew G. Knepley Level: beginner 33297cd05799SMatthew G. Knepley 3330db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 33317cd05799SMatthew G. Knepley @*/ 3332552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3333552f7358SJed Brown { 3334552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3335552f7358SJed Brown PetscInt pStart, pEnd; 3336552f7358SJed Brown PetscInt dof, off; 3337552f7358SJed Brown 3338552f7358SJed Brown PetscFunctionBegin; 3339552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 33429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 334363a3b9bcSJacob 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); 334463a3b9bcSJacob 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); 334563a3b9bcSJacob 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); 3346552f7358SJed Brown mesh->supports[off+supportPos] = supportPoint; 3347552f7358SJed Brown PetscFunctionReturn(0); 3348552f7358SJed Brown } 3349552f7358SJed Brown 3350b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3351b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3352b5a892a1SMatthew G. Knepley { 3353b5a892a1SMatthew G. Knepley switch (ct) { 3354b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3355b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3356b5a892a1SMatthew G. Knepley break; 3357b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3358b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3359b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3360b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3361b5a892a1SMatthew G. Knepley break; 3362b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3363b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3364b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3365b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3366b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3367b5a892a1SMatthew G. Knepley break; 3368b5a892a1SMatthew G. Knepley default: return o; 3369b5a892a1SMatthew G. Knepley } 3370b5a892a1SMatthew G. Knepley return o; 3371b5a892a1SMatthew G. Knepley } 3372b5a892a1SMatthew G. Knepley 3373b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3374b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3375b5a892a1SMatthew G. Knepley { 3376b5a892a1SMatthew G. Knepley switch (ct) { 3377b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3378b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3379b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3380b5a892a1SMatthew G. Knepley break; 3381b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3382b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3383b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3384b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3385b5a892a1SMatthew G. Knepley break; 3386b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3387b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3388b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3389b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3390b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3391b5a892a1SMatthew G. Knepley break; 3392b5a892a1SMatthew G. Knepley default: return o; 3393b5a892a1SMatthew G. Knepley } 3394b5a892a1SMatthew G. Knepley return o; 3395b5a892a1SMatthew G. Knepley } 3396b5a892a1SMatthew G. Knepley 3397b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3398b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3399b5a892a1SMatthew G. Knepley { 3400b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3401b5a892a1SMatthew G. Knepley 3402b5a892a1SMatthew G. Knepley PetscFunctionBegin; 34039566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3404b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3405b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3406b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3407b5a892a1SMatthew G. Knepley 34089566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 34099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 34109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3411b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3412b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3413b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3414b5a892a1SMatthew G. Knepley 34159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3416b5a892a1SMatthew G. Knepley switch (ct) { 3417b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 34189566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34199566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3420b5a892a1SMatthew G. Knepley break; 3421b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 34229566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 34239566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34249566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3425b5a892a1SMatthew G. Knepley break; 3426b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 34279566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 34289566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34299566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 34309566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3431b5a892a1SMatthew G. Knepley break; 3432b5a892a1SMatthew G. Knepley default: break; 3433b5a892a1SMatthew G. Knepley } 3434b5a892a1SMatthew G. Knepley } 3435b5a892a1SMatthew G. Knepley } 3436b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3437b5a892a1SMatthew G. Knepley } 3438b5a892a1SMatthew G. Knepley 3439012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3440b5a892a1SMatthew G. Knepley { 3441b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3442b5a892a1SMatthew G. Knepley PetscInt *closure; 3443b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3444b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3445b5a892a1SMatthew G. Knepley 3446b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3447b5a892a1SMatthew G. Knepley if (ornt) { 34489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3449b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3450b5a892a1SMatthew G. Knepley } 3451b5a892a1SMatthew G. Knepley if (*points) { 3452b5a892a1SMatthew G. Knepley closure = *points; 3453b5a892a1SMatthew G. Knepley } else { 3454b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 34559566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 34569566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure)); 3457b5a892a1SMatthew G. Knepley } 3458b5a892a1SMatthew G. Knepley if (useCone) { 34599566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &tmpSize)); 34609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &tmp)); 34619566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO)); 3462b5a892a1SMatthew G. Knepley } else { 34639566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize)); 34649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &tmp)); 3465b5a892a1SMatthew G. Knepley } 3466b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3467b5a892a1SMatthew G. Knepley closure[off++] = p; 3468b5a892a1SMatthew G. Knepley closure[off++] = 0; 3469b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3470b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3471b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3472b5a892a1SMatthew G. Knepley } 3473b5a892a1SMatthew G. Knepley } else { 34745f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3475b5a892a1SMatthew G. Knepley 3476b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3477b5a892a1SMatthew G. Knepley closure[off++] = p; 3478b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3479b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3480b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3481b5a892a1SMatthew G. Knepley 34829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3483b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3484b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3485b5a892a1SMatthew G. Knepley } 3486b5a892a1SMatthew G. Knepley } 3487b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize+1; 3488b5a892a1SMatthew G. Knepley if (points) *points = closure; 3489b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3490b5a892a1SMatthew G. Knepley } 3491b5a892a1SMatthew G. Knepley 3492b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3493b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3494b5a892a1SMatthew G. Knepley { 3495b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3496b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3497b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3498b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3499b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3500b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3501b5a892a1SMatthew G. Knepley 3502b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 35039566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 35049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 35059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 35069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &ornt)); 35079566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3508b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3509b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3510b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 3511b5a892a1SMatthew G. Knepley if (*points) {pts = *points;} 35129566063dSJacob Faibussowitsch else PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts)); 3513b5a892a1SMatthew G. Knepley c = 0; 3514b5a892a1SMatthew G. Knepley pts[c++] = point; 3515b5a892a1SMatthew G. Knepley pts[c++] = o; 35169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft)); 35179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure)); 3518b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 35199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure)); 3520b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 35219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3522b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 35239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft)); 3524b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d*2+0]]; 3525b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3526b5a892a1SMatthew G. Knepley } 3527b5a892a1SMatthew G. Knepley if (dim >= 3) { 3528b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3529b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d*2+0]]; 3530b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3531b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3532b5a892a1SMatthew G. Knepley 35339566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3534b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 35359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize)); 35369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, fpoint, &fcone)); 35379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt)); 3538b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3539b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc*2+0]]; 3540b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc*2+1]; 3541b5a892a1SMatthew G. Knepley 3542b5a892a1SMatthew G. Knepley for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3543b5a892a1SMatthew G. Knepley if (i == c) { 35449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3545b5a892a1SMatthew G. Knepley pts[c++] = cp; 3546b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3547b5a892a1SMatthew G. Knepley } 3548b5a892a1SMatthew G. Knepley } 3549b5a892a1SMatthew G. Knepley } 3550b5a892a1SMatthew G. Knepley } 3551b5a892a1SMatthew G. Knepley *numPoints = c/2; 3552b5a892a1SMatthew G. Knepley *points = pts; 3553b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3554b5a892a1SMatthew G. Knepley } 3555b5a892a1SMatthew G. Knepley 3556b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3557b5a892a1SMatthew G. Knepley { 3558b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3559b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3560b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3561b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3562b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3563b5a892a1SMatthew G. Knepley 3564b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 35659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3566b5a892a1SMatthew G. Knepley if (depth == 1) { 35679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 3568b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3569b5a892a1SMatthew G. Knepley } 35709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3571b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3572b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 35739566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 3574b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3575b5a892a1SMatthew G. Knepley } 35769566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3577b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3578b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3579b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 35809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3581b5a892a1SMatthew G. Knepley if (*points) {closure = *points;} 35829566063dSJacob Faibussowitsch else PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure)); 3583b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3584b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3585b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3586b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3587b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3588b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3589b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3590b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3591b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3592b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3593b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3594b5a892a1SMatthew G. Knepley const PetscInt *tmp, *tmpO; 3595b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3596b5a892a1SMatthew G. Knepley 3597b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3598b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 359963a3b9bcSJacob 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); 3600b5a892a1SMatthew G. Knepley } 3601b5a892a1SMatthew G. Knepley if (useCone) { 36029566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &tmpSize)); 36039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &tmp)); 36049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO)); 3605b5a892a1SMatthew G. Knepley } else { 36069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize)); 36079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &tmp)); 3608b5a892a1SMatthew G. Knepley tmpO = NULL; 3609b5a892a1SMatthew G. Knepley } 3610b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3611b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3612b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3613b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 36149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3615b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3616b5a892a1SMatthew G. Knepley PetscInt c; 3617b5a892a1SMatthew G. Knepley 3618b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3619b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3620b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3621b5a892a1SMatthew G. Knepley } 3622b5a892a1SMatthew G. Knepley if (c == closureSize) { 3623b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3624b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3625b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3626b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3627b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3628b5a892a1SMatthew G. Knepley } 3629b5a892a1SMatthew G. Knepley } 3630b5a892a1SMatthew G. Knepley } 36319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3632b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize/2; 3633b5a892a1SMatthew G. Knepley if (points) *points = closure; 3634b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3635b5a892a1SMatthew G. Knepley } 3636b5a892a1SMatthew G. Knepley 3637552f7358SJed Brown /*@C 3638eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3639552f7358SJed Brown 3640552f7358SJed Brown Not collective 3641552f7358SJed Brown 3642552f7358SJed Brown Input Parameters: 3643b5a892a1SMatthew G. Knepley + dm - The DMPlex 3644b5a892a1SMatthew G. Knepley . p - The mesh point 36456b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star 3646552f7358SJed Brown 36476b867d5aSJose E. Roman Input/Output Parameter: 36486b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 36496b867d5aSJose E. Roman if NULL on input, internal storage will be returned, otherwise the provided array is used 36506b867d5aSJose E. Roman 36516b867d5aSJose E. Roman Output Parameter: 36526b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3653552f7358SJed Brown 3654552f7358SJed Brown Note: 36550298fd71SBarry Smith If using internal storage (points is NULL on input), each call overwrites the last output. 3656552f7358SJed Brown 36573813dfbdSMatthew G Knepley Fortran Notes: 3658b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36593813dfbdSMatthew G Knepley 36603813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36613813dfbdSMatthew G Knepley 3662552f7358SJed Brown Level: beginner 3663552f7358SJed Brown 3664db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3665552f7358SJed Brown @*/ 3666552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3667552f7358SJed Brown { 3668b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3669552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3670b5a892a1SMatthew G. Knepley if (numPoints) PetscValidIntPointer(numPoints, 4); 3671b5a892a1SMatthew G. Knepley if (points) PetscValidPointer(points, 5); 36729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 36739bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 36749bf0dad6SMatthew G. Knepley } 36759bf0dad6SMatthew G. Knepley 3676552f7358SJed Brown /*@C 3677eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3678552f7358SJed Brown 3679552f7358SJed Brown Not collective 3680552f7358SJed Brown 3681552f7358SJed Brown Input Parameters: 3682b5a892a1SMatthew G. Knepley + dm - The DMPlex 3683b5a892a1SMatthew G. Knepley . p - The mesh point 3684b5a892a1SMatthew G. Knepley . useCone - PETSC_TRUE for the closure, otherwise return the star 3685b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3686b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3687552f7358SJed Brown 3688552f7358SJed Brown Note: 36890298fd71SBarry Smith If not using internal storage (points is not NULL on input), this call is unnecessary 3690552f7358SJed Brown 36913813dfbdSMatthew G Knepley Fortran Notes: 3692b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36933813dfbdSMatthew G Knepley 36943813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36953813dfbdSMatthew G Knepley 3696552f7358SJed Brown Level: beginner 3697552f7358SJed Brown 3698db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3699552f7358SJed Brown @*/ 3700552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3701552f7358SJed Brown { 3702b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3703552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37044ff43b2cSJed Brown if (numPoints) *numPoints = 0; 37059566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 3706552f7358SJed Brown PetscFunctionReturn(0); 3707552f7358SJed Brown } 3708552f7358SJed Brown 3709552f7358SJed Brown /*@ 3710eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3711552f7358SJed Brown 3712552f7358SJed Brown Not collective 3713552f7358SJed Brown 3714552f7358SJed Brown Input Parameter: 3715552f7358SJed Brown . mesh - The DMPlex 3716552f7358SJed Brown 3717552f7358SJed Brown Output Parameters: 3718552f7358SJed Brown + maxConeSize - The maximum number of in-edges 3719552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 3720552f7358SJed Brown 3721552f7358SJed Brown Level: beginner 3722552f7358SJed Brown 3723db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3724552f7358SJed Brown @*/ 3725552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3726552f7358SJed Brown { 3727552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3728552f7358SJed Brown 3729552f7358SJed Brown PetscFunctionBegin; 3730552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37311baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 37321baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 3733552f7358SJed Brown PetscFunctionReturn(0); 3734552f7358SJed Brown } 3735552f7358SJed Brown 3736552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm) 3737552f7358SJed Brown { 3738552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 37396302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 3740552f7358SJed Brown 3741552f7358SJed Brown PetscFunctionBegin; 3742552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 37449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 37459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 37469566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 37479566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt))); 37486302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 37496302a7fbSVaclav Hapla if (maxSupportSize) { 37509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 37519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 37529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 37539566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt))); 3754552f7358SJed Brown } 3755552f7358SJed Brown PetscFunctionReturn(0); 3756552f7358SJed Brown } 3757552f7358SJed Brown 3758276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3759552f7358SJed Brown { 3760552f7358SJed Brown PetscFunctionBegin; 37619566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 37629566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 3763c2939958SSatish Balay if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3764736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 3765f94b4a02SBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 3766f94b4a02SBlaise Bourdin PetscSection section, sectionSeq; 3767f94b4a02SBlaise Bourdin 37683dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 37699566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dm->sfMigration)); 37709566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection((*subdm), §ion)); 37719566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv)); 37729566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq)); 37739566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 3774f94b4a02SBlaise Bourdin 37759566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural)); 3776c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 37779566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionSeq)); 37789566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 3779f94b4a02SBlaise Bourdin } 3780552f7358SJed Brown PetscFunctionReturn(0); 3781552f7358SJed Brown } 3782552f7358SJed Brown 37832adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 37842adcc780SMatthew G. Knepley { 37853dcd263cSBlaise Bourdin PetscInt i = 0; 37862adcc780SMatthew G. Knepley 37872adcc780SMatthew G. Knepley PetscFunctionBegin; 37889566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 37899566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 3790c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 37913dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 37923dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 37933dcd263cSBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 37943dcd263cSBlaise Bourdin PetscSection section, sectionSeq; 37953dcd263cSBlaise Bourdin 37963dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 37979566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dms[i]->sfMigration)); 3798c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 37999566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection((*superdm), §ion)); 38009566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv)); 38019566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq)); 38029566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 38033dcd263cSBlaise Bourdin 38049566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural)); 3805c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 38069566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionSeq)); 38079566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 38083dcd263cSBlaise Bourdin break; 38093dcd263cSBlaise Bourdin } 38103dcd263cSBlaise Bourdin } 38112adcc780SMatthew G. Knepley PetscFunctionReturn(0); 38122adcc780SMatthew G. Knepley } 38132adcc780SMatthew G. Knepley 3814552f7358SJed Brown /*@ 3815eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3816552f7358SJed Brown 3817552f7358SJed Brown Not collective 3818552f7358SJed Brown 3819552f7358SJed Brown Input Parameter: 3820552f7358SJed Brown . mesh - The DMPlex 3821552f7358SJed Brown 3822552f7358SJed Brown Output Parameter: 3823552f7358SJed Brown 3824552f7358SJed Brown Note: 3825552f7358SJed Brown This should be called after all calls to DMPlexSetCone() 3826552f7358SJed Brown 3827552f7358SJed Brown Level: beginner 3828552f7358SJed Brown 3829db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 3830552f7358SJed Brown @*/ 3831552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm) 3832552f7358SJed Brown { 3833552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3834552f7358SJed Brown PetscInt *offsets; 3835552f7358SJed Brown PetscInt supportSize; 3836552f7358SJed Brown PetscInt pStart, pEnd, p; 3837552f7358SJed Brown 3838552f7358SJed Brown PetscFunctionBegin; 3839552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 384028b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 38419566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0)); 3842552f7358SJed Brown /* Calculate support sizes */ 38439566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3844552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3845552f7358SJed Brown PetscInt dof, off, c; 3846552f7358SJed Brown 38479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3849552f7358SJed Brown for (c = off; c < off+dof; ++c) { 38509566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 3851552f7358SJed Brown } 3852552f7358SJed Brown } 38539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 3854552f7358SJed Brown /* Calculate supports */ 38559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 38569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 38579566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 3858552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3859552f7358SJed Brown PetscInt dof, off, c; 3860552f7358SJed Brown 38619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3863552f7358SJed Brown for (c = off; c < off+dof; ++c) { 3864552f7358SJed Brown const PetscInt q = mesh->cones[c]; 3865552f7358SJed Brown PetscInt offS; 3866552f7358SJed Brown 38679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 38680d644c17SKarl Rupp 3869552f7358SJed Brown mesh->supports[offS+offsets[q]] = p; 3870552f7358SJed Brown ++offsets[q]; 3871552f7358SJed Brown } 3872552f7358SJed Brown } 38739566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 38749566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0)); 3875552f7358SJed Brown PetscFunctionReturn(0); 3876552f7358SJed Brown } 3877552f7358SJed Brown 3878277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3879277ea44aSLisandro Dalcin { 3880277ea44aSLisandro Dalcin IS stratumIS; 3881277ea44aSLisandro Dalcin 3882277ea44aSLisandro Dalcin PetscFunctionBegin; 3883277ea44aSLisandro Dalcin if (pStart >= pEnd) PetscFunctionReturn(0); 388476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3885277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 3886277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 38879566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 3888277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 38899566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3890277ea44aSLisandro Dalcin if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3891277ea44aSLisandro Dalcin } 389263a3b9bcSJacob 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); 3893277ea44aSLisandro Dalcin } 38949566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS)); 38959566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 38969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 3897277ea44aSLisandro Dalcin PetscFunctionReturn(0); 3898277ea44aSLisandro Dalcin } 3899277ea44aSLisandro Dalcin 3900552f7358SJed Brown /*@ 3901a8d69d7bSBarry Smith DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 39026dd80730SBarry Smith can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3903552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3904552f7358SJed Brown the DAG. 3905552f7358SJed Brown 3906bf4602e4SToby Isaac Collective on dm 3907552f7358SJed Brown 3908552f7358SJed Brown Input Parameter: 3909552f7358SJed Brown . mesh - The DMPlex 3910552f7358SJed Brown 3911552f7358SJed Brown Output Parameter: 3912552f7358SJed Brown 3913552f7358SJed Brown Notes: 3914b1bb481bSMatthew Knepley Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3915b1bb481bSMatthew 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 3916b1bb481bSMatthew Knepley until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3917c58f1c22SToby Isaac manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3918150b719bSJed Brown via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3919552f7358SJed Brown 3920b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3921b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3922b1bb481bSMatthew 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 3923b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 3924b1bb481bSMatthew Knepley $ cone(c0) = {e0, v2} 3925b1bb481bSMatthew Knepley $ cone(e0) = {v0, v1} 3926b1bb481bSMatthew Knepley If DMPlexStratify() is run on this mesh, it will give depths 3927b1bb481bSMatthew Knepley $ depth 0 = {v0, v1, v2} 3928b1bb481bSMatthew Knepley $ depth 1 = {e0, c0} 3929b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3930b1bb481bSMatthew Knepley 3931150b719bSJed Brown DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3932552f7358SJed Brown 3933552f7358SJed Brown Level: beginner 3934552f7358SJed Brown 3935db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 3936552f7358SJed Brown @*/ 3937552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm) 3938552f7358SJed Brown { 3939df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 3940aa50250dSMatthew G. Knepley DMLabel label; 3941552f7358SJed Brown PetscInt pStart, pEnd, p; 3942552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 3943552f7358SJed Brown 3944552f7358SJed Brown PetscFunctionBegin; 3945552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39469566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0)); 3947277ea44aSLisandro Dalcin 3948277ea44aSLisandro Dalcin /* Create depth label */ 39499566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 39509566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 39519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 3952277ea44aSLisandro Dalcin 3953277ea44aSLisandro Dalcin { 3954552f7358SJed Brown /* Initialize roots and count leaves */ 3955277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3956277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3957552f7358SJed Brown PetscInt coneSize, supportSize; 3958552f7358SJed Brown 3959277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3962552f7358SJed Brown if (!coneSize && supportSize) { 3963277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3964277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3965552f7358SJed Brown ++numRoots; 3966552f7358SJed Brown } else if (!supportSize && coneSize) { 3967552f7358SJed Brown ++numLeaves; 3968552f7358SJed Brown } else if (!supportSize && !coneSize) { 3969552f7358SJed Brown /* Isolated points */ 3970277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3971277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3972552f7358SJed Brown } 3973552f7358SJed Brown } 39749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1)); 3975277ea44aSLisandro Dalcin } 3976277ea44aSLisandro Dalcin 3977552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 3978277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3979277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3980552f7358SJed Brown PetscInt coneSize, supportSize; 3981552f7358SJed Brown 3982277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39849566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3985552f7358SJed Brown if (!supportSize && coneSize) { 3986277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3987277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3988552f7358SJed Brown } 3989552f7358SJed Brown } 39909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1)); 3991552f7358SJed Brown } else { 3992277ea44aSLisandro Dalcin PetscInt level = 0; 3993277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 3994552f7358SJed Brown 39959566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3996277ea44aSLisandro Dalcin while (qEnd > qStart) { 3997277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3998277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 399974ef644bSMatthew G. Knepley 4000277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 400174ef644bSMatthew G. Knepley const PetscInt *support; 400274ef644bSMatthew G. Knepley PetscInt supportSize, s; 400374ef644bSMatthew G. Knepley 40049566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 40059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &support)); 400674ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 4007277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 4008277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 4009552f7358SJed Brown } 4010552f7358SJed Brown } 40119566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &level)); 40129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1)); 40139566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 401474ef644bSMatthew G. Knepley } 401574ef644bSMatthew G. Knepley } 4016bf4602e4SToby Isaac { /* just in case there is an empty process */ 4017bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4018bf4602e4SToby Isaac 40199566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 40209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 4021bf4602e4SToby Isaac for (v = numValues; v < maxValues; v++) { 40229566063dSJacob Faibussowitsch PetscCall(DMLabelAddStratum(label, v)); 4023bf4602e4SToby Isaac } 4024bf4602e4SToby Isaac } 40259566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject) label, &mesh->depthState)); 40269566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0)); 4027552f7358SJed Brown PetscFunctionReturn(0); 4028552f7358SJed Brown } 4029552f7358SJed Brown 4030412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4031ba2698f1SMatthew G. Knepley { 4032412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4033412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4034ba2698f1SMatthew G. Knepley 4035412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 40369566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 40379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 40389566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4039ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4040ba2698f1SMatthew G. Knepley if (depth <= 1) { 4041ba2698f1SMatthew G. Knepley switch (pdepth) { 4042ba2698f1SMatthew G. Knepley case 0: ct = DM_POLYTOPE_POINT;break; 4043ba2698f1SMatthew G. Knepley case 1: 4044ba2698f1SMatthew G. Knepley switch (coneSize) { 4045ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4046ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4047ba2698f1SMatthew G. Knepley case 4: 4048ba2698f1SMatthew G. Knepley switch (dim) { 4049ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 4050ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 4051ba2698f1SMatthew G. Knepley default: break; 4052ba2698f1SMatthew G. Knepley } 4053ba2698f1SMatthew G. Knepley break; 4054da9060c4SMatthew G. Knepley case 5: ct = DM_POLYTOPE_PYRAMID;break; 4055ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4056ba2698f1SMatthew G. Knepley case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 4057ba2698f1SMatthew G. Knepley default: break; 4058ba2698f1SMatthew G. Knepley } 4059ba2698f1SMatthew G. Knepley } 4060ba2698f1SMatthew G. Knepley } else { 4061ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4062ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4063ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4064ba2698f1SMatthew G. Knepley switch (dim) { 4065ba2698f1SMatthew G. Knepley case 1: 4066ba2698f1SMatthew G. Knepley switch (coneSize) { 4067ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4068ba2698f1SMatthew G. Knepley default: break; 4069ba2698f1SMatthew G. Knepley } 4070ba2698f1SMatthew G. Knepley break; 4071ba2698f1SMatthew G. Knepley case 2: 4072ba2698f1SMatthew G. Knepley switch (coneSize) { 4073ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4074ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4075ba2698f1SMatthew G. Knepley default: break; 4076ba2698f1SMatthew G. Knepley } 4077ba2698f1SMatthew G. Knepley break; 4078ba2698f1SMatthew G. Knepley case 3: 4079ba2698f1SMatthew G. Knepley switch (coneSize) { 4080ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4081da9060c4SMatthew G. Knepley case 5: 4082da9060c4SMatthew G. Knepley { 4083da9060c4SMatthew G. Knepley const PetscInt *cone; 4084da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4085da9060c4SMatthew G. Knepley 40869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 40879566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4088da9060c4SMatthew G. Knepley switch (faceConeSize) { 4089da9060c4SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4090da9060c4SMatthew G. Knepley case 4: ct = DM_POLYTOPE_PYRAMID;break; 4091da9060c4SMatthew G. Knepley } 4092da9060c4SMatthew G. Knepley } 4093da9060c4SMatthew G. Knepley break; 4094ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4095ba2698f1SMatthew G. Knepley default: break; 4096ba2698f1SMatthew G. Knepley } 4097ba2698f1SMatthew G. Knepley break; 4098ba2698f1SMatthew G. Knepley default: break; 4099ba2698f1SMatthew G. Knepley } 4100ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4101ba2698f1SMatthew G. Knepley switch (coneSize) { 4102ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4103ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4104ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4105ba2698f1SMatthew G. Knepley default: break; 4106ba2698f1SMatthew G. Knepley } 4107ba2698f1SMatthew G. Knepley } 4108ba2698f1SMatthew G. Knepley } 4109412e9a14SMatthew G. Knepley *pt = ct; 4110412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4111ba2698f1SMatthew G. Knepley } 4112412e9a14SMatthew G. Knepley 4113412e9a14SMatthew G. Knepley /*@ 4114412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4115412e9a14SMatthew G. Knepley 4116412e9a14SMatthew G. Knepley Collective on dm 4117412e9a14SMatthew G. Knepley 4118412e9a14SMatthew G. Knepley Input Parameter: 4119412e9a14SMatthew G. Knepley . mesh - The DMPlex 4120412e9a14SMatthew G. Knepley 4121412e9a14SMatthew G. Knepley DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4122412e9a14SMatthew G. Knepley 4123412e9a14SMatthew G. Knepley Level: developer 4124412e9a14SMatthew G. Knepley 4125412e9a14SMatthew G. Knepley Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4126412e9a14SMatthew G. Knepley internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4127412e9a14SMatthew G. Knepley automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4128412e9a14SMatthew G. Knepley 4129db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4130412e9a14SMatthew G. Knepley @*/ 4131412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm) 4132412e9a14SMatthew G. Knepley { 4133412e9a14SMatthew G. Knepley DM_Plex *mesh; 4134412e9a14SMatthew G. Knepley DMLabel ctLabel; 4135412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4136412e9a14SMatthew G. Knepley 4137412e9a14SMatthew G. Knepley PetscFunctionBegin; 4138412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4139412e9a14SMatthew G. Knepley mesh = (DM_Plex *) dm->data; 41409566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 41419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 41429566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4143412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4144327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4145412e9a14SMatthew G. Knepley PetscInt pdepth; 4146412e9a14SMatthew G. Knepley 41479566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 41489566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 414963a3b9bcSJacob Faibussowitsch PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 41509566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 4151412e9a14SMatthew G. Knepley } 41529566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState)); 41539566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view")); 4154ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4155ba2698f1SMatthew G. Knepley } 4156ba2698f1SMatthew G. Knepley 4157552f7358SJed Brown /*@C 4158552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4159552f7358SJed Brown 4160552f7358SJed Brown Not Collective 4161552f7358SJed Brown 4162552f7358SJed Brown Input Parameters: 4163552f7358SJed Brown + dm - The DMPlex object 4164552f7358SJed Brown . numPoints - The number of input points for the join 4165552f7358SJed Brown - points - The input points 4166552f7358SJed Brown 4167552f7358SJed Brown Output Parameters: 4168552f7358SJed Brown + numCoveredPoints - The number of points in the join 4169552f7358SJed Brown - coveredPoints - The points in the join 4170552f7358SJed Brown 4171552f7358SJed Brown Level: intermediate 4172552f7358SJed Brown 4173552f7358SJed Brown Note: Currently, this is restricted to a single level join 4174552f7358SJed Brown 41753813dfbdSMatthew G Knepley Fortran Notes: 41763813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 41773813dfbdSMatthew G Knepley include petsc.h90 in your code. 41783813dfbdSMatthew G Knepley 41793813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 41803813dfbdSMatthew G Knepley 4181db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4182552f7358SJed Brown @*/ 4183552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4184552f7358SJed Brown { 4185552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4186552f7358SJed Brown PetscInt *join[2]; 4187552f7358SJed Brown PetscInt joinSize, i = 0; 4188552f7358SJed Brown PetscInt dof, off, p, c, m; 41896302a7fbSVaclav Hapla PetscInt maxSupportSize; 4190552f7358SJed Brown 4191552f7358SJed Brown PetscFunctionBegin; 4192552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 419348bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 419448bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 419548bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 41966302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41976302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 41986302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4199552f7358SJed Brown /* Copy in support of first point */ 42009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 42019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4202552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4203552f7358SJed Brown join[i][joinSize] = mesh->supports[off+joinSize]; 4204552f7358SJed Brown } 4205552f7358SJed Brown /* Check each successive support */ 4206552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4207552f7358SJed Brown PetscInt newJoinSize = 0; 4208552f7358SJed Brown 42099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 42109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4211552f7358SJed Brown for (c = 0; c < dof; ++c) { 4212552f7358SJed Brown const PetscInt point = mesh->supports[off+c]; 4213552f7358SJed Brown 4214552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4215552f7358SJed Brown if (point == join[i][m]) { 4216552f7358SJed Brown join[1-i][newJoinSize++] = point; 4217552f7358SJed Brown break; 4218552f7358SJed Brown } 4219552f7358SJed Brown } 4220552f7358SJed Brown } 4221552f7358SJed Brown joinSize = newJoinSize; 4222552f7358SJed Brown i = 1-i; 4223552f7358SJed Brown } 4224552f7358SJed Brown *numCoveredPoints = joinSize; 4225552f7358SJed Brown *coveredPoints = join[i]; 42266302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1-i])); 4227552f7358SJed Brown PetscFunctionReturn(0); 4228552f7358SJed Brown } 4229552f7358SJed Brown 4230552f7358SJed Brown /*@C 4231552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4232552f7358SJed Brown 4233552f7358SJed Brown Not Collective 4234552f7358SJed Brown 4235552f7358SJed Brown Input Parameters: 4236552f7358SJed Brown + dm - The DMPlex object 4237552f7358SJed Brown . numPoints - The number of input points for the join 4238552f7358SJed Brown - points - The input points 4239552f7358SJed Brown 4240552f7358SJed Brown Output Parameters: 4241552f7358SJed Brown + numCoveredPoints - The number of points in the join 4242552f7358SJed Brown - coveredPoints - The points in the join 4243552f7358SJed Brown 42443813dfbdSMatthew G Knepley Fortran Notes: 42453813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42463813dfbdSMatthew G Knepley include petsc.h90 in your code. 42473813dfbdSMatthew G Knepley 42483813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42493813dfbdSMatthew G Knepley 4250552f7358SJed Brown Level: intermediate 4251552f7358SJed Brown 4252db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4253552f7358SJed Brown @*/ 4254552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4255552f7358SJed Brown { 4256552f7358SJed Brown PetscFunctionBegin; 4257552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4258d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4259d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4260d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 42619566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4262d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4263552f7358SJed Brown PetscFunctionReturn(0); 4264552f7358SJed Brown } 4265552f7358SJed Brown 4266552f7358SJed Brown /*@C 4267552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4268552f7358SJed Brown 4269552f7358SJed Brown Not Collective 4270552f7358SJed Brown 4271552f7358SJed Brown Input Parameters: 4272552f7358SJed Brown + dm - The DMPlex object 4273552f7358SJed Brown . numPoints - The number of input points for the join 4274552f7358SJed Brown - points - The input points 4275552f7358SJed Brown 4276552f7358SJed Brown Output Parameters: 4277552f7358SJed Brown + numCoveredPoints - The number of points in the join 4278552f7358SJed Brown - coveredPoints - The points in the join 4279552f7358SJed Brown 42803813dfbdSMatthew G Knepley Fortran Notes: 42813813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42823813dfbdSMatthew G Knepley include petsc.h90 in your code. 42833813dfbdSMatthew G Knepley 42843813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42853813dfbdSMatthew G Knepley 4286552f7358SJed Brown Level: intermediate 4287552f7358SJed Brown 4288db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4289552f7358SJed Brown @*/ 4290552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4291552f7358SJed Brown { 4292552f7358SJed Brown PetscInt *offsets, **closures; 4293552f7358SJed Brown PetscInt *join[2]; 4294552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 429524c766afSToby Isaac PetscInt p, d, c, m, ms; 4296552f7358SJed Brown 4297552f7358SJed Brown PetscFunctionBegin; 4298552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 429948bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 430048bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 430148bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 4302552f7358SJed Brown 43039566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 43049566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 43059566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 43066302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 430724c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 43089566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 43099566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4310552f7358SJed Brown 4311552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4312552f7358SJed Brown PetscInt closureSize; 4313552f7358SJed Brown 43149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 43150d644c17SKarl Rupp 4316552f7358SJed Brown offsets[p*(depth+2)+0] = 0; 4317552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4318552f7358SJed Brown PetscInt pStart, pEnd, i; 4319552f7358SJed Brown 43209566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4321552f7358SJed Brown for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4322552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4323552f7358SJed Brown offsets[p*(depth+2)+d+1] = i; 4324552f7358SJed Brown break; 4325552f7358SJed Brown } 4326552f7358SJed Brown } 4327552f7358SJed Brown if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4328552f7358SJed Brown } 432963a3b9bcSJacob 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); 4330552f7358SJed Brown } 4331552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4332552f7358SJed Brown PetscInt dof; 4333552f7358SJed Brown 4334552f7358SJed Brown /* Copy in support of first point */ 4335552f7358SJed Brown dof = offsets[d+1] - offsets[d]; 4336552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4337552f7358SJed Brown join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4338552f7358SJed Brown } 4339552f7358SJed Brown /* Check each successive cone */ 4340552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4341552f7358SJed Brown PetscInt newJoinSize = 0; 4342552f7358SJed Brown 4343552f7358SJed Brown dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4344552f7358SJed Brown for (c = 0; c < dof; ++c) { 4345552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4346552f7358SJed Brown 4347552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4348552f7358SJed Brown if (point == join[i][m]) { 4349552f7358SJed Brown join[1-i][newJoinSize++] = point; 4350552f7358SJed Brown break; 4351552f7358SJed Brown } 4352552f7358SJed Brown } 4353552f7358SJed Brown } 4354552f7358SJed Brown joinSize = newJoinSize; 4355552f7358SJed Brown i = 1-i; 4356552f7358SJed Brown } 4357552f7358SJed Brown if (joinSize) break; 4358552f7358SJed Brown } 4359552f7358SJed Brown *numCoveredPoints = joinSize; 4360552f7358SJed Brown *coveredPoints = join[i]; 4361552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 43629566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 4363552f7358SJed Brown } 43649566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 43659566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 43666302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1-i])); 4367552f7358SJed Brown PetscFunctionReturn(0); 4368552f7358SJed Brown } 4369552f7358SJed Brown 4370552f7358SJed Brown /*@C 4371552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4372552f7358SJed Brown 4373552f7358SJed Brown Not Collective 4374552f7358SJed Brown 4375552f7358SJed Brown Input Parameters: 4376552f7358SJed Brown + dm - The DMPlex object 4377552f7358SJed Brown . numPoints - The number of input points for the meet 4378552f7358SJed Brown - points - The input points 4379552f7358SJed Brown 4380552f7358SJed Brown Output Parameters: 4381552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4382552f7358SJed Brown - coveredPoints - The points in the meet 4383552f7358SJed Brown 4384552f7358SJed Brown Level: intermediate 4385552f7358SJed Brown 4386552f7358SJed Brown Note: Currently, this is restricted to a single level meet 4387552f7358SJed Brown 43883813dfbdSMatthew G Knepley Fortran Notes: 43893813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 43903813dfbdSMatthew G Knepley include petsc.h90 in your code. 43913813dfbdSMatthew G Knepley 43923813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 43933813dfbdSMatthew G Knepley 4394db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4395552f7358SJed Brown @*/ 4396552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4397552f7358SJed Brown { 4398552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4399552f7358SJed Brown PetscInt *meet[2]; 4400552f7358SJed Brown PetscInt meetSize, i = 0; 4401552f7358SJed Brown PetscInt dof, off, p, c, m; 44026302a7fbSVaclav Hapla PetscInt maxConeSize; 4403552f7358SJed Brown 4404552f7358SJed Brown PetscFunctionBegin; 4405552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4406dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4407dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveringPoints, 4); 4408064a246eSJacob Faibussowitsch PetscValidPointer(coveringPoints, 5); 44096302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 44106302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 44116302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4412552f7358SJed Brown /* Copy in cone of first point */ 44139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 44149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4415552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4416552f7358SJed Brown meet[i][meetSize] = mesh->cones[off+meetSize]; 4417552f7358SJed Brown } 4418552f7358SJed Brown /* Check each successive cone */ 4419552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4420552f7358SJed Brown PetscInt newMeetSize = 0; 4421552f7358SJed Brown 44229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 44239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4424552f7358SJed Brown for (c = 0; c < dof; ++c) { 4425552f7358SJed Brown const PetscInt point = mesh->cones[off+c]; 4426552f7358SJed Brown 4427552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4428552f7358SJed Brown if (point == meet[i][m]) { 4429552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4430552f7358SJed Brown break; 4431552f7358SJed Brown } 4432552f7358SJed Brown } 4433552f7358SJed Brown } 4434552f7358SJed Brown meetSize = newMeetSize; 4435552f7358SJed Brown i = 1-i; 4436552f7358SJed Brown } 4437552f7358SJed Brown *numCoveringPoints = meetSize; 4438552f7358SJed Brown *coveringPoints = meet[i]; 44396302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1-i])); 4440552f7358SJed Brown PetscFunctionReturn(0); 4441552f7358SJed Brown } 4442552f7358SJed Brown 4443552f7358SJed Brown /*@C 4444552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4445552f7358SJed Brown 4446552f7358SJed Brown Not Collective 4447552f7358SJed Brown 4448552f7358SJed Brown Input Parameters: 4449552f7358SJed Brown + dm - The DMPlex object 4450552f7358SJed Brown . numPoints - The number of input points for the meet 4451552f7358SJed Brown - points - The input points 4452552f7358SJed Brown 4453552f7358SJed Brown Output Parameters: 4454552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4455552f7358SJed Brown - coveredPoints - The points in the meet 4456552f7358SJed Brown 4457552f7358SJed Brown Level: intermediate 4458552f7358SJed Brown 44593813dfbdSMatthew G Knepley Fortran Notes: 44603813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44613813dfbdSMatthew G Knepley include petsc.h90 in your code. 44623813dfbdSMatthew G Knepley 44633813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44643813dfbdSMatthew G Knepley 4465db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4466552f7358SJed Brown @*/ 4467552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4468552f7358SJed Brown { 4469552f7358SJed Brown PetscFunctionBegin; 4470552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4471d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4472d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4473d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints,5); 44749566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4475d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4476552f7358SJed Brown PetscFunctionReturn(0); 4477552f7358SJed Brown } 4478552f7358SJed Brown 4479552f7358SJed Brown /*@C 4480552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4481552f7358SJed Brown 4482552f7358SJed Brown Not Collective 4483552f7358SJed Brown 4484552f7358SJed Brown Input Parameters: 4485552f7358SJed Brown + dm - The DMPlex object 4486552f7358SJed Brown . numPoints - The number of input points for the meet 4487552f7358SJed Brown - points - The input points 4488552f7358SJed Brown 4489552f7358SJed Brown Output Parameters: 4490552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4491552f7358SJed Brown - coveredPoints - The points in the meet 4492552f7358SJed Brown 4493552f7358SJed Brown Level: intermediate 4494552f7358SJed Brown 44953813dfbdSMatthew G Knepley Fortran Notes: 44963813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44973813dfbdSMatthew G Knepley include petsc.h90 in your code. 44983813dfbdSMatthew G Knepley 44993813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 45003813dfbdSMatthew G Knepley 4501db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4502552f7358SJed Brown @*/ 4503552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4504552f7358SJed Brown { 4505552f7358SJed Brown PetscInt *offsets, **closures; 4506552f7358SJed Brown PetscInt *meet[2]; 4507552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 450824c766afSToby Isaac PetscInt p, h, c, m, mc; 4509552f7358SJed Brown 4510552f7358SJed Brown PetscFunctionBegin; 4511552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4512dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4513dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveredPoints, 4); 4514064a246eSJacob Faibussowitsch PetscValidPointer(coveredPoints, 5); 4515552f7358SJed Brown 45169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 45179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 45189566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 45196302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 452024c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 45219566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 45229566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4523552f7358SJed Brown 4524552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4525552f7358SJed Brown PetscInt closureSize; 4526552f7358SJed Brown 45279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 45280d644c17SKarl Rupp 4529552f7358SJed Brown offsets[p*(height+2)+0] = 0; 4530552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4531552f7358SJed Brown PetscInt pStart, pEnd, i; 4532552f7358SJed Brown 45339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4534552f7358SJed Brown for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4535552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4536552f7358SJed Brown offsets[p*(height+2)+h+1] = i; 4537552f7358SJed Brown break; 4538552f7358SJed Brown } 4539552f7358SJed Brown } 4540552f7358SJed Brown if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4541552f7358SJed Brown } 454263a3b9bcSJacob 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); 4543552f7358SJed Brown } 4544552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4545552f7358SJed Brown PetscInt dof; 4546552f7358SJed Brown 4547552f7358SJed Brown /* Copy in cone of first point */ 4548552f7358SJed Brown dof = offsets[h+1] - offsets[h]; 4549552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4550552f7358SJed Brown meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4551552f7358SJed Brown } 4552552f7358SJed Brown /* Check each successive cone */ 4553552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4554552f7358SJed Brown PetscInt newMeetSize = 0; 4555552f7358SJed Brown 4556552f7358SJed Brown dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4557552f7358SJed Brown for (c = 0; c < dof; ++c) { 4558552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4559552f7358SJed Brown 4560552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4561552f7358SJed Brown if (point == meet[i][m]) { 4562552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4563552f7358SJed Brown break; 4564552f7358SJed Brown } 4565552f7358SJed Brown } 4566552f7358SJed Brown } 4567552f7358SJed Brown meetSize = newMeetSize; 4568552f7358SJed Brown i = 1-i; 4569552f7358SJed Brown } 4570552f7358SJed Brown if (meetSize) break; 4571552f7358SJed Brown } 4572552f7358SJed Brown *numCoveredPoints = meetSize; 4573552f7358SJed Brown *coveredPoints = meet[i]; 4574552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 45759566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 4576552f7358SJed Brown } 45779566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 45789566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 45796302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1-i])); 4580552f7358SJed Brown PetscFunctionReturn(0); 4581552f7358SJed Brown } 4582552f7358SJed Brown 45834e3744c5SMatthew G. Knepley /*@C 45844e3744c5SMatthew G. Knepley DMPlexEqual - Determine if two DMs have the same topology 45854e3744c5SMatthew G. Knepley 45864e3744c5SMatthew G. Knepley Not Collective 45874e3744c5SMatthew G. Knepley 45884e3744c5SMatthew G. Knepley Input Parameters: 45894e3744c5SMatthew G. Knepley + dmA - A DMPlex object 45904e3744c5SMatthew G. Knepley - dmB - A DMPlex object 45914e3744c5SMatthew G. Knepley 45924e3744c5SMatthew G. Knepley Output Parameters: 45934e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical 45944e3744c5SMatthew G. Knepley 45954e3744c5SMatthew G. Knepley Level: intermediate 45964e3744c5SMatthew G. Knepley 45974e3744c5SMatthew G. Knepley Notes: 45984e3744c5SMatthew G. Knepley We are not solving graph isomorphism, so we do not permutation. 45994e3744c5SMatthew G. Knepley 4600db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 46014e3744c5SMatthew G. Knepley @*/ 46024e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 46034e3744c5SMatthew G. Knepley { 46044e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 46054e3744c5SMatthew G. Knepley 46064e3744c5SMatthew G. Knepley PetscFunctionBegin; 46074e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 46084e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4609dadcf809SJacob Faibussowitsch PetscValidBoolPointer(equal, 3); 46104e3744c5SMatthew G. Knepley 46114e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 46129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 46139566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 46144e3744c5SMatthew G. Knepley if (depth != depthB) PetscFunctionReturn(0); 46159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 46169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 46174e3744c5SMatthew G. Knepley if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 46184e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 46194e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 46204e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 46214e3744c5SMatthew G. Knepley 46229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 46239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 46249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 46259566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 46269566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 46279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 46284e3744c5SMatthew G. Knepley if (coneSize != coneSizeB) PetscFunctionReturn(0); 46294e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 46304e3744c5SMatthew G. Knepley if (cone[c] != coneB[c]) PetscFunctionReturn(0); 46314e3744c5SMatthew G. Knepley if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 46324e3744c5SMatthew G. Knepley } 46339566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 46349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 46359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 46369566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 46374e3744c5SMatthew G. Knepley if (supportSize != supportSizeB) PetscFunctionReturn(0); 46384e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 46394e3744c5SMatthew G. Knepley if (support[s] != supportB[s]) PetscFunctionReturn(0); 46404e3744c5SMatthew G. Knepley } 46414e3744c5SMatthew G. Knepley } 46424e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 46434e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 46444e3744c5SMatthew G. Knepley } 46454e3744c5SMatthew G. Knepley 46467cd05799SMatthew G. Knepley /*@C 46477cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 46487cd05799SMatthew G. Knepley 46497cd05799SMatthew G. Knepley Not Collective 46507cd05799SMatthew G. Knepley 46517cd05799SMatthew G. Knepley Input Parameters: 46527cd05799SMatthew G. Knepley + dm - The DMPlex 46537cd05799SMatthew G. Knepley . cellDim - The cell dimension 46547cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 46557cd05799SMatthew G. Knepley 46567cd05799SMatthew G. Knepley Output Parameters: 46577cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 46587cd05799SMatthew G. Knepley 46597cd05799SMatthew G. Knepley Level: developer 46607cd05799SMatthew G. Knepley 46617cd05799SMatthew G. Knepley Notes: 46627cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 46637cd05799SMatthew G. Knepley 4664db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 46657cd05799SMatthew G. Knepley @*/ 466618ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4667a6dfd86eSKarl Rupp { 466882f516ccSBarry Smith MPI_Comm comm; 4669552f7358SJed Brown 4670552f7358SJed Brown PetscFunctionBegin; 46719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm,&comm)); 4672dadcf809SJacob Faibussowitsch PetscValidIntPointer(numFaceVertices,4); 4673552f7358SJed Brown switch (cellDim) { 4674552f7358SJed Brown case 0: 4675552f7358SJed Brown *numFaceVertices = 0; 4676552f7358SJed Brown break; 4677552f7358SJed Brown case 1: 4678552f7358SJed Brown *numFaceVertices = 1; 4679552f7358SJed Brown break; 4680552f7358SJed Brown case 2: 4681552f7358SJed Brown switch (numCorners) { 468219436ca2SJed Brown case 3: /* triangle */ 468319436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4684552f7358SJed Brown break; 468519436ca2SJed Brown case 4: /* quadrilateral */ 468619436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4687552f7358SJed Brown break; 468819436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 468919436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4690552f7358SJed Brown break; 469119436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 469219436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4693552f7358SJed Brown break; 4694552f7358SJed Brown default: 469563a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4696552f7358SJed Brown } 4697552f7358SJed Brown break; 4698552f7358SJed Brown case 3: 4699552f7358SJed Brown switch (numCorners) { 470019436ca2SJed Brown case 4: /* tetradehdron */ 470119436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 4702552f7358SJed Brown break; 470319436ca2SJed Brown case 6: /* tet cohesive cells */ 470419436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4705552f7358SJed Brown break; 470619436ca2SJed Brown case 8: /* hexahedron */ 470719436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4708552f7358SJed Brown break; 470919436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 471019436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4711552f7358SJed Brown break; 471219436ca2SJed Brown case 10: /* quadratic tetrahedron */ 471319436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4714552f7358SJed Brown break; 471519436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 471619436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4717552f7358SJed Brown break; 471819436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 471919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4720552f7358SJed Brown break; 472119436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 472219436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 4723552f7358SJed Brown break; 4724552f7358SJed Brown default: 472563a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4726552f7358SJed Brown } 4727552f7358SJed Brown break; 4728552f7358SJed Brown default: 472963a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 4730552f7358SJed Brown } 4731552f7358SJed Brown PetscFunctionReturn(0); 4732552f7358SJed Brown } 4733552f7358SJed Brown 4734552f7358SJed Brown /*@ 4735aa50250dSMatthew G. Knepley DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4736552f7358SJed Brown 4737552f7358SJed Brown Not Collective 4738552f7358SJed Brown 4739aa50250dSMatthew G. Knepley Input Parameter: 4740552f7358SJed Brown . dm - The DMPlex object 4741552f7358SJed Brown 4742aa50250dSMatthew G. Knepley Output Parameter: 4743aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth 4744552f7358SJed Brown 4745552f7358SJed Brown Level: developer 4746552f7358SJed Brown 4747db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 4748aa50250dSMatthew G. Knepley @*/ 4749aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4750aa50250dSMatthew G. Knepley { 4751aa50250dSMatthew G. Knepley PetscFunctionBegin; 4752aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4753aa50250dSMatthew G. Knepley PetscValidPointer(depthLabel, 2); 4754c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 4755aa50250dSMatthew G. Knepley PetscFunctionReturn(0); 4756aa50250dSMatthew G. Knepley } 4757aa50250dSMatthew G. Knepley 4758aa50250dSMatthew G. Knepley /*@ 4759aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 4760aa50250dSMatthew G. Knepley 4761aa50250dSMatthew G. Knepley Not Collective 4762aa50250dSMatthew G. Knepley 4763aa50250dSMatthew G. Knepley Input Parameter: 4764aa50250dSMatthew G. Knepley . dm - The DMPlex object 4765aa50250dSMatthew G. Knepley 4766aa50250dSMatthew G. Knepley Output Parameter: 4767aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 4768aa50250dSMatthew G. Knepley 4769aa50250dSMatthew G. Knepley Level: developer 4770552f7358SJed Brown 4771b1bb481bSMatthew Knepley Notes: 4772b1bb481bSMatthew Knepley This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4773dc287ab2SVaclav Hapla The point depth is described more in detail in DMPlexGetDepthStratum(). 4774dc287ab2SVaclav Hapla An empty mesh gives -1. 4775b1bb481bSMatthew Knepley 4776db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 4777552f7358SJed Brown @*/ 4778552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4779552f7358SJed Brown { 4780aa50250dSMatthew G. Knepley DMLabel label; 4781aa50250dSMatthew G. Knepley PetscInt d = 0; 4782552f7358SJed Brown 4783552f7358SJed Brown PetscFunctionBegin; 4784552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4785dadcf809SJacob Faibussowitsch PetscValidIntPointer(depth, 2); 47869566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 47879566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 4788552f7358SJed Brown *depth = d-1; 4789552f7358SJed Brown PetscFunctionReturn(0); 4790552f7358SJed Brown } 4791552f7358SJed Brown 4792552f7358SJed Brown /*@ 4793552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4794552f7358SJed Brown 4795552f7358SJed Brown Not Collective 4796552f7358SJed Brown 4797552f7358SJed Brown Input Parameters: 4798552f7358SJed Brown + dm - The DMPlex object 4799570fa34dSVaclav Hapla - depth - The requested depth 4800552f7358SJed Brown 4801552f7358SJed Brown Output Parameters: 4802552f7358SJed Brown + start - The first point at this depth 4803552f7358SJed Brown - end - One beyond the last point at this depth 4804552f7358SJed Brown 4805647867b2SJed Brown Notes: 4806647867b2SJed Brown Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4807647867b2SJed Brown often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4808647867b2SJed Brown higher dimension, e.g., "edges". 4809647867b2SJed Brown 4810552f7358SJed Brown Level: developer 4811552f7358SJed Brown 4812db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 4813552f7358SJed Brown @*/ 4814570fa34dSVaclav Hapla PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 48150adebc6cSBarry Smith { 4816aa50250dSMatthew G. Knepley DMLabel label; 481763d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 4818552f7358SJed Brown 4819552f7358SJed Brown PetscFunctionBegin; 4820552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4821dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4822dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48239566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 48240d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4825570fa34dSVaclav Hapla if (depth < 0) { 482663d1a920SMatthew G. Knepley if (start) *start = pStart; 482763d1a920SMatthew G. Knepley if (end) *end = pEnd; 482863d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4829552f7358SJed Brown } 48309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 483128b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4832570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 4833552f7358SJed Brown PetscFunctionReturn(0); 4834552f7358SJed Brown } 4835552f7358SJed Brown 4836552f7358SJed Brown /*@ 4837552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4838552f7358SJed Brown 4839552f7358SJed Brown Not Collective 4840552f7358SJed Brown 4841552f7358SJed Brown Input Parameters: 4842552f7358SJed Brown + dm - The DMPlex object 4843570fa34dSVaclav Hapla - height - The requested height 4844552f7358SJed Brown 4845552f7358SJed Brown Output Parameters: 4846552f7358SJed Brown + start - The first point at this height 4847552f7358SJed Brown - end - One beyond the last point at this height 4848552f7358SJed Brown 4849647867b2SJed Brown Notes: 4850647867b2SJed Brown Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4851647867b2SJed Brown points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4852647867b2SJed Brown stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4853647867b2SJed Brown 4854552f7358SJed Brown Level: developer 4855552f7358SJed Brown 4856db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4857552f7358SJed Brown @*/ 4858570fa34dSVaclav Hapla PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 48590adebc6cSBarry Smith { 4860aa50250dSMatthew G. Knepley DMLabel label; 486163d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 4862552f7358SJed Brown 4863552f7358SJed Brown PetscFunctionBegin; 4864552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4865dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4866dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 48680d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4869570fa34dSVaclav Hapla if (height < 0) { 487063d1a920SMatthew G. Knepley if (start) *start = pStart; 487163d1a920SMatthew G. Knepley if (end) *end = pEnd; 487263d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4873552f7358SJed Brown } 48749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 487528b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 48769566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 4877570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth-1-height, start, end)); 4878552f7358SJed Brown PetscFunctionReturn(0); 4879552f7358SJed Brown } 4880552f7358SJed Brown 4881ba2698f1SMatthew G. Knepley /*@ 4882ba2698f1SMatthew G. Knepley DMPlexGetPointDepth - Get the depth of a given point 4883ba2698f1SMatthew G. Knepley 4884ba2698f1SMatthew G. Knepley Not Collective 4885ba2698f1SMatthew G. Knepley 4886d8d19677SJose E. Roman Input Parameters: 4887ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4888ba2698f1SMatthew G. Knepley - point - The point 4889ba2698f1SMatthew G. Knepley 4890ba2698f1SMatthew G. Knepley Output Parameter: 4891ba2698f1SMatthew G. Knepley . depth - The depth of the point 4892ba2698f1SMatthew G. Knepley 4893ba2698f1SMatthew G. Knepley Level: intermediate 4894ba2698f1SMatthew G. Knepley 4895db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4896ba2698f1SMatthew G. Knepley @*/ 4897ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4898ba2698f1SMatthew G. Knepley { 4899ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4900ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 490140a2aa30SMatthew G. Knepley PetscValidIntPointer(depth, 3); 49029566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 4903ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4904ba2698f1SMatthew G. Knepley } 4905ba2698f1SMatthew G. Knepley 4906ba2698f1SMatthew G. Knepley /*@ 49070c0a32dcSVaclav Hapla DMPlexGetPointHeight - Get the height of a given point 49080c0a32dcSVaclav Hapla 49090c0a32dcSVaclav Hapla Not Collective 49100c0a32dcSVaclav Hapla 4911d8d19677SJose E. Roman Input Parameters: 49120c0a32dcSVaclav Hapla + dm - The DMPlex object 49130c0a32dcSVaclav Hapla - point - The point 49140c0a32dcSVaclav Hapla 49150c0a32dcSVaclav Hapla Output Parameter: 49160c0a32dcSVaclav Hapla . height - The height of the point 49170c0a32dcSVaclav Hapla 49180c0a32dcSVaclav Hapla Level: intermediate 49190c0a32dcSVaclav Hapla 4920db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 49210c0a32dcSVaclav Hapla @*/ 49220c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 49230c0a32dcSVaclav Hapla { 49240c0a32dcSVaclav Hapla PetscInt n, pDepth; 49250c0a32dcSVaclav Hapla 49260c0a32dcSVaclav Hapla PetscFunctionBegin; 49270c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49280c0a32dcSVaclav Hapla PetscValidIntPointer(height, 3); 49299566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 49309566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 49310c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 49320c0a32dcSVaclav Hapla PetscFunctionReturn(0); 49330c0a32dcSVaclav Hapla } 49340c0a32dcSVaclav Hapla 49350c0a32dcSVaclav Hapla /*@ 4936ba2698f1SMatthew G. Knepley DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4937ba2698f1SMatthew G. Knepley 4938ba2698f1SMatthew G. Knepley Not Collective 4939ba2698f1SMatthew G. Knepley 4940ba2698f1SMatthew G. Knepley Input Parameter: 4941ba2698f1SMatthew G. Knepley . dm - The DMPlex object 4942ba2698f1SMatthew G. Knepley 4943ba2698f1SMatthew G. Knepley Output Parameter: 4944ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type 4945ba2698f1SMatthew G. Knepley 4946412e9a14SMatthew G. Knepley Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4947412e9a14SMatthew G. Knepley DMCreateLabel(dm, "celltype") beforehand. 4948412e9a14SMatthew G. Knepley 4949ba2698f1SMatthew G. Knepley Level: developer 4950ba2698f1SMatthew G. Knepley 4951db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 4952ba2698f1SMatthew G. Knepley @*/ 4953ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4954ba2698f1SMatthew G. Knepley { 4955ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4956ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4957ba2698f1SMatthew G. Knepley PetscValidPointer(celltypeLabel, 2); 49589566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 4959ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 4960ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4961ba2698f1SMatthew G. Knepley } 4962ba2698f1SMatthew G. Knepley 4963ba2698f1SMatthew G. Knepley /*@ 4964ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 4965ba2698f1SMatthew G. Knepley 4966ba2698f1SMatthew G. Knepley Not Collective 4967ba2698f1SMatthew G. Knepley 4968d8d19677SJose E. Roman Input Parameters: 4969ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4970ba2698f1SMatthew G. Knepley - cell - The cell 4971ba2698f1SMatthew G. Knepley 4972ba2698f1SMatthew G. Knepley Output Parameter: 4973ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 4974ba2698f1SMatthew G. Knepley 4975ba2698f1SMatthew G. Knepley Level: intermediate 4976ba2698f1SMatthew G. Knepley 4977db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 4978ba2698f1SMatthew G. Knepley @*/ 4979ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4980ba2698f1SMatthew G. Knepley { 4981ba2698f1SMatthew G. Knepley DMLabel label; 4982ba2698f1SMatthew G. Knepley PetscInt ct; 4983ba2698f1SMatthew G. Knepley 4984ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4985ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4986ba2698f1SMatthew G. Knepley PetscValidPointer(celltype, 3); 49879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 49889566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 498963a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 4990ba2698f1SMatthew G. Knepley *celltype = (DMPolytopeType) ct; 4991ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4992ba2698f1SMatthew G. Knepley } 4993ba2698f1SMatthew G. Knepley 4994412e9a14SMatthew G. Knepley /*@ 4995412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 4996412e9a14SMatthew G. Knepley 4997412e9a14SMatthew G. Knepley Not Collective 4998412e9a14SMatthew G. Knepley 4999412e9a14SMatthew G. Knepley Input Parameters: 5000412e9a14SMatthew G. Knepley + dm - The DMPlex object 5001412e9a14SMatthew G. Knepley . cell - The cell 5002412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5003412e9a14SMatthew G. Knepley 5004412e9a14SMatthew G. Knepley Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 5005412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5006412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5007412e9a14SMatthew G. Knepley DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 5008412e9a14SMatthew G. Knepley 5009412e9a14SMatthew G. Knepley Level: advanced 5010412e9a14SMatthew G. Knepley 5011db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5012412e9a14SMatthew G. Knepley @*/ 5013412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5014412e9a14SMatthew G. Knepley { 5015412e9a14SMatthew G. Knepley DMLabel label; 5016412e9a14SMatthew G. Knepley 5017412e9a14SMatthew G. Knepley PetscFunctionBegin; 5018412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 50209566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 5021412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 5022412e9a14SMatthew G. Knepley } 5023412e9a14SMatthew G. Knepley 50240adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 50250adebc6cSBarry Smith { 5026efe440bfSMatthew G. Knepley PetscSection section, s; 5027efe440bfSMatthew G. Knepley Mat m; 50283e922f36SToby Isaac PetscInt maxHeight; 5029552f7358SJed Brown 5030552f7358SJed Brown PetscFunctionBegin; 50319566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 50329566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 50339566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 50349566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 50359566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 50369566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 50379566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 50389566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 50399566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 50409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 50419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 50428f4c458bSMatthew G. Knepley 50439566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 50449566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5045552f7358SJed Brown PetscFunctionReturn(0); 5046552f7358SJed Brown } 5047552f7358SJed Brown 5048f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5049f19dbd58SToby Isaac { 5050*6858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 5051*6858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5052f19dbd58SToby Isaac 5053f19dbd58SToby Isaac PetscFunctionBegin; 5054f19dbd58SToby Isaac *field = NULL; 50559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 50569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 5057*6858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 5058*6858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5059f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 5060*6858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 5061*6858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5062f19dbd58SToby Isaac } 5063f19dbd58SToby Isaac PetscFunctionReturn(0); 5064f19dbd58SToby Isaac } 5065f19dbd58SToby Isaac 50667cd05799SMatthew G. Knepley /*@C 50677cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 50687cd05799SMatthew G. Knepley 50697cd05799SMatthew G. Knepley Not Collective 50707cd05799SMatthew G. Knepley 50717cd05799SMatthew G. Knepley Input Parameters: 50727cd05799SMatthew G. Knepley . dm - The DMPlex object 50737cd05799SMatthew G. Knepley 50747cd05799SMatthew G. Knepley Output Parameter: 50757cd05799SMatthew G. Knepley . section - The PetscSection object 50767cd05799SMatthew G. Knepley 50777cd05799SMatthew G. Knepley Level: developer 50787cd05799SMatthew G. Knepley 5079db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()` 50807cd05799SMatthew G. Knepley @*/ 50810adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 50820adebc6cSBarry Smith { 5083552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5084552f7358SJed Brown 5085552f7358SJed Brown PetscFunctionBegin; 5086552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5087552f7358SJed Brown if (section) *section = mesh->coneSection; 5088552f7358SJed Brown PetscFunctionReturn(0); 5089552f7358SJed Brown } 5090552f7358SJed Brown 50917cd05799SMatthew G. Knepley /*@C 50927cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 50937cd05799SMatthew G. Knepley 50947cd05799SMatthew G. Knepley Not Collective 50957cd05799SMatthew G. Knepley 50967cd05799SMatthew G. Knepley Input Parameters: 50977cd05799SMatthew G. Knepley . dm - The DMPlex object 50987cd05799SMatthew G. Knepley 50997cd05799SMatthew G. Knepley Output Parameter: 51007cd05799SMatthew G. Knepley . section - The PetscSection object 51017cd05799SMatthew G. Knepley 51027cd05799SMatthew G. Knepley Level: developer 51037cd05799SMatthew G. Knepley 5104db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 51057cd05799SMatthew G. Knepley @*/ 51068cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 51078cb4d582SMatthew G. Knepley { 51088cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 51098cb4d582SMatthew G. Knepley 51108cb4d582SMatthew G. Knepley PetscFunctionBegin; 51118cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51128cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 51138cb4d582SMatthew G. Knepley PetscFunctionReturn(0); 51148cb4d582SMatthew G. Knepley } 51158cb4d582SMatthew G. Knepley 51167cd05799SMatthew G. Knepley /*@C 51177cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 51187cd05799SMatthew G. Knepley 51197cd05799SMatthew G. Knepley Not Collective 51207cd05799SMatthew G. Knepley 51217cd05799SMatthew G. Knepley Input Parameters: 51227cd05799SMatthew G. Knepley . dm - The DMPlex object 51237cd05799SMatthew G. Knepley 51247cd05799SMatthew G. Knepley Output Parameter: 51257cd05799SMatthew G. Knepley . cones - The cone for each point 51267cd05799SMatthew G. Knepley 51277cd05799SMatthew G. Knepley Level: developer 51287cd05799SMatthew G. Knepley 5129db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 51307cd05799SMatthew G. Knepley @*/ 5131a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5132a6dfd86eSKarl Rupp { 5133552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5134552f7358SJed Brown 5135552f7358SJed Brown PetscFunctionBegin; 5136552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5137552f7358SJed Brown if (cones) *cones = mesh->cones; 5138552f7358SJed Brown PetscFunctionReturn(0); 5139552f7358SJed Brown } 5140552f7358SJed Brown 51417cd05799SMatthew G. Knepley /*@C 51427cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 51437cd05799SMatthew G. Knepley 51447cd05799SMatthew G. Knepley Not Collective 51457cd05799SMatthew G. Knepley 51467cd05799SMatthew G. Knepley Input Parameters: 51477cd05799SMatthew G. Knepley . dm - The DMPlex object 51487cd05799SMatthew G. Knepley 51497cd05799SMatthew G. Knepley Output Parameter: 5150b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 51517cd05799SMatthew G. Knepley 51527cd05799SMatthew G. Knepley Level: developer 51537cd05799SMatthew G. Knepley 5154b5a892a1SMatthew G. Knepley Notes: 5155b5a892a1SMatthew G. Knepley The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5156b5a892a1SMatthew G. Knepley 5157b5a892a1SMatthew G. Knepley The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5158b5a892a1SMatthew G. Knepley 5159db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()` 51607cd05799SMatthew G. Knepley @*/ 5161a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5162a6dfd86eSKarl Rupp { 5163552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5164552f7358SJed Brown 5165552f7358SJed Brown PetscFunctionBegin; 5166552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5167552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5168552f7358SJed Brown PetscFunctionReturn(0); 5169552f7358SJed Brown } 5170552f7358SJed Brown 5171552f7358SJed Brown /******************************** FEM Support **********************************/ 5172552f7358SJed Brown 51739e8305c2SJed Brown /* 51749e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 51759e8305c2SJed Brown representing a line in the section. 51769e8305c2SJed Brown */ 51779e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 51789e8305c2SJed Brown { 51799e8305c2SJed Brown PetscFunctionBeginHot; 51809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5181a433471fSStefano Zampini if (line < 0) { 5182a433471fSStefano Zampini *k = 0; 5183a433471fSStefano Zampini *Nc = 0; 5184a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 51859e8305c2SJed Brown *k = 1; 51869e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 51879e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 51889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 51899e8305c2SJed Brown *k = *k / *Nc + 1; 51909e8305c2SJed Brown } 51919e8305c2SJed Brown PetscFunctionReturn(0); 51929e8305c2SJed Brown } 51939e8305c2SJed Brown 5194a4355906SMatthew Knepley /*@ 5195bc1eb3faSJed Brown 5196bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5197bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 51981bb6d2a8SBarry Smith section provided (or the section of the DM). 5199a4355906SMatthew Knepley 5200a4355906SMatthew Knepley Input Parameters: 5201a4355906SMatthew Knepley + dm - The DM 5202a4355906SMatthew Knepley . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5203a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section 5204a4355906SMatthew Knepley 5205a4355906SMatthew Knepley Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5206a4355906SMatthew Knepley degree of the basis. 5207a4355906SMatthew Knepley 5208bc1eb3faSJed Brown Example: 5209bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5210bc1eb3faSJed Brown .vb 5211bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5212bc1eb3faSJed Brown 5213bc1eb3faSJed Brown v4 -- e6 -- v3 5214bc1eb3faSJed Brown | | 5215bc1eb3faSJed Brown e7 c0 e8 5216bc1eb3faSJed Brown | | 5217bc1eb3faSJed Brown v1 -- e5 -- v2 5218bc1eb3faSJed Brown .ve 5219bc1eb3faSJed Brown 5220bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5221bc1eb3faSJed Brown dofs in the order of points, e.g., 5222bc1eb3faSJed Brown .vb 5223bc1eb3faSJed Brown c0 -> [0,1,2,3] 5224bc1eb3faSJed Brown v1 -> [4] 5225bc1eb3faSJed Brown ... 5226bc1eb3faSJed Brown e5 -> [8, 9] 5227bc1eb3faSJed Brown .ve 5228bc1eb3faSJed Brown 5229bc1eb3faSJed Brown which corresponds to the dofs 5230bc1eb3faSJed Brown .vb 5231bc1eb3faSJed Brown 6 10 11 7 5232bc1eb3faSJed Brown 13 2 3 15 5233bc1eb3faSJed Brown 12 0 1 14 5234bc1eb3faSJed Brown 4 8 9 5 5235bc1eb3faSJed Brown .ve 5236bc1eb3faSJed Brown 5237bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5238bc1eb3faSJed Brown .vb 5239bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5240bc1eb3faSJed Brown .ve 5241bc1eb3faSJed Brown 5242bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5243bc1eb3faSJed Brown .vb 5244bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5245bc1eb3faSJed Brown .ve 5246bc1eb3faSJed Brown 5247a4355906SMatthew Knepley Level: developer 5248a4355906SMatthew Knepley 5249db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5250a4355906SMatthew Knepley @*/ 5251bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 52523194fc30SMatthew G. Knepley { 52537391a63aSMatthew G. Knepley DMLabel label; 5254bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 52559e8305c2SJed Brown PetscBool vertexchart; 52563194fc30SMatthew G. Knepley 52573194fc30SMatthew G. Knepley PetscFunctionBegin; 52589566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5259a433471fSStefano Zampini if (dim < 1) PetscFunctionReturn(0); 5260a433471fSStefano Zampini if (point < 0) { 5261a433471fSStefano Zampini PetscInt sStart,sEnd; 5262a433471fSStefano Zampini 52639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5264a433471fSStefano Zampini point = sEnd-sStart ? sStart : point; 5265a433471fSStefano Zampini } 52669566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52679566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 52689566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 52697391a63aSMatthew G. Knepley if (depth == 1) {eStart = point;} 52707391a63aSMatthew G. Knepley else if (depth == dim) { 52717391a63aSMatthew G. Knepley const PetscInt *cone; 52727391a63aSMatthew G. Knepley 52739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5274d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5275d4e6627bSStefano Zampini else if (dim == 3) { 5276d4e6627bSStefano Zampini const PetscInt *cone2; 52779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5278d4e6627bSStefano Zampini eStart = cone2[0]; 527963a3b9bcSJacob 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); 528063a3b9bcSJacob 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); 52819e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 52829e8305c2SJed Brown PetscInt pStart,pEnd,cStart,cEnd; 52839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd)); 52849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&cStart,&cEnd)); 5285796d0a68SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5286796d0a68SJed Brown else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5287796d0a68SJed Brown else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 52889e8305c2SJed Brown } 52899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5290bb197d40SJed Brown for (PetscInt d=1; d<=dim; d++) { 5291bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5292bb197d40SJed Brown PetscInt *perm; 5293bb197d40SJed Brown 52943194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 52959566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5296bb197d40SJed Brown size += PetscPowInt(k+1, d)*Nc; 52973194fc30SMatthew G. Knepley } 52989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 52993194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5300bb197d40SJed Brown switch (d) { 5301babf31e0SJed Brown case 1: 53029566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5303babf31e0SJed Brown /* 5304babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5305babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5306babf31e0SJed Brown */ 5307babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5308babf31e0SJed Brown for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5309babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5310babf31e0SJed Brown foffset = offset; 5311babf31e0SJed Brown break; 531289eabcffSMatthew G. Knepley case 2: 53133194fc30SMatthew 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} */ 53149566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 53153194fc30SMatthew G. Knepley /* The SEM order is 53163194fc30SMatthew G. Knepley 53173194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 531889eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 53193194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 53203194fc30SMatthew G. Knepley */ 53213194fc30SMatthew G. Knepley { 53223194fc30SMatthew G. Knepley const PetscInt of = 0; 53233194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k-1); 53243194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k-1); 53253194fc30SMatthew G. Knepley const PetscInt oet = oer + (k-1); 53263194fc30SMatthew G. Knepley const PetscInt oel = oet + (k-1); 53273194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k-1); 53283194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 53293194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 53303194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 53313194fc30SMatthew G. Knepley PetscInt o; 53323194fc30SMatthew G. Knepley 53333194fc30SMatthew G. Knepley /* bottom */ 53343194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 53353194fc30SMatthew G. Knepley for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53363194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 53373194fc30SMatthew G. Knepley /* middle */ 53383194fc30SMatthew G. Knepley for (i = 0; i < k-1; ++i) { 53393194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 53403194fc30SMatthew 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; 53413194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 53423194fc30SMatthew G. Knepley } 53433194fc30SMatthew G. Knepley /* top */ 53443194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 53453194fc30SMatthew G. Knepley for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53463194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 53473194fc30SMatthew G. Knepley foffset = offset; 53483194fc30SMatthew G. Knepley } 534989eabcffSMatthew G. Knepley break; 535089eabcffSMatthew G. Knepley case 3: 535189eabcffSMatthew G. Knepley /* The original hex closure is 535289eabcffSMatthew G. Knepley 535389eabcffSMatthew G. Knepley {c, 535489eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 535589eabcffSMatthew 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, 535689eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 535789eabcffSMatthew G. Knepley */ 53589566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 535989eabcffSMatthew G. Knepley /* The SEM order is 536089eabcffSMatthew G. Knepley Bottom Slice 536189eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 536289eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 536389eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 536489eabcffSMatthew G. Knepley 536589eabcffSMatthew G. Knepley Middle Slice (j) 536689eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 536789eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 536889eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 536989eabcffSMatthew G. Knepley 537089eabcffSMatthew G. Knepley Top Slice 537189eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 537289eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 537389eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 537489eabcffSMatthew G. Knepley */ 537589eabcffSMatthew G. Knepley { 537689eabcffSMatthew G. Knepley const PetscInt oc = 0; 537789eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 537889eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k-1); 537989eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k-1); 538089eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k-1); 538189eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k-1); 538289eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k-1); 538389eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k-1); 538489eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k-1); 538589eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k-1); 538689eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k-1); 538789eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k-1); 538889eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k-1); 538989eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k-1); 539089eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k-1); 539189eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k-1); 539289eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k-1); 539389eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k-1); 539489eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k-1); 539589eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k-1); 539689eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 539789eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 539889eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 539989eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 540089eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 540189eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 540289eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 540389eabcffSMatthew G. Knepley PetscInt o, n; 540489eabcffSMatthew G. Knepley 540589eabcffSMatthew G. Knepley /* Bottom Slice */ 540689eabcffSMatthew G. Knepley /* bottom */ 540789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 540889eabcffSMatthew G. Knepley for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 540989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 541089eabcffSMatthew G. Knepley /* middle */ 541189eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 541289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5413316b7f87SMax 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;} 541489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 54153194fc30SMatthew G. Knepley } 541689eabcffSMatthew G. Knepley /* top */ 541789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 541889eabcffSMatthew G. Knepley for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 541989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 542089eabcffSMatthew G. Knepley 542189eabcffSMatthew G. Knepley /* Middle Slice */ 542289eabcffSMatthew G. Knepley for (j = 0; j < k-1; ++j) { 542389eabcffSMatthew G. Knepley /* bottom */ 542489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 542589eabcffSMatthew 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; 542689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 542789eabcffSMatthew G. Knepley /* middle */ 542889eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 542989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 543089eabcffSMatthew 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; 543189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 543289eabcffSMatthew G. Knepley } 543389eabcffSMatthew G. Knepley /* top */ 543489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 543589eabcffSMatthew 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; 543689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 543789eabcffSMatthew G. Knepley } 543889eabcffSMatthew G. Knepley 543989eabcffSMatthew G. Knepley /* Top Slice */ 544089eabcffSMatthew G. Knepley /* bottom */ 544189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 544289eabcffSMatthew G. Knepley for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 544389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 544489eabcffSMatthew G. Knepley /* middle */ 544589eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 544689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 544789eabcffSMatthew 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; 544889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 544989eabcffSMatthew G. Knepley } 545089eabcffSMatthew G. Knepley /* top */ 545189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 545289eabcffSMatthew G. Knepley for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 545389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 545489eabcffSMatthew G. Knepley 545589eabcffSMatthew G. Knepley foffset = offset; 545689eabcffSMatthew G. Knepley } 545789eabcffSMatthew G. Knepley break; 545863a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 545989eabcffSMatthew G. Knepley } 546089eabcffSMatthew G. Knepley } 546163a3b9bcSJacob Faibussowitsch PetscCheck(offset == size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 54623194fc30SMatthew G. Knepley /* Check permutation */ 54633194fc30SMatthew G. Knepley { 54643194fc30SMatthew G. Knepley PetscInt *check; 54653194fc30SMatthew G. Knepley 54669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 54671dca8a05SBarry Smith for (i = 0; i < size; ++i) { 54681dca8a05SBarry Smith check[i] = -1; 54691dca8a05SBarry 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]); 54701dca8a05SBarry Smith } 54713194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 54721dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 54739566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 54743194fc30SMatthew G. Knepley } 54759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm)); 5476a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5477a05c9aa3SJed Brown PetscInt *loc_perm; 54789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size*2, &loc_perm)); 5479a05c9aa3SJed Brown for (PetscInt i=0; i<size; i++) { 5480a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5481a05c9aa3SJed Brown loc_perm[size+i] = size + perm[i]; 5482a05c9aa3SJed Brown } 54839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm)); 5484a05c9aa3SJed Brown } 5485bb197d40SJed Brown } 54863194fc30SMatthew G. Knepley PetscFunctionReturn(0); 54873194fc30SMatthew G. Knepley } 54883194fc30SMatthew G. Knepley 5489e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5490e071409bSToby Isaac { 5491e071409bSToby Isaac PetscDS prob; 5492e071409bSToby Isaac PetscInt depth, Nf, h; 5493e071409bSToby Isaac DMLabel label; 5494e071409bSToby Isaac 5495e071409bSToby Isaac PetscFunctionBeginHot; 54969566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 5497e071409bSToby Isaac Nf = prob->Nf; 5498e071409bSToby Isaac label = dm->depthLabel; 5499e071409bSToby Isaac *dspace = NULL; 5500e071409bSToby Isaac if (field < Nf) { 5501e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5502e071409bSToby Isaac 5503e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5504e071409bSToby Isaac PetscDualSpace dsp; 5505e071409bSToby Isaac 55069566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp)); 55079566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label,&depth)); 55089566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label,point,&h)); 5509e071409bSToby Isaac h = depth - 1 - h; 5510e071409bSToby Isaac if (h) { 55119566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp,h,dspace)); 5512e071409bSToby Isaac } else { 5513e071409bSToby Isaac *dspace = dsp; 5514e071409bSToby Isaac } 5515e071409bSToby Isaac } 5516e071409bSToby Isaac } 5517e071409bSToby Isaac PetscFunctionReturn(0); 5518e071409bSToby Isaac } 5519e071409bSToby Isaac 55209fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5521a6dfd86eSKarl Rupp { 5522552f7358SJed Brown PetscScalar *array, *vArray; 5523d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 55241a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5525552f7358SJed Brown 55261b406b76SMatthew G. Knepley PetscFunctionBeginHot; 55279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 55289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 55299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 55309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 55313f7cbbe7SMatthew G. Knepley if (!values || !*values) { 55329df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55339df71ca4SMatthew G. Knepley PetscInt dof; 5534d9917b9dSMatthew G. Knepley 55359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55369df71ca4SMatthew G. Knepley size += dof; 55379df71ca4SMatthew G. Knepley } 55389df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55399df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55402a3aaacfSMatthew G. Knepley PetscInt dof; 55415a1bb5cfSMatthew G. Knepley 55425a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55445a1bb5cfSMatthew G. Knepley size += dof; 55455a1bb5cfSMatthew G. Knepley } 55463f7cbbe7SMatthew G. Knepley if (!values) { 55473f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 55483f7cbbe7SMatthew G. Knepley PetscFunctionReturn(0); 55493f7cbbe7SMatthew G. Knepley } 55509566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 5551982e9ed1SMatthew G. Knepley } else { 5552982e9ed1SMatthew G. Knepley array = *values; 5553982e9ed1SMatthew G. Knepley } 55549df71ca4SMatthew G. Knepley size = 0; 55559566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &vArray)); 55569df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55579df71ca4SMatthew G. Knepley PetscInt dof, off, d; 55589df71ca4SMatthew G. Knepley PetscScalar *varr; 5559d9917b9dSMatthew G. Knepley 55609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 55629df71ca4SMatthew G. Knepley varr = &vArray[off]; 55631a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55641a271a75SMatthew G. Knepley array[offset] = varr[d]; 55659df71ca4SMatthew G. Knepley } 55669df71ca4SMatthew G. Knepley size += dof; 55679df71ca4SMatthew G. Knepley } 55689df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55699df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55709df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 55715a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 55725a1bb5cfSMatthew G. Knepley PetscScalar *varr; 55735a1bb5cfSMatthew G. Knepley 557452ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 55775a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 55785a1bb5cfSMatthew G. Knepley if (o >= 0) { 55791a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55801a271a75SMatthew G. Knepley array[offset] = varr[d]; 55815a1bb5cfSMatthew G. Knepley } 55825a1bb5cfSMatthew G. Knepley } else { 55831a271a75SMatthew G. Knepley for (d = dof-1; d >= 0; --d, ++offset) { 55841a271a75SMatthew G. Knepley array[offset] = varr[d]; 55855a1bb5cfSMatthew G. Knepley } 55865a1bb5cfSMatthew G. Knepley } 55879df71ca4SMatthew G. Knepley size += dof; 55885a1bb5cfSMatthew G. Knepley } 55899566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &vArray)); 55909df71ca4SMatthew G. Knepley if (!*values) { 55915a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 55925a1bb5cfSMatthew G. Knepley *values = array; 55939df71ca4SMatthew G. Knepley } else { 559463a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 55958c312ff3SMatthew G. Knepley *csize = size; 55969df71ca4SMatthew G. Knepley } 55975a1bb5cfSMatthew G. Knepley PetscFunctionReturn(0); 55985a1bb5cfSMatthew G. Knepley } 5599d9917b9dSMatthew G. Knepley 560027f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 56019fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 560227f02ce8SMatthew G. Knepley { 560327f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 560427f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 560527f02ce8SMatthew G. Knepley 56069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 560727f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 560827f02ce8SMatthew G. Knepley const PetscInt r = points[p*2]; 560927f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 561027f02ce8SMatthew G. Knepley points[q*2] = r; 561127f02ce8SMatthew G. Knepley points[q*2+1] = points[p*2+1]; 561227f02ce8SMatthew G. Knepley ++q; 561327f02ce8SMatthew G. Knepley } 561427f02ce8SMatthew G. Knepley } 561527f02ce8SMatthew G. Knepley *numPoints = q; 561627f02ce8SMatthew G. Knepley return 0; 561727f02ce8SMatthew G. Knepley } 561827f02ce8SMatthew G. Knepley 561997529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 56201dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5621923c78e0SToby Isaac { 562227f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 5623923c78e0SToby Isaac PetscInt np, *pts = NULL; 5624923c78e0SToby Isaac 5625923c78e0SToby Isaac PetscFunctionBeginHot; 56269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints)); 562727f02ce8SMatthew G. Knepley if (*clPoints) { 5628923c78e0SToby Isaac PetscInt dof, off; 5629923c78e0SToby Isaac 56309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 56319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 56329566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 5633923c78e0SToby Isaac np = dof/2; 5634923c78e0SToby Isaac pts = (PetscInt *) &cla[off]; 563527f02ce8SMatthew G. Knepley } else { 56369566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts)); 56379566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 5638923c78e0SToby Isaac } 5639923c78e0SToby Isaac *numPoints = np; 5640923c78e0SToby Isaac *points = pts; 5641923c78e0SToby Isaac *clp = cla; 5642923c78e0SToby Isaac PetscFunctionReturn(0); 5643923c78e0SToby Isaac } 5644923c78e0SToby Isaac 56451dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5646923c78e0SToby Isaac { 5647923c78e0SToby Isaac PetscFunctionBeginHot; 5648923c78e0SToby Isaac if (!*clPoints) { 56499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 5650923c78e0SToby Isaac } else { 56519566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 5652923c78e0SToby Isaac } 5653923c78e0SToby Isaac *numPoints = 0; 5654923c78e0SToby Isaac *points = NULL; 5655923c78e0SToby Isaac *clSec = NULL; 5656923c78e0SToby Isaac *clPoints = NULL; 5657923c78e0SToby Isaac *clp = NULL; 5658923c78e0SToby Isaac PetscFunctionReturn(0); 5659923c78e0SToby Isaac } 5660923c78e0SToby Isaac 56619fbee547SJacob 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[]) 56621a271a75SMatthew G. Knepley { 56631a271a75SMatthew G. Knepley PetscInt offset = 0, p; 566497e99dd9SToby Isaac const PetscInt **perms = NULL; 566597e99dd9SToby Isaac const PetscScalar **flips = NULL; 56661a271a75SMatthew G. Knepley 56671a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5668fe02ba77SJed Brown *size = 0; 56699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 567097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 567197e99dd9SToby Isaac const PetscInt point = points[2*p]; 567297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 567397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 56741a271a75SMatthew G. Knepley PetscInt dof, off, d; 56751a271a75SMatthew G. Knepley const PetscScalar *varr; 56761a271a75SMatthew G. Knepley 56779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 56789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 56791a271a75SMatthew G. Knepley varr = &vArray[off]; 568097e99dd9SToby Isaac if (clperm) { 568197e99dd9SToby Isaac if (perm) { 568297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 56831a271a75SMatthew G. Knepley } else { 568497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 568597e99dd9SToby Isaac } 568697e99dd9SToby Isaac if (flip) { 568797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 568897e99dd9SToby Isaac } 568997e99dd9SToby Isaac } else { 569097e99dd9SToby Isaac if (perm) { 569197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 569297e99dd9SToby Isaac } else { 569397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 569497e99dd9SToby Isaac } 569597e99dd9SToby Isaac if (flip) { 569697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 56971a271a75SMatthew G. Knepley } 56981a271a75SMatthew G. Knepley } 569997e99dd9SToby Isaac offset += dof; 570097e99dd9SToby Isaac } 57019566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 57021a271a75SMatthew G. Knepley *size = offset; 57031a271a75SMatthew G. Knepley PetscFunctionReturn(0); 57041a271a75SMatthew G. Knepley } 57051a271a75SMatthew G. Knepley 57069fbee547SJacob 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[]) 57071a271a75SMatthew G. Knepley { 57081a271a75SMatthew G. Knepley PetscInt offset = 0, f; 57091a271a75SMatthew G. Knepley 57101a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5711fe02ba77SJed Brown *size = 0; 57121a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 571397e99dd9SToby Isaac PetscInt p; 571497e99dd9SToby Isaac const PetscInt **perms = NULL; 571597e99dd9SToby Isaac const PetscScalar **flips = NULL; 57161a271a75SMatthew G. Knepley 57179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 571897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 571997e99dd9SToby Isaac const PetscInt point = points[2*p]; 572097e99dd9SToby Isaac PetscInt fdof, foff, b; 57211a271a75SMatthew G. Knepley const PetscScalar *varr; 572297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 572397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 57241a271a75SMatthew G. Knepley 57259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 57269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 57271a271a75SMatthew G. Knepley varr = &vArray[foff]; 572897e99dd9SToby Isaac if (clperm) { 572997e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 573097e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 573197e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 57321a271a75SMatthew G. Knepley } else { 573397e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 573497e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 573597e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 57361a271a75SMatthew G. Knepley } 573797e99dd9SToby Isaac offset += fdof; 57381a271a75SMatthew G. Knepley } 57399566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 57401a271a75SMatthew G. Knepley } 57411a271a75SMatthew G. Knepley *size = offset; 57421a271a75SMatthew G. Knepley PetscFunctionReturn(0); 57431a271a75SMatthew G. Knepley } 57441a271a75SMatthew G. Knepley 5745552f7358SJed Brown /*@C 5746552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5747552f7358SJed Brown 5748552f7358SJed Brown Not collective 5749552f7358SJed Brown 5750552f7358SJed Brown Input Parameters: 5751552f7358SJed Brown + dm - The DM 5752552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section 5753552f7358SJed Brown . v - The local vector 57546b867d5aSJose E. Roman - point - The point in the DM 5755552f7358SJed Brown 57566b867d5aSJose E. Roman Input/Output Parameters: 57576b867d5aSJose E. Roman + csize - The size of the input values array, or NULL; on output the number of values in the closure 57586b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically; 57596b867d5aSJose E. Roman if the user provided NULL, it is a borrowed array and should not be freed 576022c1ee49SMatthew G. Knepley 576122c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 576222c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 576322c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation. 576422c1ee49SMatthew G. Knepley $ 576522c1ee49SMatthew G. Knepley $ A typical use could be 576622c1ee49SMatthew G. Knepley $ 576722c1ee49SMatthew G. Knepley $ values = NULL; 57689566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 576922c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 577022c1ee49SMatthew G. Knepley $ <Compute on closure> 577122c1ee49SMatthew G. Knepley $ } 57729566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 577322c1ee49SMatthew G. Knepley $ 577422c1ee49SMatthew G. Knepley $ or 577522c1ee49SMatthew G. Knepley $ 577622c1ee49SMatthew G. Knepley $ PetscMalloc1(clMaxSize, &values); 577722c1ee49SMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) { 577822c1ee49SMatthew G. Knepley $ clSize = clMaxSize; 57799566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 578022c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 578122c1ee49SMatthew G. Knepley $ <Compute on closure> 578222c1ee49SMatthew G. Knepley $ } 578322c1ee49SMatthew G. Knepley $ } 578422c1ee49SMatthew G. Knepley $ PetscFree(values); 5785552f7358SJed Brown 5786552f7358SJed Brown Fortran Notes: 5787552f7358SJed Brown Since it returns an array, this routine is only available in Fortran 90, and you must 5788552f7358SJed Brown include petsc.h90 in your code. 5789552f7358SJed Brown 5790552f7358SJed Brown The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5791552f7358SJed Brown 5792552f7358SJed Brown Level: intermediate 5793552f7358SJed Brown 5794db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5795552f7358SJed Brown @*/ 5796552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5797552f7358SJed Brown { 5798552f7358SJed Brown PetscSection clSection; 5799d9917b9dSMatthew G. Knepley IS clPoints; 5800552f7358SJed Brown PetscInt *points = NULL; 5801c459fbc1SJed Brown const PetscInt *clp, *perm; 5802c459fbc1SJed Brown PetscInt depth, numFields, numPoints, asize; 5803552f7358SJed Brown 5804d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 5805552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58069566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 58071a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 58081a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 58099566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 58109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5811552f7358SJed Brown if (depth == 1 && numFields < 2) { 58129566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5813552f7358SJed Brown PetscFunctionReturn(0); 5814552f7358SJed Brown } 58151a271a75SMatthew G. Knepley /* Get points */ 58169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5817c459fbc1SJed Brown /* Get sizes */ 5818c459fbc1SJed Brown asize = 0; 5819c459fbc1SJed Brown for (PetscInt p = 0; p < numPoints*2; p += 2) { 5820c459fbc1SJed Brown PetscInt dof; 58219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 58221a271a75SMatthew G. Knepley asize += dof; 5823552f7358SJed Brown } 5824c459fbc1SJed Brown if (values) { 5825c459fbc1SJed Brown const PetscScalar *vArray; 5826c459fbc1SJed Brown PetscInt size; 5827c459fbc1SJed Brown 5828c459fbc1SJed Brown if (*values) { 582963a3b9bcSJacob 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); 58309566063dSJacob Faibussowitsch } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 58319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm)); 58329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 58331a271a75SMatthew G. Knepley /* Get values */ 58349566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 58359566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 583663a3b9bcSJacob Faibussowitsch PetscCheck(asize == size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size); 58371a271a75SMatthew G. Knepley /* Cleanup array */ 58389566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5839d0f6b257SMatthew G. Knepley } 5840c459fbc1SJed Brown if (csize) *csize = asize; 5841c459fbc1SJed Brown /* Cleanup points */ 58429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5843552f7358SJed Brown PetscFunctionReturn(0); 5844552f7358SJed Brown } 5845552f7358SJed Brown 5846e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5847e5c487bfSMatthew G. Knepley { 5848e5c487bfSMatthew G. Knepley DMLabel depthLabel; 5849e5c487bfSMatthew G. Knepley PetscSection clSection; 5850e5c487bfSMatthew G. Knepley IS clPoints; 5851e5c487bfSMatthew G. Knepley PetscScalar *array; 5852e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 5853e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 5854c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 5855c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5856e5c487bfSMatthew G. Knepley 5857e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 5858e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58599566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 5860e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5861e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 58629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 58639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 58649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5865e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 58669566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5867e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5868e5c487bfSMatthew G. Knepley } 5869e5c487bfSMatthew G. Knepley /* Get points */ 58709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5871c459fbc1SJed Brown for (clsize=0,p=0; p<Np; p++) { 5872c459fbc1SJed Brown PetscInt dof; 58739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 5874c459fbc1SJed Brown clsize += dof; 5875c459fbc1SJed Brown } 58769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm)); 5877e5c487bfSMatthew G. Knepley /* Filter points */ 5878e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 5879e5c487bfSMatthew G. Knepley PetscInt dep; 5880e5c487bfSMatthew G. Knepley 58819566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 5882e5c487bfSMatthew G. Knepley if (dep != depth) continue; 5883e5c487bfSMatthew G. Knepley points[Np*2+0] = points[p]; 5884e5c487bfSMatthew G. Knepley points[Np*2+1] = points[p+1]; 5885e5c487bfSMatthew G. Knepley ++Np; 5886e5c487bfSMatthew G. Knepley } 5887e5c487bfSMatthew G. Knepley /* Get array */ 5888e5c487bfSMatthew G. Knepley if (!values || !*values) { 5889e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 5890e5c487bfSMatthew G. Knepley 5891e5c487bfSMatthew G. Knepley for (p = 0; p < Np*2; p += 2) { 58929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 5893e5c487bfSMatthew G. Knepley asize += dof; 5894e5c487bfSMatthew G. Knepley } 5895e5c487bfSMatthew G. Knepley if (!values) { 58969566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5897e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 5898e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5899e5c487bfSMatthew G. Knepley } 59009566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 5901e5c487bfSMatthew G. Knepley } else { 5902e5c487bfSMatthew G. Knepley array = *values; 5903e5c487bfSMatthew G. Knepley } 59049566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 5905e5c487bfSMatthew G. Knepley /* Get values */ 59069566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 59079566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 5908e5c487bfSMatthew G. Knepley /* Cleanup points */ 59099566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5910e5c487bfSMatthew G. Knepley /* Cleanup array */ 59119566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5912e5c487bfSMatthew G. Knepley if (!*values) { 5913e5c487bfSMatthew G. Knepley if (csize) *csize = size; 5914e5c487bfSMatthew G. Knepley *values = array; 5915e5c487bfSMatthew G. Knepley } else { 591663a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 5917e5c487bfSMatthew G. Knepley *csize = size; 5918e5c487bfSMatthew G. Knepley } 5919e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5920e5c487bfSMatthew G. Knepley } 5921e5c487bfSMatthew G. Knepley 5922552f7358SJed Brown /*@C 5923552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5924552f7358SJed Brown 5925552f7358SJed Brown Not collective 5926552f7358SJed Brown 5927552f7358SJed Brown Input Parameters: 5928552f7358SJed Brown + dm - The DM 59290298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section 5930552f7358SJed Brown . v - The local vector 5931eaf898f9SPatrick Sanan . point - The point in the DM 59320298fd71SBarry Smith . csize - The number of values in the closure, or NULL 5933552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 5934552f7358SJed Brown 593522c1ee49SMatthew 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() 593622c1ee49SMatthew G. Knepley 59373813dfbdSMatthew G Knepley Fortran Notes: 59383813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 59393813dfbdSMatthew G Knepley include petsc.h90 in your code. 59403813dfbdSMatthew G Knepley 59413813dfbdSMatthew G Knepley The csize argument is not present in the Fortran 90 binding since it is internal to the array. 59423813dfbdSMatthew G Knepley 5943552f7358SJed Brown Level: intermediate 5944552f7358SJed Brown 5945db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5946552f7358SJed Brown @*/ 59477c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5948a6dfd86eSKarl Rupp { 5949552f7358SJed Brown PetscInt size = 0; 5950552f7358SJed Brown 5951552f7358SJed Brown PetscFunctionBegin; 5952552f7358SJed Brown /* Should work without recalculating size */ 59539566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values)); 5954c9fdaa05SMatthew G. Knepley *values = NULL; 5955552f7358SJed Brown PetscFunctionReturn(0); 5956552f7358SJed Brown } 5957552f7358SJed Brown 59589fbee547SJacob Faibussowitsch static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 59599fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5960552f7358SJed Brown 59619fbee547SJacob 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[]) 5962552f7358SJed Brown { 5963552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 5964552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5965552f7358SJed Brown PetscScalar *a; 5966552f7358SJed Brown PetscInt off, cind = 0, k; 5967552f7358SJed Brown 5968552f7358SJed Brown PetscFunctionBegin; 59699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 59709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 5971552f7358SJed Brown a = &array[off]; 5972552f7358SJed Brown if (!cdof || setBC) { 597397e99dd9SToby Isaac if (clperm) { 597497e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 597597e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5976552f7358SJed Brown } else { 597797e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 597897e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5979552f7358SJed Brown } 5980552f7358SJed Brown } else { 59819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 598297e99dd9SToby Isaac if (clperm) { 598397e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) { 5984552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 598597e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5986552f7358SJed Brown } 5987552f7358SJed Brown } else { 5988552f7358SJed Brown for (k = 0; k < dof; ++k) { 5989552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 599097e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 599197e99dd9SToby Isaac } 599297e99dd9SToby Isaac } 599397e99dd9SToby Isaac } else { 599497e99dd9SToby Isaac if (perm) { 599597e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 599697e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 599797e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 599897e99dd9SToby Isaac } 599997e99dd9SToby Isaac } else { 600097e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 600197e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 600297e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 600397e99dd9SToby Isaac } 6004552f7358SJed Brown } 6005552f7358SJed Brown } 6006552f7358SJed Brown } 6007552f7358SJed Brown PetscFunctionReturn(0); 6008552f7358SJed Brown } 6009552f7358SJed Brown 60109fbee547SJacob 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[]) 6011a5e93ea8SMatthew G. Knepley { 6012a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6013a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6014a5e93ea8SMatthew G. Knepley PetscScalar *a; 6015a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6016a5e93ea8SMatthew G. Knepley 6017a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 60189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 60199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6020a5e93ea8SMatthew G. Knepley a = &array[off]; 6021a5e93ea8SMatthew G. Knepley if (cdof) { 60229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 602397e99dd9SToby Isaac if (clperm) { 602497e99dd9SToby Isaac if (perm) { 6025a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6026a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 602797e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 602897e99dd9SToby Isaac cind++; 6029a5e93ea8SMatthew G. Knepley } 6030a5e93ea8SMatthew G. Knepley } 6031a5e93ea8SMatthew G. Knepley } else { 6032a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6033a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 603497e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 603597e99dd9SToby Isaac cind++; 603697e99dd9SToby Isaac } 603797e99dd9SToby Isaac } 603897e99dd9SToby Isaac } 603997e99dd9SToby Isaac } else { 604097e99dd9SToby Isaac if (perm) { 604197e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 604297e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 604397e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 604497e99dd9SToby Isaac cind++; 604597e99dd9SToby Isaac } 604697e99dd9SToby Isaac } 604797e99dd9SToby Isaac } else { 604897e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 604997e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 605097e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 605197e99dd9SToby Isaac cind++; 605297e99dd9SToby Isaac } 6053a5e93ea8SMatthew G. Knepley } 6054a5e93ea8SMatthew G. Knepley } 6055a5e93ea8SMatthew G. Knepley } 6056a5e93ea8SMatthew G. Knepley } 6057a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6058a5e93ea8SMatthew G. Knepley } 6059a5e93ea8SMatthew G. Knepley 60609fbee547SJacob 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[]) 6061a6dfd86eSKarl Rupp { 6062552f7358SJed Brown PetscScalar *a; 60631a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60641a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 606597e99dd9SToby Isaac PetscInt cind = 0, b; 6066552f7358SJed Brown 6067552f7358SJed Brown PetscFunctionBegin; 60689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 60699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 60709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 60711a271a75SMatthew G. Knepley a = &array[foff]; 6072552f7358SJed Brown if (!fcdof || setBC) { 607397e99dd9SToby Isaac if (clperm) { 607497e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 607597e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6076552f7358SJed Brown } else { 607797e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 607897e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6079552f7358SJed Brown } 6080552f7358SJed Brown } else { 60819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 608297e99dd9SToby Isaac if (clperm) { 608397e99dd9SToby Isaac if (perm) { 608497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 608597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 608697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6087552f7358SJed Brown } 6088552f7358SJed Brown } else { 608997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 609097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 609197e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 609297e99dd9SToby Isaac } 609397e99dd9SToby Isaac } 609497e99dd9SToby Isaac } else { 609597e99dd9SToby Isaac if (perm) { 609697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 609797e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 609897e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 609997e99dd9SToby Isaac } 610097e99dd9SToby Isaac } else { 610197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 610297e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 610397e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6104552f7358SJed Brown } 6105552f7358SJed Brown } 6106552f7358SJed Brown } 6107552f7358SJed Brown } 61081a271a75SMatthew G. Knepley *offset += fdof; 6109552f7358SJed Brown PetscFunctionReturn(0); 6110552f7358SJed Brown } 6111552f7358SJed Brown 61129fbee547SJacob 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[]) 6113a5e93ea8SMatthew G. Knepley { 6114a5e93ea8SMatthew G. Knepley PetscScalar *a; 61151a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 61161a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 61175da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6118ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6119a5e93ea8SMatthew G. Knepley 6120a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 61219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 61229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 61239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 61249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 61251a271a75SMatthew G. Knepley a = &array[foff]; 6126a5e93ea8SMatthew G. Knepley if (fcdof) { 6127ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 61289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 612997e99dd9SToby Isaac if (clperm) { 613097e99dd9SToby Isaac if (perm) { 6131ba322698SMatthew G. Knepley if (comps) { 6132ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6133ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61345da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6135ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6136ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6137ba322698SMatthew G. Knepley } 6138ba322698SMatthew G. Knepley } else { 613997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 614097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 614197e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6142a5e93ea8SMatthew G. Knepley ++cind; 6143a5e93ea8SMatthew G. Knepley } 6144a5e93ea8SMatthew G. Knepley } 6145ba322698SMatthew G. Knepley } 6146ba322698SMatthew G. Knepley } else { 6147ba322698SMatthew G. Knepley if (comps) { 6148ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6149ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61505da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6151ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6152ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6153ba322698SMatthew G. Knepley } 6154a5e93ea8SMatthew G. Knepley } else { 615597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 615697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 615797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 615897e99dd9SToby Isaac ++cind; 615997e99dd9SToby Isaac } 616097e99dd9SToby Isaac } 616197e99dd9SToby Isaac } 6162ba322698SMatthew G. Knepley } 616397e99dd9SToby Isaac } else { 616497e99dd9SToby Isaac if (perm) { 6165ba322698SMatthew G. Knepley if (comps) { 6166ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6167ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61685da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6169ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6170ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6171ba322698SMatthew G. Knepley } 6172ba322698SMatthew G. Knepley } else { 617397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 617497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 617597e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 617697e99dd9SToby Isaac ++cind; 617797e99dd9SToby Isaac } 617897e99dd9SToby Isaac } 6179ba322698SMatthew G. Knepley } 6180ba322698SMatthew G. Knepley } else { 6181ba322698SMatthew G. Knepley if (comps) { 6182ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6183ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61845da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6185ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6186ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6187ba322698SMatthew G. Knepley } 618897e99dd9SToby Isaac } else { 618997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 619097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 619197e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6192a5e93ea8SMatthew G. Knepley ++cind; 6193a5e93ea8SMatthew G. Knepley } 6194a5e93ea8SMatthew G. Knepley } 6195a5e93ea8SMatthew G. Knepley } 6196a5e93ea8SMatthew G. Knepley } 6197a5e93ea8SMatthew G. Knepley } 6198ba322698SMatthew G. Knepley } 61991a271a75SMatthew G. Knepley *offset += fdof; 6200a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6201a5e93ea8SMatthew G. Knepley } 6202a5e93ea8SMatthew G. Knepley 62039fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6204a6dfd86eSKarl Rupp { 6205552f7358SJed Brown PetscScalar *array; 62061b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 62071b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6208552f7358SJed Brown 62091b406b76SMatthew G. Knepley PetscFunctionBeginHot; 62109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 62119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 62129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 62139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 62149566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6215b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6216b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p-1]; 6217b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p-1]; 6218b6ebb6e6SMatthew G. Knepley 6219b6ebb6e6SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 62209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6221b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6222b6ebb6e6SMatthew G. Knepley { 6223b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6224b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6225b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6226b6ebb6e6SMatthew G. Knepley 62279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 62289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6229b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6230b6ebb6e6SMatthew G. Knepley if (!cdof) { 6231b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6232b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6233b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6234b6ebb6e6SMatthew G. Knepley } 6235b6ebb6e6SMatthew G. Knepley } else { 6236b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6237b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6238b6ebb6e6SMatthew G. Knepley } 6239b6ebb6e6SMatthew G. Knepley } 6240b6ebb6e6SMatthew G. Knepley } else { 62419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6242b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6243b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6244b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6245b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6246b6ebb6e6SMatthew G. Knepley } 6247b6ebb6e6SMatthew G. Knepley } else { 6248b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6249b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6250b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6251b6ebb6e6SMatthew G. Knepley } 6252b6ebb6e6SMatthew G. Knepley } 6253b6ebb6e6SMatthew G. Knepley } 6254b6ebb6e6SMatthew G. Knepley } 6255b6ebb6e6SMatthew G. Knepley } 62569566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6257b6ebb6e6SMatthew G. Knepley PetscFunctionReturn(0); 6258b6ebb6e6SMatthew G. Knepley } 62591b406b76SMatthew G. Knepley 62601b406b76SMatthew G. Knepley /*@C 62611b406b76SMatthew G. Knepley DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 62621b406b76SMatthew G. Knepley 62631b406b76SMatthew G. Knepley Not collective 62641b406b76SMatthew G. Knepley 62651b406b76SMatthew G. Knepley Input Parameters: 62661b406b76SMatthew G. Knepley + dm - The DM 62671b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 62681b406b76SMatthew G. Knepley . v - The local vector 6269eaf898f9SPatrick Sanan . point - The point in the DM 62701b406b76SMatthew G. Knepley . values - The array of values 627122c1ee49SMatthew 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, 627222c1ee49SMatthew G. Knepley where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 62731b406b76SMatthew G. Knepley 62741b406b76SMatthew G. Knepley Fortran Notes: 62751b406b76SMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 62761b406b76SMatthew G. Knepley 62771b406b76SMatthew G. Knepley Level: intermediate 62781b406b76SMatthew G. Knepley 6279db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 62801b406b76SMatthew G. Knepley @*/ 62811b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 62821b406b76SMatthew G. Knepley { 62831b406b76SMatthew G. Knepley PetscSection clSection; 62841b406b76SMatthew G. Knepley IS clPoints; 62851b406b76SMatthew G. Knepley PetscScalar *array; 62861b406b76SMatthew G. Knepley PetscInt *points = NULL; 628727f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6288c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 62891b406b76SMatthew G. Knepley 62901a271a75SMatthew G. Knepley PetscFunctionBeginHot; 62911b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62929566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 62931a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 62941a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 62959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 62969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 62971b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 62989566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 62991b406b76SMatthew G. Knepley PetscFunctionReturn(0); 63001b406b76SMatthew G. Knepley } 63011a271a75SMatthew G. Knepley /* Get points */ 63029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6303c459fbc1SJed Brown for (clsize=0,p=0; p<numPoints; p++) { 6304c459fbc1SJed Brown PetscInt dof; 63059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 6306c459fbc1SJed Brown clsize += dof; 6307c459fbc1SJed Brown } 63089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 63091a271a75SMatthew G. Knepley /* Get array */ 63109566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 63111a271a75SMatthew G. Knepley /* Get values */ 6312ef90cfe2SMatthew G. Knepley if (numFields > 0) { 631397e99dd9SToby Isaac PetscInt offset = 0, f; 6314552f7358SJed Brown for (f = 0; f < numFields; ++f) { 631597e99dd9SToby Isaac const PetscInt **perms = NULL; 631697e99dd9SToby Isaac const PetscScalar **flips = NULL; 631797e99dd9SToby Isaac 63189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6319552f7358SJed Brown switch (mode) { 6320552f7358SJed Brown case INSERT_VALUES: 632197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632297e99dd9SToby Isaac const PetscInt point = points[2*p]; 632397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 632597e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6326552f7358SJed Brown } break; 6327552f7358SJed Brown case INSERT_ALL_VALUES: 632897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632997e99dd9SToby Isaac const PetscInt point = points[2*p]; 633097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 633197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 633297e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6333552f7358SJed Brown } break; 6334a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 633597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 633697e99dd9SToby Isaac const PetscInt point = points[2*p]; 633797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 633897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6339ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6340a5e93ea8SMatthew G. Knepley } break; 6341552f7358SJed Brown case ADD_VALUES: 634297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 634397e99dd9SToby Isaac const PetscInt point = points[2*p]; 634497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 634597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 634697e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6347552f7358SJed Brown } break; 6348552f7358SJed Brown case ADD_ALL_VALUES: 634997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 635097e99dd9SToby Isaac const PetscInt point = points[2*p]; 635197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 635297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 635397e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6354552f7358SJed Brown } break; 6355304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 635697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 635797e99dd9SToby Isaac const PetscInt point = points[2*p]; 635897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 635997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6360ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6361304ab55fSMatthew G. Knepley } break; 6362552f7358SJed Brown default: 636398921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6364552f7358SJed Brown } 63659566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 63661a271a75SMatthew G. Knepley } 6367552f7358SJed Brown } else { 63681a271a75SMatthew G. Knepley PetscInt dof, off; 636997e99dd9SToby Isaac const PetscInt **perms = NULL; 637097e99dd9SToby Isaac const PetscScalar **flips = NULL; 63711a271a75SMatthew G. Knepley 63729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 6373552f7358SJed Brown switch (mode) { 6374552f7358SJed Brown case INSERT_VALUES: 637597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 637697e99dd9SToby Isaac const PetscInt point = points[2*p]; 637797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 637897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 638097e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6381552f7358SJed Brown } break; 6382552f7358SJed Brown case INSERT_ALL_VALUES: 638397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 638497e99dd9SToby Isaac const PetscInt point = points[2*p]; 638597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 638697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 638897e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6389552f7358SJed Brown } break; 6390a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 639197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 639297e99dd9SToby Isaac const PetscInt point = points[2*p]; 639397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 639497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 639697e99dd9SToby Isaac updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6397a5e93ea8SMatthew G. Knepley } break; 6398552f7358SJed Brown case ADD_VALUES: 639997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 640097e99dd9SToby Isaac const PetscInt point = points[2*p]; 640197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 640297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 640497e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6405552f7358SJed Brown } break; 6406552f7358SJed Brown case ADD_ALL_VALUES: 640797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 640897e99dd9SToby Isaac const PetscInt point = points[2*p]; 640997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 641097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 641297e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6413552f7358SJed Brown } break; 6414304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 641597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 641697e99dd9SToby Isaac const PetscInt point = points[2*p]; 641797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 641897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 642097e99dd9SToby Isaac updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6421304ab55fSMatthew G. Knepley } break; 6422552f7358SJed Brown default: 642398921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6424552f7358SJed Brown } 64259566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 6426552f7358SJed Brown } 64271a271a75SMatthew G. Knepley /* Cleanup points */ 64289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 64291a271a75SMatthew G. Knepley /* Cleanup array */ 64309566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6431552f7358SJed Brown PetscFunctionReturn(0); 6432552f7358SJed Brown } 6433552f7358SJed Brown 64345f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 64359fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 64365f790a90SMatthew G. Knepley { 64375f790a90SMatthew G. Knepley PetscFunctionBegin; 64385f790a90SMatthew G. Knepley if (label) { 64395f790a90SMatthew G. Knepley PetscInt val, fdof; 64405f790a90SMatthew G. Knepley 64415f790a90SMatthew G. Knepley /* There is a problem with this: 64425f790a90SMatthew G. Knepley Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 64435f790a90SMatthew G. Knepley touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 64445f790a90SMatthew G. Knepley Thus I am only going to check val != -1, not val != labelId 64455f790a90SMatthew G. Knepley */ 64469566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 64475f790a90SMatthew G. Knepley if (val < 0) { 64489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 64495f790a90SMatthew G. Knepley *offset += fdof; 64505f790a90SMatthew G. Knepley PetscFunctionReturn(1); 64515f790a90SMatthew G. Knepley } 64525f790a90SMatthew G. Knepley } 64535f790a90SMatthew G. Knepley PetscFunctionReturn(0); 64545f790a90SMatthew G. Knepley } 64555f790a90SMatthew G. Knepley 645697529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 64575f790a90SMatthew 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) 6458e07394fbSMatthew G. Knepley { 6459e07394fbSMatthew G. Knepley PetscSection clSection; 6460e07394fbSMatthew G. Knepley IS clPoints; 6461e07394fbSMatthew G. Knepley PetscScalar *array; 6462e07394fbSMatthew G. Knepley PetscInt *points = NULL; 646397529cf3SJed Brown const PetscInt *clp; 6464e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 646597e99dd9SToby Isaac PetscInt offset = 0, f; 6466e07394fbSMatthew G. Knepley 6467e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 6468e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64699566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6470e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6471e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6473e07394fbSMatthew G. Knepley /* Get points */ 64749566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6475e07394fbSMatthew G. Knepley /* Get array */ 64769566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6477e07394fbSMatthew G. Knepley /* Get values */ 6478e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 647997e99dd9SToby Isaac const PetscInt **perms = NULL; 648097e99dd9SToby Isaac const PetscScalar **flips = NULL; 648197e99dd9SToby Isaac 6482e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 6483e07394fbSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 6484e07394fbSMatthew G. Knepley PetscInt fdof; 64859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 6486e07394fbSMatthew G. Knepley offset += fdof; 6487e07394fbSMatthew G. Knepley } 6488e07394fbSMatthew G. Knepley continue; 6489e07394fbSMatthew G. Knepley } 64909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6491e07394fbSMatthew G. Knepley switch (mode) { 6492e07394fbSMatthew G. Knepley case INSERT_VALUES: 649397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649497e99dd9SToby Isaac const PetscInt point = points[2*p]; 649597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64975f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64989566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 6499e07394fbSMatthew G. Knepley } break; 6500e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 650197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 650297e99dd9SToby Isaac const PetscInt point = points[2*p]; 650397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 650497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65055f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65069566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 6507e07394fbSMatthew G. Knepley } break; 6508e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 650997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 651097e99dd9SToby Isaac const PetscInt point = points[2*p]; 651197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 651297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65135f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65149566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 6515e07394fbSMatthew G. Knepley } break; 6516e07394fbSMatthew G. Knepley case ADD_VALUES: 651797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 651897e99dd9SToby Isaac const PetscInt point = points[2*p]; 651997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 652097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65215f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65229566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 6523e07394fbSMatthew G. Knepley } break; 6524e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 652597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 652697e99dd9SToby Isaac const PetscInt point = points[2*p]; 652797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 652897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65295f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65309566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 6531e07394fbSMatthew G. Knepley } break; 6532e07394fbSMatthew G. Knepley default: 653398921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6534e07394fbSMatthew G. Knepley } 65359566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6536e07394fbSMatthew G. Knepley } 6537e07394fbSMatthew G. Knepley /* Cleanup points */ 65389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6539e07394fbSMatthew G. Knepley /* Cleanup array */ 65409566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6541e07394fbSMatthew G. Knepley PetscFunctionReturn(0); 6542e07394fbSMatthew G. Knepley } 6543e07394fbSMatthew G. Knepley 65447cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6545552f7358SJed Brown { 6546552f7358SJed Brown PetscMPIInt rank; 6547552f7358SJed Brown PetscInt i, j; 6548552f7358SJed Brown 6549552f7358SJed Brown PetscFunctionBegin; 65509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 655163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 655263a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 655363a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 6554b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 6555557cf195SMatthew G. Knepley if (!values) PetscFunctionReturn(0); 6556b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 65579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 6558b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 6559519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 65609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]))); 6561552f7358SJed Brown #else 65629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j])); 6563552f7358SJed Brown #endif 6564552f7358SJed Brown } 65659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6566552f7358SJed Brown } 6567552f7358SJed Brown PetscFunctionReturn(0); 6568552f7358SJed Brown } 6569552f7358SJed Brown 657005586334SMatthew G. Knepley /* 657105586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 657205586334SMatthew G. Knepley 657305586334SMatthew G. Knepley Input Parameters: 657405586334SMatthew G. Knepley + section - The section for this data layout 657536fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 657605586334SMatthew G. Knepley . point - The point contributing dofs with these indices 657705586334SMatthew G. Knepley . off - The global offset of this point 657805586334SMatthew G. Knepley . loff - The local offset of each field 6579a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 658005586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 658105586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 658205586334SMatthew G. Knepley 658305586334SMatthew G. Knepley Output Parameter: 658405586334SMatthew G. Knepley . indices - Indices for dofs on this point 658505586334SMatthew G. Knepley 658605586334SMatthew G. Knepley Level: developer 658705586334SMatthew G. Knepley 658805586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 658905586334SMatthew G. Knepley */ 659036fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6591a6dfd86eSKarl Rupp { 6592e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 6593552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6594552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6595552f7358SJed Brown PetscInt cind = 0, k; 6596552f7358SJed Brown 6597552f7358SJed Brown PetscFunctionBegin; 659808401ef6SPierre Jolivet PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 65999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 66009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 6601552f7358SJed Brown if (!cdof || setBC) { 660205586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 660305586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 660405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 660505586334SMatthew G. Knepley 660605586334SMatthew G. Knepley indices[ind] = off + k; 6607552f7358SJed Brown } 6608552f7358SJed Brown } else { 66099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 66104acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 661105586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 661205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 661305586334SMatthew G. Knepley 66144acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 66154acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 661605586334SMatthew G. Knepley indices[ind] = -(off+k+1); 66174acb8e1eSToby Isaac ++cind; 66184acb8e1eSToby Isaac } else { 661936fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 6620552f7358SJed Brown } 6621552f7358SJed Brown } 6622552f7358SJed Brown } 6623e6ccafaeSMatthew G Knepley *loff += dof; 6624552f7358SJed Brown PetscFunctionReturn(0); 6625552f7358SJed Brown } 6626552f7358SJed Brown 66277e29afd2SMatthew G. Knepley /* 662836fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 66297e29afd2SMatthew G. Knepley 663036fa2b79SJed Brown Input Parameters: 663136fa2b79SJed Brown + section - a section (global or local) 663236fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 663336fa2b79SJed Brown . point - point within section 663436fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 663536fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 663636fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 663736fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 663836fa2b79SJed Brown . permsoff - offset 663936fa2b79SJed Brown - indperm - index permutation 664036fa2b79SJed Brown 664136fa2b79SJed Brown Output Parameter: 664236fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 664336fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 664436fa2b79SJed Brown 664536fa2b79SJed Brown Notes: 664636fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 664736fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 664836fa2b79SJed Brown in the local vector. 664936fa2b79SJed Brown 665036fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 665136fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 665236fa2b79SJed Brown 665336fa2b79SJed Brown Developer Note: 665436fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 665536fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 665636fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 665736fa2b79SJed Brown 665836fa2b79SJed Brown Example: 665936fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 666036fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 666136fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 666236fa2b79SJed 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. 666336fa2b79SJed Brown 666436fa2b79SJed Brown Level: developer 66657e29afd2SMatthew G. Knepley */ 666636fa2b79SJed 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[]) 6667a6dfd86eSKarl Rupp { 6668552f7358SJed Brown PetscInt numFields, foff, f; 6669552f7358SJed Brown 6670552f7358SJed Brown PetscFunctionBegin; 667108401ef6SPierre Jolivet PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 66729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6673552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 66744acb8e1eSToby Isaac PetscInt fdof, cfdof; 6675552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 66764acb8e1eSToby Isaac PetscInt cind = 0, b; 66774acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6678552f7358SJed Brown 66799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 66809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 6681552f7358SJed Brown if (!cfdof || setBC) { 668205586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 668305586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 668405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 668505586334SMatthew G. Knepley 668605586334SMatthew G. Knepley indices[ind] = off+foff+b; 668705586334SMatthew G. Knepley } 6688552f7358SJed Brown } else { 66899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 669005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 669105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 669205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 669305586334SMatthew G. Knepley 66944acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 669505586334SMatthew G. Knepley indices[ind] = -(off+foff+b+1); 6696552f7358SJed Brown ++cind; 6697552f7358SJed Brown } else { 669836fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 6699552f7358SJed Brown } 6700552f7358SJed Brown } 6701552f7358SJed Brown } 670236fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6703552f7358SJed Brown foffs[f] += fdof; 6704552f7358SJed Brown } 6705552f7358SJed Brown PetscFunctionReturn(0); 6706552f7358SJed Brown } 6707552f7358SJed Brown 67087e29afd2SMatthew G. Knepley /* 67097e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 67107e29afd2SMatthew G. Knepley 67117e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 6712645102dcSJed Brown 6713645102dcSJed Brown Notes: 6714645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6715645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 67167e29afd2SMatthew G. Knepley */ 6717645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 67187e29afd2SMatthew G. Knepley { 67197e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 67207e29afd2SMatthew G. Knepley 67217e29afd2SMatthew G. Knepley PetscFunctionBegin; 67229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 67237e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 67247e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 67257e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67267e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 67277e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 67287e29afd2SMatthew G. Knepley 67299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 67319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 6732645102dcSJed Brown if (!cfdof) { 673305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 673405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 673505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 673605586334SMatthew G. Knepley 673705586334SMatthew G. Knepley indices[ind] = foff+b; 673805586334SMatthew G. Knepley } 67397e29afd2SMatthew G. Knepley } else { 67409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 674105586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 674205586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 674305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 674405586334SMatthew G. Knepley 67457e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 674605586334SMatthew G. Knepley indices[ind] = -(foff+b+1); 67477e29afd2SMatthew G. Knepley ++cind; 67487e29afd2SMatthew G. Knepley } else { 674905586334SMatthew G. Knepley indices[ind] = foff+b-cind; 67507e29afd2SMatthew G. Knepley } 67517e29afd2SMatthew G. Knepley } 67527e29afd2SMatthew G. Knepley } 67537e29afd2SMatthew G. Knepley foffs[f] += fdof; 67547e29afd2SMatthew G. Knepley } 67557e29afd2SMatthew G. Knepley PetscFunctionReturn(0); 67567e29afd2SMatthew G. Knepley } 67577e29afd2SMatthew G. Knepley 67584acb8e1eSToby 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) 6759d3d1a6afSToby Isaac { 6760d3d1a6afSToby Isaac Mat cMat; 6761d3d1a6afSToby Isaac PetscSection aSec, cSec; 6762d3d1a6afSToby Isaac IS aIS; 6763d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 6764d3d1a6afSToby Isaac const PetscInt *anchors; 6765e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 6766d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 6767d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 6768d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 6769d3d1a6afSToby Isaac PetscInt newOffsets[32]; 6770d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 6771d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 6772d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 67736ecaa68aSToby Isaac PetscScalar *newValues=NULL,*tmpValues; 6774d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 6775d3d1a6afSToby Isaac 6776d3d1a6afSToby Isaac PetscFunctionBegin; 6777d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6778d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 67799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6780d3d1a6afSToby Isaac 67819566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 6782d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 6783d3d1a6afSToby Isaac if (aSec) { 67849566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 67859566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 67869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd)); 6787d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 6788d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 6789d3d1a6afSToby Isaac * into the global matrix anyway) */ 6790d3d1a6afSToby Isaac for (p = 0; p < 2*numPoints; p+=2) { 6791d3d1a6afSToby Isaac PetscInt b = points[p]; 67924b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6793d3d1a6afSToby Isaac 67949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 67954b2f2278SToby Isaac if (!bSecDof) { 67964b2f2278SToby Isaac continue; 67974b2f2278SToby Isaac } 6798d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 67999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,b,&bDof)); 6800d3d1a6afSToby Isaac } 6801d3d1a6afSToby Isaac if (bDof) { 6802d3d1a6afSToby Isaac /* this point is constrained */ 6803d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 6804d3d1a6afSToby Isaac PetscInt bOff, q; 6805d3d1a6afSToby Isaac 6806d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 6807d3d1a6afSToby Isaac newNumPoints += bDof; 68089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,b,&bOff)); 6809d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6810d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6811d3d1a6afSToby Isaac PetscInt aDof; 6812d3d1a6afSToby Isaac 68139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 6814d3d1a6afSToby Isaac newNumIndices += aDof; 6815d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6816d3d1a6afSToby Isaac PetscInt fDof; 6817d3d1a6afSToby Isaac 68189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 6819d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6820d3d1a6afSToby Isaac } 6821d3d1a6afSToby Isaac } 6822d3d1a6afSToby Isaac } 6823d3d1a6afSToby Isaac else { 6824d3d1a6afSToby Isaac /* this point is not constrained */ 6825d3d1a6afSToby Isaac newNumPoints++; 68264b2f2278SToby Isaac newNumIndices += bSecDof; 6827d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6828d3d1a6afSToby Isaac PetscInt fDof; 6829d3d1a6afSToby Isaac 68309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6831d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6832d3d1a6afSToby Isaac } 6833d3d1a6afSToby Isaac } 6834d3d1a6afSToby Isaac } 6835d3d1a6afSToby Isaac } 6836d3d1a6afSToby Isaac if (!anyConstrained) { 683772b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 683872b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 683972b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 684072b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 68419566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors)); 6842d3d1a6afSToby Isaac PetscFunctionReturn(0); 6843d3d1a6afSToby Isaac } 6844d3d1a6afSToby Isaac 68456ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 68466ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 68476ecaa68aSToby Isaac 6848f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6849d3d1a6afSToby Isaac 68506ecaa68aSToby Isaac if (!outPoints && !outValues) { 68516ecaa68aSToby Isaac if (offsets) { 68526ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 68536ecaa68aSToby Isaac offsets[f] = newOffsets[f]; 68546ecaa68aSToby Isaac } 68556ecaa68aSToby Isaac } 68569566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors)); 68576ecaa68aSToby Isaac PetscFunctionReturn(0); 68586ecaa68aSToby Isaac } 68596ecaa68aSToby Isaac 68601dca8a05SBarry 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); 6861d3d1a6afSToby Isaac 68629566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 6863d3d1a6afSToby Isaac 6864d3d1a6afSToby Isaac /* workspaces */ 6865d3d1a6afSToby Isaac if (numFields) { 6866d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 68679566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 68689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 6869d3d1a6afSToby Isaac } 6870d3d1a6afSToby Isaac } 6871d3d1a6afSToby Isaac else { 68729566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 68739566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0])); 6874d3d1a6afSToby Isaac } 6875d3d1a6afSToby Isaac 6876d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 6877d3d1a6afSToby Isaac if (numFields) { 68784b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 68794b2f2278SToby Isaac 6880d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6881d3d1a6afSToby Isaac PetscInt b = points[2*p]; 68824b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6883d3d1a6afSToby Isaac 68849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 68854b2f2278SToby Isaac if (!bSecDof) { 68864b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 68874b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 68884b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 68894b2f2278SToby Isaac } 68904b2f2278SToby Isaac continue; 68914b2f2278SToby Isaac } 6892d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 68939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6894d3d1a6afSToby Isaac } 6895d3d1a6afSToby Isaac if (bDof) { 6896d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6897d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 6898d3d1a6afSToby Isaac 68999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 69009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6901d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6902d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6903d3d1a6afSToby Isaac PetscInt aFDof; 6904d3d1a6afSToby Isaac 69059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 6906d3d1a6afSToby Isaac allFDof += aFDof; 6907d3d1a6afSToby Isaac } 6908d3d1a6afSToby Isaac newPointOffsets[f][p+1] = allFDof; 6909d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = fDof * allFDof; 6910d3d1a6afSToby Isaac } 6911d3d1a6afSToby Isaac } 6912d3d1a6afSToby Isaac else { 6913d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6914d3d1a6afSToby Isaac PetscInt fDof; 6915d3d1a6afSToby Isaac 69169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6917d3d1a6afSToby Isaac newPointOffsets[f][p+1] = fDof; 6918d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = 0; 6919d3d1a6afSToby Isaac } 6920d3d1a6afSToby Isaac } 6921d3d1a6afSToby Isaac } 69224b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 69234b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 69244b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 6925d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6926d3d1a6afSToby Isaac newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6927d3d1a6afSToby Isaac pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6928d3d1a6afSToby Isaac } 692919f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 693019f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 69319566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 6932d3d1a6afSToby Isaac } 6933d3d1a6afSToby Isaac } 6934d3d1a6afSToby Isaac else { 6935d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6936d3d1a6afSToby Isaac PetscInt b = points[2*p]; 69374b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6938d3d1a6afSToby Isaac 69399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 69404b2f2278SToby Isaac if (!bSecDof) { 69414b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 69424b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 69434b2f2278SToby Isaac continue; 69444b2f2278SToby Isaac } 6945d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6947d3d1a6afSToby Isaac } 6948d3d1a6afSToby Isaac if (bDof) { 69494b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 6950d3d1a6afSToby Isaac 69519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6952d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6953d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 6954d3d1a6afSToby Isaac 69559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 6956d3d1a6afSToby Isaac allDof += aDof; 6957d3d1a6afSToby Isaac } 6958d3d1a6afSToby Isaac newPointOffsets[0][p+1] = allDof; 69594b2f2278SToby Isaac pointMatOffsets[0][p+1] = bSecDof * allDof; 6960d3d1a6afSToby Isaac } 6961d3d1a6afSToby Isaac else { 69624b2f2278SToby Isaac newPointOffsets[0][p+1] = bSecDof; 6963d3d1a6afSToby Isaac pointMatOffsets[0][p+1] = 0; 6964d3d1a6afSToby Isaac } 6965d3d1a6afSToby Isaac } 6966d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 6967d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 6968d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6969d3d1a6afSToby Isaac newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6970d3d1a6afSToby Isaac pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6971d3d1a6afSToby Isaac } 69729566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 6973d3d1a6afSToby Isaac } 6974d3d1a6afSToby Isaac 69756ecaa68aSToby Isaac /* output arrays */ 69769566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 69776ecaa68aSToby Isaac 6978d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 69799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 69809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 69819566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices)); 69829566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 6983d3d1a6afSToby Isaac if (numFields) { 6984d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 6985d3d1a6afSToby Isaac PetscInt b = points[2*p]; 6986d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 69874b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6988d3d1a6afSToby Isaac 69899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 69904b2f2278SToby Isaac if (!bSecDof) { 69914b2f2278SToby Isaac continue; 69924b2f2278SToby Isaac } 6993d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6995d3d1a6afSToby Isaac } 6996d3d1a6afSToby Isaac if (bDof) { 6997d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6998d3d1a6afSToby Isaac 6999d3d1a6afSToby Isaac fStart[0] = 0; 7000d3d1a6afSToby Isaac fEnd[0] = 0; 7001d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7002d3d1a6afSToby Isaac PetscInt fDof; 7003d3d1a6afSToby Isaac 70049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7005d3d1a6afSToby Isaac fStart[f+1] = fStart[f] + fDof; 7006d3d1a6afSToby Isaac fEnd[f+1] = fStart[f+1]; 7007d3d1a6afSToby Isaac } 70089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 70099566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7010d3d1a6afSToby Isaac 7011d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7012d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7013d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7014d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7015d3d1a6afSToby Isaac 7016d3d1a6afSToby Isaac fAnchorStart[f+1] = fAnchorStart[f] + fDof; 7017d3d1a6afSToby Isaac fAnchorEnd[f+1] = fAnchorStart[f + 1]; 7018d3d1a6afSToby Isaac } 70199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7020d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7021d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7022d3d1a6afSToby Isaac 7023d3d1a6afSToby 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 */ 7024d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7025d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70279566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7028d3d1a6afSToby Isaac } 7029d3d1a6afSToby Isaac newP += bDof; 7030d3d1a6afSToby Isaac 70316ecaa68aSToby Isaac if (outValues) { 7032d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 7033d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 70349566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p])); 7035d3d1a6afSToby Isaac } 7036d3d1a6afSToby Isaac } 70376ecaa68aSToby Isaac } 7038d3d1a6afSToby Isaac else { 7039d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7040d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7041d3d1a6afSToby Isaac newP++; 7042d3d1a6afSToby Isaac } 7043d3d1a6afSToby Isaac } 7044d3d1a6afSToby Isaac } else { 7045d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7046d3d1a6afSToby Isaac PetscInt b = points[2*p]; 7047d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 70484b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7049d3d1a6afSToby Isaac 70509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 70514b2f2278SToby Isaac if (!bSecDof) { 70524b2f2278SToby Isaac continue; 70534b2f2278SToby Isaac } 7054d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 70559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7056d3d1a6afSToby Isaac } 7057d3d1a6afSToby Isaac if (bDof) { 7058d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7059d3d1a6afSToby Isaac 70609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 70619566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7062d3d1a6afSToby Isaac 70639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset (aSec, b, &bOff)); 7064d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7065d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7066d3d1a6afSToby Isaac 7067d3d1a6afSToby 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 */ 7068d3d1a6afSToby Isaac 7069d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7070d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70729566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7073d3d1a6afSToby Isaac } 7074d3d1a6afSToby Isaac newP += bDof; 7075d3d1a6afSToby Isaac 7076d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 70776ecaa68aSToby Isaac if (outValues) { 70789566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p])); 7079d3d1a6afSToby Isaac } 70806ecaa68aSToby Isaac } 7081d3d1a6afSToby Isaac else { 7082d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7083d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7084d3d1a6afSToby Isaac newP++; 7085d3d1a6afSToby Isaac } 7086d3d1a6afSToby Isaac } 7087d3d1a6afSToby Isaac } 7088d3d1a6afSToby Isaac 70896ecaa68aSToby Isaac if (outValues) { 70909566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 70919566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues,newNumIndices*numIndices)); 7092d3d1a6afSToby Isaac /* multiply constraints on the right */ 7093d3d1a6afSToby Isaac if (numFields) { 7094d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7095d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7096d3d1a6afSToby Isaac 7097d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7098d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7099d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7100d3d1a6afSToby Isaac PetscInt c, r, k; 7101d3d1a6afSToby Isaac PetscInt dof; 7102d3d1a6afSToby Isaac 71039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,b,f,&dof)); 71044b2f2278SToby Isaac if (!dof) { 71054b2f2278SToby Isaac continue; 71064b2f2278SToby Isaac } 7107d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7108d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7109d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7110d3d1a6afSToby Isaac 7111d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7112d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7113d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 71144acb8e1eSToby Isaac tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7115d3d1a6afSToby Isaac } 7116d3d1a6afSToby Isaac } 7117d3d1a6afSToby Isaac } 7118d3d1a6afSToby Isaac } 7119d3d1a6afSToby Isaac else { 7120d3d1a6afSToby Isaac /* copy this column as is */ 7121d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7122d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7123d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7124d3d1a6afSToby Isaac } 7125d3d1a6afSToby Isaac } 7126d3d1a6afSToby Isaac } 7127d3d1a6afSToby Isaac oldOff += dof; 7128d3d1a6afSToby Isaac } 7129d3d1a6afSToby Isaac } 7130d3d1a6afSToby Isaac } 7131d3d1a6afSToby Isaac else { 7132d3d1a6afSToby Isaac PetscInt oldOff = 0; 7133d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7134d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7135d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7136d3d1a6afSToby Isaac PetscInt c, r, k; 7137d3d1a6afSToby Isaac PetscInt dof; 7138d3d1a6afSToby Isaac 71399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&dof)); 71404b2f2278SToby Isaac if (!dof) { 71414b2f2278SToby Isaac continue; 71424b2f2278SToby Isaac } 7143d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7144d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7145d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7146d3d1a6afSToby Isaac 7147d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7148d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7149d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7150d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7151d3d1a6afSToby Isaac } 7152d3d1a6afSToby Isaac } 7153d3d1a6afSToby Isaac } 7154d3d1a6afSToby Isaac } 7155d3d1a6afSToby Isaac else { 7156d3d1a6afSToby Isaac /* copy this column as is */ 7157d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7158d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7159d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7160d3d1a6afSToby Isaac } 7161d3d1a6afSToby Isaac } 7162d3d1a6afSToby Isaac } 7163d3d1a6afSToby Isaac oldOff += dof; 7164d3d1a6afSToby Isaac } 7165d3d1a6afSToby Isaac } 7166d3d1a6afSToby Isaac 71676ecaa68aSToby Isaac if (multiplyLeft) { 71689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues)); 71699566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues,newNumIndices*newNumIndices)); 7170d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7171d3d1a6afSToby Isaac if (numFields) { 7172d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7173d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7174d3d1a6afSToby Isaac 7175d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7176d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7177d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7178d3d1a6afSToby Isaac PetscInt c, r, k; 7179d3d1a6afSToby Isaac PetscInt dof; 7180d3d1a6afSToby Isaac 71819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,b,f,&dof)); 7182d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7183d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7184d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7185d3d1a6afSToby Isaac 7186d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7187d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7188d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7189d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7190d3d1a6afSToby Isaac } 7191d3d1a6afSToby Isaac } 7192d3d1a6afSToby Isaac } 7193d3d1a6afSToby Isaac } 7194d3d1a6afSToby Isaac else { 7195d3d1a6afSToby Isaac /* copy this row as is */ 7196d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7197d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7198d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7199d3d1a6afSToby Isaac } 7200d3d1a6afSToby Isaac } 7201d3d1a6afSToby Isaac } 7202d3d1a6afSToby Isaac oldOff += dof; 7203d3d1a6afSToby Isaac } 7204d3d1a6afSToby Isaac } 7205d3d1a6afSToby Isaac } 7206d3d1a6afSToby Isaac else { 7207d3d1a6afSToby Isaac PetscInt oldOff = 0; 7208d3d1a6afSToby Isaac 7209d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7210d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7211d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7212d3d1a6afSToby Isaac PetscInt c, r, k; 7213d3d1a6afSToby Isaac PetscInt dof; 7214d3d1a6afSToby Isaac 72159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&dof)); 7216d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7217d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7218d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7219d3d1a6afSToby Isaac 7220d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7221d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7222d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7223d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7224d3d1a6afSToby Isaac } 7225d3d1a6afSToby Isaac } 7226d3d1a6afSToby Isaac } 7227d3d1a6afSToby Isaac } 7228d3d1a6afSToby Isaac else { 7229d3d1a6afSToby Isaac /* copy this row as is */ 72309fc93327SToby Isaac for (r = 0; r < dof; r++) { 7231d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7232d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7233d3d1a6afSToby Isaac } 7234d3d1a6afSToby Isaac } 7235d3d1a6afSToby Isaac } 7236d3d1a6afSToby Isaac oldOff += dof; 7237d3d1a6afSToby Isaac } 7238d3d1a6afSToby Isaac } 7239d3d1a6afSToby Isaac 72409566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 72416ecaa68aSToby Isaac } 72426ecaa68aSToby Isaac else { 72436ecaa68aSToby Isaac newValues = tmpValues; 72446ecaa68aSToby Isaac } 72456ecaa68aSToby Isaac } 72466ecaa68aSToby Isaac 7247d3d1a6afSToby Isaac /* clean up */ 72489566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices)); 72499566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 72506ecaa68aSToby Isaac 7251d3d1a6afSToby Isaac if (numFields) { 7252d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 72539566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 72549566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 72559566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 7256d3d1a6afSToby Isaac } 7257d3d1a6afSToby Isaac } 7258d3d1a6afSToby Isaac else { 72599566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 72609566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 72619566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0])); 7262d3d1a6afSToby Isaac } 72639566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 7264d3d1a6afSToby Isaac 7265d3d1a6afSToby Isaac /* output */ 72666ecaa68aSToby Isaac if (outPoints) { 7267d3d1a6afSToby Isaac *outPoints = newPoints; 72686ecaa68aSToby Isaac } 72696ecaa68aSToby Isaac else { 72709566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 72716ecaa68aSToby Isaac } 727231620726SToby Isaac if (outValues) { 7273d3d1a6afSToby Isaac *outValues = newValues; 72746ecaa68aSToby Isaac } 72756ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 7276d3d1a6afSToby Isaac offsets[f] = newOffsets[f]; 7277d3d1a6afSToby Isaac } 7278d3d1a6afSToby Isaac PetscFunctionReturn(0); 7279d3d1a6afSToby Isaac } 7280d3d1a6afSToby Isaac 72814a1e0b3eSMatthew G. Knepley /*@C 728271f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 72837cd05799SMatthew G. Knepley 72847cd05799SMatthew G. Knepley Not collective 72857cd05799SMatthew G. Knepley 72867cd05799SMatthew G. Knepley Input Parameters: 72877cd05799SMatthew G. Knepley + dm - The DM 728871f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 728971f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 729071f0bbf9SMatthew G. Knepley . point - The point defining the closure 729171f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 72927cd05799SMatthew G. Knepley 729371f0bbf9SMatthew G. Knepley Output Parameters: 729471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 729571f0bbf9SMatthew G. Knepley . indices - The dof indices 729671f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 729771f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 72987cd05799SMatthew G. Knepley 729936fa2b79SJed Brown Notes: 730036fa2b79SJed Brown Must call DMPlexRestoreClosureIndices() to free allocated memory 730136fa2b79SJed Brown 730236fa2b79SJed Brown If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 730336fa2b79SJed Brown of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 730436fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 730536fa2b79SJed Brown indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 730636fa2b79SJed Brown indices (with the above semantics) are implied. 73077cd05799SMatthew G. Knepley 73087cd05799SMatthew G. Knepley Level: advanced 73097cd05799SMatthew G. Knepley 7310db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 73114a1e0b3eSMatthew G. Knepley @*/ 731271f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 731371f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 73147773e69fSMatthew G. Knepley { 731571f0bbf9SMatthew G. Knepley /* Closure ordering */ 73167773e69fSMatthew G. Knepley PetscSection clSection; 73177773e69fSMatthew G. Knepley IS clPoints; 731871f0bbf9SMatthew G. Knepley const PetscInt *clp; 731971f0bbf9SMatthew G. Knepley PetscInt *points; 732071f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 732171f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 73224acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 732371f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 732471f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 732571f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 732671f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 732771f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 732871f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 732971f0bbf9SMatthew G. Knepley 733071f0bbf9SMatthew G. Knepley PetscInt *idx; 733171f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 733271f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 73337773e69fSMatthew G. Knepley 733471f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 73357773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 73367773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 733736fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7338dadcf809SJacob Faibussowitsch if (numIndices) PetscValidIntPointer(numIndices, 6); 733971f0bbf9SMatthew G. Knepley if (indices) PetscValidPointer(indices, 7); 7340dadcf809SJacob Faibussowitsch if (outOffsets) PetscValidIntPointer(outOffsets, 8); 734171f0bbf9SMatthew G. Knepley if (values) PetscValidPointer(values, 9); 73429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 734363a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 73449566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 734571f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 73469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7347c459fbc1SJed Brown if (useClPerm) { 7348c459fbc1SJed Brown PetscInt depth, clsize; 73499566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7350c459fbc1SJed Brown for (clsize=0,p=0; p<Ncl; p++) { 7351c459fbc1SJed Brown PetscInt dof; 73529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 7353c459fbc1SJed Brown clsize += dof; 7354c459fbc1SJed Brown } 73559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 7356c459fbc1SJed Brown } 735771f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 735871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl*2; p += 2) { 73597773e69fSMatthew G. Knepley PetscInt dof, fdof; 73607773e69fSMatthew G. Knepley 73619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 73627773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 73639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 73647773e69fSMatthew G. Knepley offsets[f+1] += fdof; 73657773e69fSMatthew G. Knepley } 736671f0bbf9SMatthew G. Knepley Ni += dof; 73677773e69fSMatthew G. Knepley } 73687773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 73691dca8a05SBarry 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); 737071f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 737171f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73729566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73739566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 737471f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 737571f0bbf9SMatthew G. Knepley if (values && flips[f]) { 737671f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 73776ecaa68aSToby Isaac 737871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 737971f0bbf9SMatthew G. Knepley PetscInt pnt = points[2*p], fdof; 738071f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 738171f0bbf9SMatthew G. Knepley 73829566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 73839566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 738471f0bbf9SMatthew G. Knepley if (flip) { 738571f0bbf9SMatthew G. Knepley PetscInt i, j, k; 738671f0bbf9SMatthew G. Knepley 738771f0bbf9SMatthew G. Knepley if (!valCopy) { 73889566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 738971f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 739071f0bbf9SMatthew G. Knepley *values = valCopy; 739171f0bbf9SMatthew G. Knepley } 739271f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 739371f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 739471f0bbf9SMatthew G. Knepley 739571f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 739671f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 739771f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 73986ecaa68aSToby Isaac } 73996ecaa68aSToby Isaac } 740071f0bbf9SMatthew G. Knepley } 740171f0bbf9SMatthew G. Knepley foffset += fdof; 740271f0bbf9SMatthew G. Knepley } 740371f0bbf9SMatthew G. Knepley } 740471f0bbf9SMatthew G. Knepley } 740571f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 74069566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 740771f0bbf9SMatthew G. Knepley if (NclC) { 74089566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 740971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74109566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 74119566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 741271f0bbf9SMatthew G. Knepley } 741371f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74149566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 74159566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 741671f0bbf9SMatthew G. Knepley } 74179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 741871f0bbf9SMatthew G. Knepley Ncl = NclC; 741971f0bbf9SMatthew G. Knepley Ni = NiC; 742071f0bbf9SMatthew G. Knepley points = pointsC; 742171f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 742271f0bbf9SMatthew G. Knepley } 742371f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 74249566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 742571f0bbf9SMatthew G. Knepley if (Nf) { 742671f0bbf9SMatthew G. Knepley PetscInt idxOff; 742771f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 742871f0bbf9SMatthew G. Knepley 742971f0bbf9SMatthew G. Knepley if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 74309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 743171f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 743271f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 743371f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 743471f0bbf9SMatthew G. Knepley 74359566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 74367773e69fSMatthew G. Knepley } 74377773e69fSMatthew G. Knepley } else { 743871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 743971f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 744071f0bbf9SMatthew G. Knepley 74419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 744271f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 744371f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 744471f0bbf9SMatthew G. Knepley * global section. */ 74459566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 744671f0bbf9SMatthew G. Knepley } 744771f0bbf9SMatthew G. Knepley } 744871f0bbf9SMatthew G. Knepley } else { 744971f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 745071f0bbf9SMatthew G. Knepley 745171f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 745271f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 74534acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 74544acb8e1eSToby Isaac 74559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 745671f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 745771f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 74589566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 74597773e69fSMatthew G. Knepley } 74607773e69fSMatthew G. Knepley } 746171f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 746271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74639566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 74649566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 74654acb8e1eSToby Isaac } 746671f0bbf9SMatthew G. Knepley if (NclC) { 74679566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC)); 74687773e69fSMatthew G. Knepley } else { 74699566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 74707773e69fSMatthew G. Knepley } 747171f0bbf9SMatthew G. Knepley 747271f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 747371f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 74747773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74757773e69fSMatthew G. Knepley } 74767773e69fSMatthew G. Knepley 74777cd05799SMatthew G. Knepley /*@C 747871f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 74797cd05799SMatthew G. Knepley 74807cd05799SMatthew G. Knepley Not collective 74817cd05799SMatthew G. Knepley 74827cd05799SMatthew G. Knepley Input Parameters: 74837cd05799SMatthew G. Knepley + dm - The DM 748471f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 748571f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 748671f0bbf9SMatthew G. Knepley . point - The point defining the closure 748771f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 748871f0bbf9SMatthew G. Knepley 748971f0bbf9SMatthew G. Knepley Output Parameters: 749071f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 749171f0bbf9SMatthew G. Knepley . indices - The dof indices 749271f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 749371f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 749471f0bbf9SMatthew G. Knepley 749571f0bbf9SMatthew G. Knepley Notes: 749671f0bbf9SMatthew G. Knepley If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 749771f0bbf9SMatthew G. Knepley 749871f0bbf9SMatthew G. Knepley If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 749971f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 750071f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 750171f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 750271f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 75037cd05799SMatthew G. Knepley 75047cd05799SMatthew G. Knepley Level: advanced 75057cd05799SMatthew G. Knepley 7506db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 75077cd05799SMatthew G. Knepley @*/ 750871f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 750971f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 75107773e69fSMatthew G. Knepley { 75117773e69fSMatthew G. Knepley PetscFunctionBegin; 75127773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7513064a246eSJacob Faibussowitsch PetscValidPointer(indices, 7); 75149566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 75157773e69fSMatthew G. Knepley PetscFunctionReturn(0); 75167773e69fSMatthew G. Knepley } 75177773e69fSMatthew G. Knepley 75187f5d1fdeSMatthew G. Knepley /*@C 75197f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 75207f5d1fdeSMatthew G. Knepley 75217f5d1fdeSMatthew G. Knepley Not collective 75227f5d1fdeSMatthew G. Knepley 75237f5d1fdeSMatthew G. Knepley Input Parameters: 75247f5d1fdeSMatthew G. Knepley + dm - The DM 7525ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section 7526ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section 75277f5d1fdeSMatthew G. Knepley . A - The matrix 7528eaf898f9SPatrick Sanan . point - The point in the DM 75297f5d1fdeSMatthew G. Knepley . values - The array of values 75307f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75317f5d1fdeSMatthew G. Knepley 75327f5d1fdeSMatthew G. Knepley Fortran Notes: 75337f5d1fdeSMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 75347f5d1fdeSMatthew G. Knepley 75357f5d1fdeSMatthew G. Knepley Level: intermediate 75367f5d1fdeSMatthew G. Knepley 7537db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 75387f5d1fdeSMatthew G. Knepley @*/ 75397c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7540552f7358SJed Brown { 7541552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7542552f7358SJed Brown PetscInt *indices; 754371f0bbf9SMatthew G. Knepley PetscInt numIndices; 754471f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 7545552f7358SJed Brown PetscErrorCode ierr; 7546552f7358SJed Brown 7547552f7358SJed Brown PetscFunctionBegin; 7548552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 75499566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 75503dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 75519566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 75523dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 75533dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7554552f7358SJed Brown 75559566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75560d644c17SKarl Rupp 75579566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 7558d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 75594a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7560552f7358SJed Brown if (ierr) { 7561552f7358SJed Brown PetscMPIInt rank; 7562552f7358SJed Brown 75639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 75649566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 75659566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 75669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75679566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 7568c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7569552f7358SJed Brown } 75704a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 75714a1e0b3eSMatthew G. Knepley PetscInt i; 75729566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 757363a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 75749566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 75754a1e0b3eSMatthew G. Knepley } 757671f0bbf9SMatthew G. Knepley 75779566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75789566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 757971f0bbf9SMatthew G. Knepley PetscFunctionReturn(0); 75804acb8e1eSToby Isaac } 758171f0bbf9SMatthew G. Knepley 75824a1e0b3eSMatthew G. Knepley /*@C 75834a1e0b3eSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 75844a1e0b3eSMatthew G. Knepley 75854a1e0b3eSMatthew G. Knepley Not collective 75864a1e0b3eSMatthew G. Knepley 75874a1e0b3eSMatthew G. Knepley Input Parameters: 75884a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields 75894a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 75904a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 75914a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields 75924a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 75934a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 75944a1e0b3eSMatthew G. Knepley . A - The matrix 75954a1e0b3eSMatthew G. Knepley . point - The point in the DMs 75964a1e0b3eSMatthew G. Knepley . values - The array of values 75974a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75984a1e0b3eSMatthew G. Knepley 75994a1e0b3eSMatthew G. Knepley Level: intermediate 76004a1e0b3eSMatthew G. Knepley 7601db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 76024a1e0b3eSMatthew G. Knepley @*/ 760371f0bbf9SMatthew 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) 760471f0bbf9SMatthew G. Knepley { 760571f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmRow->data; 760671f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 760771f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 760871f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 760971f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 761071f0bbf9SMatthew G. Knepley 761171f0bbf9SMatthew G. Knepley PetscFunctionBegin; 761271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 76139566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 761471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 76159566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 761671f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 761771f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 76189566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 761971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 76209566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 762171f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 762271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 762371f0bbf9SMatthew G. Knepley 76249566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76259566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 762671f0bbf9SMatthew G. Knepley 76279566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 7628d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 76294a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 763071f0bbf9SMatthew G. Knepley if (ierr) { 763171f0bbf9SMatthew G. Knepley PetscMPIInt rank; 763271f0bbf9SMatthew G. Knepley 76339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 76349566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 76359566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 76369566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76379566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values)); 76389566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7639d3d1a6afSToby Isaac } 764071f0bbf9SMatthew G. Knepley 76419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 76439566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7644552f7358SJed Brown PetscFunctionReturn(0); 7645552f7358SJed Brown } 7646552f7358SJed Brown 7647de41b84cSMatthew 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) 7648de41b84cSMatthew G. Knepley { 7649de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmf->data; 7650de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 7651de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 7652de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 765317c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7654de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 7655412e9a14SMatthew G. Knepley DMPolytopeType ct; 76564ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7657de41b84cSMatthew G. Knepley PetscErrorCode ierr; 7658de41b84cSMatthew G. Knepley 7659de41b84cSMatthew G. Knepley PetscFunctionBegin; 7660de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7661de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 76629566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 7663de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 76649566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 7665de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 76669566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 7667de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 76689566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 7669de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7670de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 76719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 767263a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 76739566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 76749566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 7675de41b84cSMatthew G. Knepley /* Column indices */ 76769566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 76774ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 7678de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 7679de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 76809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 7681de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7682de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7683de41b84cSMatthew G. Knepley cpoints[q*2] = cpoints[p]; 7684de41b84cSMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 7685de41b84cSMatthew G. Knepley ++q; 7686de41b84cSMatthew G. Knepley } 7687de41b84cSMatthew G. Knepley } 7688de41b84cSMatthew G. Knepley numCPoints = q; 7689de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7690de41b84cSMatthew G. Knepley PetscInt fdof; 7691de41b84cSMatthew G. Knepley 76929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 76934ca5e9f5SMatthew G. Knepley if (!dof) continue; 7694de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 76959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 7696de41b84cSMatthew G. Knepley coffsets[f+1] += fdof; 7697de41b84cSMatthew G. Knepley } 7698de41b84cSMatthew G. Knepley numCIndices += dof; 7699de41b84cSMatthew G. Knepley } 7700de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7701de41b84cSMatthew G. Knepley /* Row indices */ 77029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7703412e9a14SMatthew G. Knepley { 7704012bc364SMatthew G. Knepley DMPlexTransform tr; 7705012bc364SMatthew G. Knepley DMPolytopeType *rct; 7706012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7707012bc364SMatthew G. Knepley 77089566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 77099566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 77109566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7711012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 77129566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7713412e9a14SMatthew G. Knepley } 77149566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 7715de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 7716de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 77179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 7718de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 77199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 7720de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 7721de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 77229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 77234ca5e9f5SMatthew G. Knepley if (!dof) continue; 77244ca5e9f5SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 77254ca5e9f5SMatthew G. Knepley if (s < q) continue; 7726de41b84cSMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 7727de41b84cSMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 7728de41b84cSMatthew G. Knepley ++q; 7729de41b84cSMatthew G. Knepley } 7730de41b84cSMatthew G. Knepley } 77319566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 7732de41b84cSMatthew G. Knepley } 7733de41b84cSMatthew G. Knepley numFPoints = q; 7734de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7735de41b84cSMatthew G. Knepley PetscInt fdof; 7736de41b84cSMatthew G. Knepley 77379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 77384ca5e9f5SMatthew G. Knepley if (!dof) continue; 7739de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 77409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 7741de41b84cSMatthew G. Knepley foffsets[f+1] += fdof; 7742de41b84cSMatthew G. Knepley } 7743de41b84cSMatthew G. Knepley numFIndices += dof; 7744de41b84cSMatthew G. Knepley } 7745de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7746de41b84cSMatthew G. Knepley 77471dca8a05SBarry 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); 77481dca8a05SBarry 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); 77499566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77509566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7751de41b84cSMatthew G. Knepley if (numFields) { 77524acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 77534acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 77544acb8e1eSToby Isaac 77554acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7758de41b84cSMatthew G. Knepley } 77594acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 77609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77619566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 77624acb8e1eSToby Isaac } 77634acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 77649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77659566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 77664acb8e1eSToby Isaac } 77674acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77689566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77699566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7770de41b84cSMatthew G. Knepley } 7771de41b84cSMatthew G. Knepley } else { 77724acb8e1eSToby Isaac const PetscInt **permsF = NULL; 77734acb8e1eSToby Isaac const PetscInt **permsC = NULL; 77744acb8e1eSToby Isaac 77759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 77774acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 77784acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 77794acb8e1eSToby Isaac 77809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77819566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 7782de41b84cSMatthew G. Knepley } 77834acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 77844acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 77854acb8e1eSToby Isaac 77869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77879566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 7788de41b84cSMatthew G. Knepley } 77899566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77909566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 7791de41b84cSMatthew G. Knepley } 77929566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77934acb8e1eSToby Isaac /* TODO: flips */ 7794d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 7795de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7796de41b84cSMatthew G. Knepley if (ierr) { 7797de41b84cSMatthew G. Knepley PetscMPIInt rank; 7798de41b84cSMatthew G. Knepley 77999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 78009566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 78019566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 78029566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 78039566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7804de41b84cSMatthew G. Knepley } 78059566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 78069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78079566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 78089566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7809de41b84cSMatthew G. Knepley PetscFunctionReturn(0); 7810de41b84cSMatthew G. Knepley } 7811de41b84cSMatthew G. Knepley 78127c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 78137c927364SMatthew G. Knepley { 78147c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 78157c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 78167c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 781717c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7818412e9a14SMatthew G. Knepley DMPolytopeType ct; 78197c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 78207c927364SMatthew G. Knepley 78217c927364SMatthew G. Knepley PetscFunctionBegin; 78227c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 78237c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 78249566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 78257c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 78269566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 78277c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 78289566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 78297c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 78309566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 78317c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 78329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 783363a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 78349566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 78359566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 78367c927364SMatthew G. Knepley /* Column indices */ 78379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78387c927364SMatthew G. Knepley maxFPoints = numCPoints; 78397c927364SMatthew G. Knepley /* Compress out points not in the section */ 78407c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 78419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 78427c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 78437c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 78447c927364SMatthew G. Knepley cpoints[q*2] = cpoints[p]; 78457c927364SMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 78467c927364SMatthew G. Knepley ++q; 78477c927364SMatthew G. Knepley } 78487c927364SMatthew G. Knepley } 78497c927364SMatthew G. Knepley numCPoints = q; 78507c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 78517c927364SMatthew G. Knepley PetscInt fdof; 78527c927364SMatthew G. Knepley 78539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 78547c927364SMatthew G. Knepley if (!dof) continue; 78557c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 78577c927364SMatthew G. Knepley coffsets[f+1] += fdof; 78587c927364SMatthew G. Knepley } 78597c927364SMatthew G. Knepley numCIndices += dof; 78607c927364SMatthew G. Knepley } 78617c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 78627c927364SMatthew G. Knepley /* Row indices */ 78639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7864412e9a14SMatthew G. Knepley { 7865012bc364SMatthew G. Knepley DMPlexTransform tr; 7866012bc364SMatthew G. Knepley DMPolytopeType *rct; 7867012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7868012bc364SMatthew G. Knepley 78699566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 78709566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 78719566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7872012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 78739566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7874412e9a14SMatthew G. Knepley } 78759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 78767c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 78777c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 78789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 78797c927364SMatthew G. Knepley /* Compress out points not in the section */ 78809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 78817c927364SMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 78827c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 78839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 78847c927364SMatthew G. Knepley if (!dof) continue; 78857c927364SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 78867c927364SMatthew G. Knepley if (s < q) continue; 78877c927364SMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 78887c927364SMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 78897c927364SMatthew G. Knepley ++q; 78907c927364SMatthew G. Knepley } 78917c927364SMatthew G. Knepley } 78929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 78937c927364SMatthew G. Knepley } 78947c927364SMatthew G. Knepley numFPoints = q; 78957c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 78967c927364SMatthew G. Knepley PetscInt fdof; 78977c927364SMatthew G. Knepley 78989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 78997c927364SMatthew G. Knepley if (!dof) continue; 79007c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 79019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 79027c927364SMatthew G. Knepley foffsets[f+1] += fdof; 79037c927364SMatthew G. Knepley } 79047c927364SMatthew G. Knepley numFIndices += dof; 79057c927364SMatthew G. Knepley } 79067c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 79077c927364SMatthew G. Knepley 79081dca8a05SBarry 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); 79091dca8a05SBarry 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); 79107c927364SMatthew G. Knepley if (numFields) { 79114acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 79124acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 79134acb8e1eSToby Isaac 79144acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 79159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 79169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 79177c927364SMatthew G. Knepley } 79184acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 79199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 79209566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 79214acb8e1eSToby Isaac } 79224acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 79239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79249566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 79254acb8e1eSToby Isaac } 79264acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 79279566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 79289566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 79297c927364SMatthew G. Knepley } 79307c927364SMatthew G. Knepley } else { 79314acb8e1eSToby Isaac const PetscInt **permsF = NULL; 79324acb8e1eSToby Isaac const PetscInt **permsC = NULL; 79334acb8e1eSToby Isaac 79349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79364acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 79374acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 79384acb8e1eSToby Isaac 79399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 79409566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 79417c927364SMatthew G. Knepley } 79424acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 79434acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 79444acb8e1eSToby Isaac 79459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79469566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 79477c927364SMatthew G. Knepley } 79489566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79499566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79507c927364SMatthew G. Knepley } 79519566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 79529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 79537c927364SMatthew G. Knepley PetscFunctionReturn(0); 79547c927364SMatthew G. Knepley } 79557c927364SMatthew G. Knepley 79567cd05799SMatthew G. Knepley /*@C 79577cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 79587cd05799SMatthew G. Knepley 79597cd05799SMatthew G. Knepley Input Parameter: 79607cd05799SMatthew G. Knepley . dm - The DMPlex object 79617cd05799SMatthew G. Knepley 79627cd05799SMatthew G. Knepley Output Parameter: 79637cd05799SMatthew G. Knepley . cellHeight - The height of a cell 79647cd05799SMatthew G. Knepley 79657cd05799SMatthew G. Knepley Level: developer 79667cd05799SMatthew G. Knepley 7967db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()` 79687cd05799SMatthew G. Knepley @*/ 7969552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7970552f7358SJed Brown { 7971552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7972552f7358SJed Brown 7973552f7358SJed Brown PetscFunctionBegin; 7974552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7975dadcf809SJacob Faibussowitsch PetscValidIntPointer(cellHeight, 2); 7976552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 7977552f7358SJed Brown PetscFunctionReturn(0); 7978552f7358SJed Brown } 7979552f7358SJed Brown 79807cd05799SMatthew G. Knepley /*@C 79817cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 79827cd05799SMatthew G. Knepley 79837cd05799SMatthew G. Knepley Input Parameters: 79847cd05799SMatthew G. Knepley + dm - The DMPlex object 79857cd05799SMatthew G. Knepley - cellHeight - The height of a cell 79867cd05799SMatthew G. Knepley 79877cd05799SMatthew G. Knepley Level: developer 79887cd05799SMatthew G. Knepley 7989db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()` 79907cd05799SMatthew G. Knepley @*/ 7991552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7992552f7358SJed Brown { 7993552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7994552f7358SJed Brown 7995552f7358SJed Brown PetscFunctionBegin; 7996552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7997552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 7998552f7358SJed Brown PetscFunctionReturn(0); 7999552f7358SJed Brown } 8000552f7358SJed Brown 8001e6139122SMatthew G. Knepley /*@ 8002e6139122SMatthew G. Knepley DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 8003e6139122SMatthew G. Knepley 8004e6139122SMatthew G. Knepley Input Parameter: 8005e6139122SMatthew G. Knepley . dm - The DMPlex object 8006e6139122SMatthew G. Knepley 8007e6139122SMatthew G. Knepley Output Parameters: 80082a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL 80092a9f31c0SMatthew G. Knepley - gcEnd - The upper bound on ghost cells, or NULL 8010e6139122SMatthew G. Knepley 80112a9f31c0SMatthew G. Knepley Level: advanced 8012e6139122SMatthew G. Knepley 8013db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 8014e6139122SMatthew G. Knepley @*/ 8015e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 8016e6139122SMatthew G. Knepley { 8017412e9a14SMatthew G. Knepley DMLabel ctLabel; 8018e6139122SMatthew G. Knepley 8019e6139122SMatthew G. Knepley PetscFunctionBegin; 8020e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 80229566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd)); 8023e6139122SMatthew G. Knepley PetscFunctionReturn(0); 8024e6139122SMatthew G. Knepley } 8025e6139122SMatthew G. Knepley 80269886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8027552f7358SJed Brown { 8028552f7358SJed Brown PetscSection section, globalSection; 8029552f7358SJed Brown PetscInt *numbers, p; 8030552f7358SJed Brown 8031552f7358SJed Brown PetscFunctionBegin; 80326c1ef331SVaclav Hapla if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf)); 80339566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 80349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8035552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, 1)); 8037552f7358SJed Brown } 80389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 80399566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 80409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8041552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart])); 8043ef48cebcSMatthew G. Knepley if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8044ef48cebcSMatthew G. Knepley else numbers[p-pStart] += shift; 8045552f7358SJed Brown } 80469566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8047ef48cebcSMatthew G. Knepley if (globalSize) { 8048ef48cebcSMatthew G. Knepley PetscLayout layout; 80499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout)); 80509566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 80519566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8052ef48cebcSMatthew G. Knepley } 80539566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 80549566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 8055552f7358SJed Brown PetscFunctionReturn(0); 8056552f7358SJed Brown } 8057552f7358SJed Brown 805881ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8059552f7358SJed Brown { 8060412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8061552f7358SJed Brown 8062552f7358SJed Brown PetscFunctionBegin; 80639566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 80649566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 80659566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 80669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 806781ed3555SMatthew G. Knepley PetscFunctionReturn(0); 8068552f7358SJed Brown } 806981ed3555SMatthew G. Knepley 80708dab3259SMatthew G. Knepley /*@ 80717cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 80727cd05799SMatthew G. Knepley 80737cd05799SMatthew G. Knepley Input Parameter: 80747cd05799SMatthew G. Knepley . dm - The DMPlex object 80757cd05799SMatthew G. Knepley 80767cd05799SMatthew G. Knepley Output Parameter: 80777cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 80787cd05799SMatthew G. Knepley 80797cd05799SMatthew G. Knepley Level: developer 80807cd05799SMatthew G. Knepley 8081db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()` 80827cd05799SMatthew G. Knepley @*/ 808381ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 808481ed3555SMatthew G. Knepley { 808581ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 808681ed3555SMatthew G. Knepley 808781ed3555SMatthew G. Knepley PetscFunctionBegin; 808881ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80899566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8090552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 8091552f7358SJed Brown PetscFunctionReturn(0); 8092552f7358SJed Brown } 8093552f7358SJed Brown 809481ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 809581ed3555SMatthew G. Knepley { 8096412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 809781ed3555SMatthew G. Knepley 809881ed3555SMatthew G. Knepley PetscFunctionBegin; 809981ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 81019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 810281ed3555SMatthew G. Knepley PetscFunctionReturn(0); 810381ed3555SMatthew G. Knepley } 810481ed3555SMatthew G. Knepley 81058dab3259SMatthew G. Knepley /*@ 81066aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 81077cd05799SMatthew G. Knepley 81087cd05799SMatthew G. Knepley Input Parameter: 81097cd05799SMatthew G. Knepley . dm - The DMPlex object 81107cd05799SMatthew G. Knepley 81117cd05799SMatthew G. Knepley Output Parameter: 81127cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 81137cd05799SMatthew G. Knepley 81147cd05799SMatthew G. Knepley Level: developer 81157cd05799SMatthew G. Knepley 8116db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 81177cd05799SMatthew G. Knepley @*/ 8118552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8119552f7358SJed Brown { 8120552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 8121552f7358SJed Brown 8122552f7358SJed Brown PetscFunctionBegin; 8123552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81249566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8125552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 8126552f7358SJed Brown PetscFunctionReturn(0); 8127552f7358SJed Brown } 8128552f7358SJed Brown 81298dab3259SMatthew G. Knepley /*@ 81307cd05799SMatthew G. Knepley DMPlexCreatePointNumbering - Create a global numbering for all points on this process 81317cd05799SMatthew G. Knepley 81327cd05799SMatthew G. Knepley Input Parameter: 81337cd05799SMatthew G. Knepley . dm - The DMPlex object 81347cd05799SMatthew G. Knepley 81357cd05799SMatthew G. Knepley Output Parameter: 81367cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 81377cd05799SMatthew G. Knepley 81387cd05799SMatthew G. Knepley Level: developer 81397cd05799SMatthew G. Knepley 8140db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 81417cd05799SMatthew G. Knepley @*/ 8142ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8143ef48cebcSMatthew G. Knepley { 8144ef48cebcSMatthew G. Knepley IS nums[4]; 8145862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8146ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 8147ef48cebcSMatthew G. Knepley 8148ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8149ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 81518abc87a0SMichael Lange /* For unstratified meshes use dim instead of depth */ 81529566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 8153862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8154862913ffSStefano Zampini PetscInt end; 8155862913ffSStefano Zampini 8156862913ffSStefano Zampini depths[d] = depth-d; 81579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 8158862913ffSStefano Zampini if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8159862913ffSStefano Zampini } 81609566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(depth+1, starts, depths)); 81611c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm))); 8162862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 81631dca8a05SBarry 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]); 8164862913ffSStefano Zampini } 8165ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8166ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8167ef48cebcSMatthew G. Knepley 81689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 81699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8170ef48cebcSMatthew G. Knepley shift += gsize; 8171ef48cebcSMatthew G. Knepley } 81729566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers)); 81739566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 8174ef48cebcSMatthew G. Knepley PetscFunctionReturn(0); 8175ef48cebcSMatthew G. Knepley } 8176ef48cebcSMatthew G. Knepley 817708a22f4bSMatthew G. Knepley /*@ 817808a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 817908a22f4bSMatthew G. Knepley 818008a22f4bSMatthew G. Knepley Input Parameter: 818108a22f4bSMatthew G. Knepley . dm - The DMPlex object 818208a22f4bSMatthew G. Knepley 818308a22f4bSMatthew G. Knepley Output Parameter: 818408a22f4bSMatthew G. Knepley . ranks - The rank field 818508a22f4bSMatthew G. Knepley 818608a22f4bSMatthew G. Knepley Options Database Keys: 818708a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 818808a22f4bSMatthew G. Knepley 818908a22f4bSMatthew G. Knepley Level: intermediate 819008a22f4bSMatthew G. Knepley 8191db781477SPatrick Sanan .seealso: `DMView()` 819208a22f4bSMatthew G. Knepley @*/ 819308a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 819408a22f4bSMatthew G. Knepley { 819508a22f4bSMatthew G. Knepley DM rdm; 819608a22f4bSMatthew G. Knepley PetscFE fe; 819708a22f4bSMatthew G. Knepley PetscScalar *r; 819808a22f4bSMatthew G. Knepley PetscMPIInt rank; 8199a55f9a55SMatthew G. Knepley DMPolytopeType ct; 820008a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8201a55f9a55SMatthew G. Knepley PetscBool simplex; 820208a22f4bSMatthew G. Knepley 820308a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8204f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8205f95ace6aSMatthew G. Knepley PetscValidPointer(ranks, 2); 82069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 82079566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 82089566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 82099566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8211a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 82129566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 82139566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) fe, "rank")); 82149566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 82159566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 82169566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 82179566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 82189566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *ranks, "partition")); 82199566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 822008a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 822108a22f4bSMatthew G. Knepley PetscScalar *lr; 822208a22f4bSMatthew G. Knepley 82239566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 822471f09efeSPierre Jolivet if (lr) *lr = rank; 822508a22f4bSMatthew G. Knepley } 82269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 82279566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 822808a22f4bSMatthew G. Knepley PetscFunctionReturn(0); 822908a22f4bSMatthew G. Knepley } 823008a22f4bSMatthew G. Knepley 8231ca8062c8SMatthew G. Knepley /*@ 823218e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 823318e14f0cSMatthew G. Knepley 823418e14f0cSMatthew G. Knepley Input Parameters: 823518e14f0cSMatthew G. Knepley + dm - The DMPlex 823618e14f0cSMatthew G. Knepley - label - The DMLabel 823718e14f0cSMatthew G. Knepley 823818e14f0cSMatthew G. Knepley Output Parameter: 823918e14f0cSMatthew G. Knepley . val - The label value field 824018e14f0cSMatthew G. Knepley 824118e14f0cSMatthew G. Knepley Options Database Keys: 824218e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 824318e14f0cSMatthew G. Knepley 824418e14f0cSMatthew G. Knepley Level: intermediate 824518e14f0cSMatthew G. Knepley 8246db781477SPatrick Sanan .seealso: `DMView()` 824718e14f0cSMatthew G. Knepley @*/ 824818e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 824918e14f0cSMatthew G. Knepley { 825018e14f0cSMatthew G. Knepley DM rdm; 825118e14f0cSMatthew G. Knepley PetscFE fe; 825218e14f0cSMatthew G. Knepley PetscScalar *v; 825318e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 825418e14f0cSMatthew G. Knepley 825518e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 825618e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 825718e14f0cSMatthew G. Knepley PetscValidPointer(label, 2); 825818e14f0cSMatthew G. Knepley PetscValidPointer(val, 3); 82599566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 82609566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 82619566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 82629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) fe, "label_value")); 82639566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 82649566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 82659566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 82669566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82679566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 82689566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *val, "label_value")); 82699566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 827018e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 827118e14f0cSMatthew G. Knepley PetscScalar *lv; 827218e14f0cSMatthew G. Knepley PetscInt cval; 827318e14f0cSMatthew G. Knepley 82749566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 82759566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 827618e14f0cSMatthew G. Knepley *lv = cval; 827718e14f0cSMatthew G. Knepley } 82789566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 82799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 828018e14f0cSMatthew G. Knepley PetscFunctionReturn(0); 828118e14f0cSMatthew G. Knepley } 828218e14f0cSMatthew G. Knepley 828318e14f0cSMatthew G. Knepley /*@ 8284ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8285ca8062c8SMatthew G. Knepley 828669916449SMatthew G. Knepley Input Parameter: 828769916449SMatthew G. Knepley . dm - The DMPlex object 8288ca8062c8SMatthew G. Knepley 828995eb5ee5SVaclav Hapla Notes: 829095eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 829195eb5ee5SVaclav Hapla 829295eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8293ca8062c8SMatthew G. Knepley 8294ca8062c8SMatthew G. Knepley Level: developer 8295ca8062c8SMatthew G. Knepley 8296db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8297ca8062c8SMatthew G. Knepley @*/ 8298ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm) 8299ca8062c8SMatthew G. Knepley { 8300ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8301ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8302ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 830357beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 830457beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8305ca8062c8SMatthew G. Knepley 8306ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8307ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 83089566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 83099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 83109566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8311ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 83129566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8313ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 83149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 83159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8316ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 831742e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 831842e66dfaSMatthew G. Knepley PetscInt d; 831942e66dfaSMatthew G. Knepley for (d = c-1; d >= 0; --d) { 832042e66dfaSMatthew G. Knepley if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 832142e66dfaSMatthew G. Knepley } 83229566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 83239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8324ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8325ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8326ca8062c8SMatthew G. Knepley } 832742e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s+1] != p))) { 832863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 8329ca8062c8SMatthew G. Knepley for (s = 0; s < coneSize; ++s) { 833063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 8331ca8062c8SMatthew G. Knepley } 83329566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 833363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 8334ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 833563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 8336ca8062c8SMatthew G. Knepley } 83379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 833863a3b9bcSJacob 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]); 833963a3b9bcSJacob Faibussowitsch else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8340ca8062c8SMatthew G. Knepley } 834142e66dfaSMatthew G. Knepley } 83429566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 834357beb4faSStefano Zampini if (p != pp) { storagecheck = PETSC_FALSE; continue; } 83449566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 83459566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8346ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 83479566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 83489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8349ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 83509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 835157beb4faSStefano Zampini if (cone[c] != pp) { c = 0; break; } 8352ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8353ca8062c8SMatthew G. Knepley } 8354ca8062c8SMatthew G. Knepley if (c >= coneSize) { 835563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 8356ca8062c8SMatthew G. Knepley for (c = 0; c < supportSize; ++c) { 835763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 8358ca8062c8SMatthew G. Knepley } 83599566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 836063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 8361ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 836263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 8363ca8062c8SMatthew G. Knepley } 83649566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 836563a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8366ca8062c8SMatthew G. Knepley } 8367ca8062c8SMatthew G. Knepley } 8368ca8062c8SMatthew G. Knepley } 836957beb4faSStefano Zampini if (storagecheck) { 83709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 83719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 837263a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 837357beb4faSStefano Zampini } 8374ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8375ca8062c8SMatthew G. Knepley } 8376ca8062c8SMatthew G. Knepley 8377412e9a14SMatthew G. Knepley /* 8378412e9a14SMatthew 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. 8379412e9a14SMatthew G. Knepley */ 8380412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8381412e9a14SMatthew G. Knepley { 8382412e9a14SMatthew G. Knepley DMPolytopeType cct; 8383412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8384412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8385412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8386412e9a14SMatthew G. Knepley 8387412e9a14SMatthew G. Knepley PetscFunctionBegin; 8388412e9a14SMatthew G. Knepley *unsplit = 0; 8389412e9a14SMatthew G. Knepley switch (ct) { 8390b5a892a1SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 8391b5a892a1SMatthew G. Knepley ptpoints[npt++] = c; 8392b5a892a1SMatthew G. Knepley break; 8393412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 83949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 83959566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8396412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 8398412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8399412e9a14SMatthew G. Knepley } 8400412e9a14SMatthew G. Knepley break; 8401412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8402412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 84039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 84049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8405412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 84069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 84079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8408412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 84099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8410412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8411412e9a14SMatthew G. Knepley PetscInt p; 8412412e9a14SMatthew G. Knepley for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8413412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8414412e9a14SMatthew G. Knepley } 8415412e9a14SMatthew G. Knepley } 8416412e9a14SMatthew G. Knepley } 8417412e9a14SMatthew G. Knepley break; 8418412e9a14SMatthew G. Knepley default: break; 8419412e9a14SMatthew G. Knepley } 8420412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 84219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8422412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8423412e9a14SMatthew G. Knepley } 8424412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 8425412e9a14SMatthew G. Knepley } 8426412e9a14SMatthew G. Knepley 8427ca8062c8SMatthew G. Knepley /*@ 8428ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8429ca8062c8SMatthew G. Knepley 8430ca8062c8SMatthew G. Knepley Input Parameters: 8431ca8062c8SMatthew G. Knepley + dm - The DMPlex object 843258723a97SMatthew G. Knepley - cellHeight - Normally 0 8433ca8062c8SMatthew G. Knepley 843495eb5ee5SVaclav Hapla Notes: 843595eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 843625c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 8437ca8062c8SMatthew G. Knepley 843895eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 843995eb5ee5SVaclav Hapla 8440ca8062c8SMatthew G. Knepley Level: developer 8441ca8062c8SMatthew G. Knepley 8442db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8443ca8062c8SMatthew G. Knepley @*/ 844425c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8445ca8062c8SMatthew G. Knepley { 8446412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 8447412e9a14SMatthew G. Knepley DMPolytopeType ct; 8448412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 8449ca8062c8SMatthew G. Knepley 8450ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8451ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84529566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 84539566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 84549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8455412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8456412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 8457412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 845858723a97SMatthew G. Knepley 84599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 846063a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt) ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 8461412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 8462412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 84639566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 846463a3b9bcSJacob 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)); 8465412e9a14SMatthew G. Knepley } 84669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 846758723a97SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 846858723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 8469412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 847058723a97SMatthew G. Knepley } 84719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8472412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 8473412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8474412e9a14SMatthew G. Knepley PetscInt unsplit; 847542363296SMatthew G. Knepley 84769566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8477412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 847842363296SMatthew G. Knepley } 847963a3b9bcSJacob 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)); 848042363296SMatthew G. Knepley } 8481ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8482ca8062c8SMatthew G. Knepley } 84839bf0dad6SMatthew G. Knepley 84849bf0dad6SMatthew G. Knepley /*@ 84859bf0dad6SMatthew 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 84869bf0dad6SMatthew G. Knepley 84878f6815adSVaclav Hapla Collective 8488899ea2b8SJacob Faibussowitsch 84899bf0dad6SMatthew G. Knepley Input Parameters: 84909bf0dad6SMatthew G. Knepley + dm - The DMPlex object 84919bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 84929bf0dad6SMatthew G. Knepley 849345da879fSVaclav Hapla Notes: 849445da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 849545da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 849645da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 849745da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 84989bf0dad6SMatthew G. Knepley 849995eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 850095eb5ee5SVaclav Hapla 85019bf0dad6SMatthew G. Knepley Level: developer 85029bf0dad6SMatthew G. Knepley 8503db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 85049bf0dad6SMatthew G. Knepley @*/ 850525c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 85069bf0dad6SMatthew G. Knepley { 8507ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8508899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 85099bf0dad6SMatthew G. Knepley 85109bf0dad6SMatthew G. Knepley PetscFunctionBegin; 85119bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85128f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 851345da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 85148f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 85158f6815adSVaclav Hapla PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"); 85168f6815adSVaclav Hapla PetscFunctionReturn(0); 8517899ea2b8SJacob Faibussowitsch } 8518899ea2b8SJacob Faibussowitsch 85199566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 85209566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 85219566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8522ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 85239566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 85243554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8525412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 8526412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 8527ba2698f1SMatthew G. Knepley DMPolytopeType ct; 8528412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 8529412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 85309bf0dad6SMatthew G. Knepley 85319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 85329566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8533412e9a14SMatthew G. Knepley if (unsplit) continue; 85349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 85359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 85369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 85379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85389bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 85399bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 85409bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 85419bf0dad6SMatthew G. Knepley } 85429566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 854363a3b9bcSJacob 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); 85449bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 8545d4961f80SStefano Zampini DMPolytopeType fct; 85469bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 85479bf0dad6SMatthew G. Knepley 85489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 85499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 85509bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize*2; cl += 2) { 85519bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 85529bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 85539bf0dad6SMatthew G. Knepley } 855463a3b9bcSJacob 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]); 85559bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 8556b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff+v]) { 8557b5a892a1SMatthew G. Knepley PetscInt v1; 8558b5a892a1SMatthew G. Knepley 85599566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 856063a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 85619566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 856263a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff+v1])); 85639566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 856463a3b9bcSJacob 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]); 8565b5a892a1SMatthew G. Knepley } 85669bf0dad6SMatthew G. Knepley } 85679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 8568412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 85699bf0dad6SMatthew G. Knepley } 85709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 85719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85729bf0dad6SMatthew G. Knepley } 85733554e41dSMatthew G. Knepley } 8574552f7358SJed Brown PetscFunctionReturn(0); 8575552f7358SJed Brown } 85763913d7c8SMatthew G. Knepley 8577bb6a34a8SMatthew G. Knepley /*@ 8578bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 8579bb6a34a8SMatthew G. Knepley 8580bb6a34a8SMatthew G. Knepley Input Parameter: 8581bb6a34a8SMatthew G. Knepley . dm - The DMPlex object 8582bb6a34a8SMatthew G. Knepley 858395eb5ee5SVaclav Hapla Notes: 858495eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 858595eb5ee5SVaclav Hapla 858695eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8587bb6a34a8SMatthew G. Knepley 8588bb6a34a8SMatthew G. Knepley Level: developer 8589bb6a34a8SMatthew G. Knepley 8590db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8591bb6a34a8SMatthew G. Knepley @*/ 8592bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm) 8593bb6a34a8SMatthew G. Knepley { 8594a2a9e04cSMatthew G. Knepley Vec coordinates; 8595bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 8596bb6a34a8SMatthew G. Knepley PetscReal vol; 859751a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 8598bb6a34a8SMatthew G. Knepley 8599bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 86009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 86019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 860251a74b61SMatthew G. Knepley if (dim != dE) PetscFunctionReturn(0); 86039566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8604bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 86059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8606a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 86079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8608412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8609412e9a14SMatthew G. Knepley DMPolytopeType ct; 8610412e9a14SMatthew G. Knepley PetscInt unsplit; 8611412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 8612412e9a14SMatthew G. Knepley 86139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 8614412e9a14SMatthew G. Knepley switch (ct) { 8615412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 8616412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8617412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8618412e9a14SMatthew G. Knepley ignoreZeroVol = PETSC_TRUE; break; 8619412e9a14SMatthew G. Knepley default: break; 8620412e9a14SMatthew G. Knepley } 8621412e9a14SMatthew G. Knepley switch (ct) { 8622412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 8623412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8624412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8625a2a9e04cSMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 8626412e9a14SMatthew G. Knepley continue; 8627412e9a14SMatthew G. Knepley default: break; 8628412e9a14SMatthew G. Knepley } 86299566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8630412e9a14SMatthew G. Knepley if (unsplit) continue; 86319566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 86321dca8a05SBarry 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); 863363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ*refVol))); 8634*6858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 8635*6858538eSMatthew G. Knepley if (depth > 1) { 86369566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 86371dca8a05SBarry 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); 863863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double) vol)); 8639bb6a34a8SMatthew G. Knepley } 8640bb6a34a8SMatthew G. Knepley } 8641bb6a34a8SMatthew G. Knepley PetscFunctionReturn(0); 8642bb6a34a8SMatthew G. Knepley } 8643bb6a34a8SMatthew G. Knepley 864403da9461SVaclav Hapla /*@ 86457726db96SVaclav Hapla DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex. 86467726db96SVaclav Hapla 86477726db96SVaclav Hapla Collective 864803da9461SVaclav Hapla 864903da9461SVaclav Hapla Input Parameters: 86507726db96SVaclav Hapla + dm - The DMPlex object 86517726db96SVaclav Hapla - pointSF - The Point SF, or NULL for Point SF attached to DM 865203da9461SVaclav Hapla 8653e83a0d2dSVaclav Hapla Notes: 8654e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 865503da9461SVaclav Hapla 865695eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 865795eb5ee5SVaclav Hapla 865803da9461SVaclav Hapla Level: developer 865903da9461SVaclav Hapla 8660db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()` 866103da9461SVaclav Hapla @*/ 86627726db96SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF) 866303da9461SVaclav Hapla { 86647726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 86657726db96SVaclav Hapla const PetscInt *locals; 86667726db96SVaclav Hapla const PetscSFNode *remotes; 8667f0cfc026SVaclav Hapla PetscBool distributed; 86687726db96SVaclav Hapla MPI_Comm comm; 86697726db96SVaclav Hapla PetscMPIInt rank; 867003da9461SVaclav Hapla 867103da9461SVaclav Hapla PetscFunctionBegin; 867203da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86737726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 86747726db96SVaclav Hapla else pointSF = dm->sf; 86757726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 86767726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 86777726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 86787726db96SVaclav Hapla { 86797726db96SVaclav Hapla PetscMPIInt mpiFlag; 86807726db96SVaclav Hapla 86817726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF),&mpiFlag)); 86827726db96SVaclav 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); 86837726db96SVaclav Hapla } 86847726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 86859566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 86867726db96SVaclav Hapla if (!distributed) { 86877726db96SVaclav 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); 86888918e3e2SVaclav Hapla PetscFunctionReturn(0); 86898918e3e2SVaclav Hapla } 86907726db96SVaclav 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); 86917726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 869203da9461SVaclav Hapla 86937726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 86947726db96SVaclav Hapla { 86957726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 86967726db96SVaclav Hapla 86977726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86987726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 86997726db96SVaclav Hapla PetscCheck(pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd-pStart, nroots); 87007726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 87017726db96SVaclav Hapla } 87027726db96SVaclav Hapla 87037726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 87047726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 87057726db96SVaclav 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); 87067726db96SVaclav Hapla } 87077726db96SVaclav Hapla 87087726db96SVaclav Hapla /* Check there are no cells in interface */ 87097726db96SVaclav Hapla if (!overlap) { 87107726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 87117726db96SVaclav Hapla 87129566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87139566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 8714f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 87157726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 8716f5869d18SMatthew G. Knepley 87177726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 87187726db96SVaclav Hapla } 871903da9461SVaclav Hapla } 8720ece87651SVaclav Hapla 87217726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 87227726db96SVaclav Hapla { 87237726db96SVaclav Hapla const PetscInt *rootdegree; 87247726db96SVaclav Hapla 87257726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 87267726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 8727f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 87287726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 8729f5869d18SMatthew G. Knepley const PetscInt *cone; 8730f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 8731f5869d18SMatthew G. Knepley 87329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 87339566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 8734f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8735f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 87367726db96SVaclav Hapla if (locals) { 87379566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 87387726db96SVaclav Hapla } else { 87397726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 87407726db96SVaclav Hapla } 874163a3b9bcSJacob 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]); 8742f5869d18SMatthew G. Knepley } 8743f5869d18SMatthew G. Knepley } 8744ece87651SVaclav Hapla } 87457726db96SVaclav Hapla } 874603da9461SVaclav Hapla PetscFunctionReturn(0); 874703da9461SVaclav Hapla } 874803da9461SVaclav Hapla 87497f9d8d6cSVaclav Hapla /*@ 87507f9d8d6cSVaclav Hapla DMPlexCheck - Perform various checks of Plex sanity 87517f9d8d6cSVaclav Hapla 87527f9d8d6cSVaclav Hapla Input Parameter: 87537f9d8d6cSVaclav Hapla . dm - The DMPlex object 87547f9d8d6cSVaclav Hapla 87557f9d8d6cSVaclav Hapla Notes: 87567f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 87577f9d8d6cSVaclav Hapla 87587f9d8d6cSVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 87597f9d8d6cSVaclav Hapla 87607f9d8d6cSVaclav Hapla Currently does not include DMPlexCheckCellShape(). 87617f9d8d6cSVaclav Hapla 87627f9d8d6cSVaclav Hapla Level: developer 87637f9d8d6cSVaclav Hapla 87647f9d8d6cSVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 87657f9d8d6cSVaclav Hapla @*/ 87667f9d8d6cSVaclav Hapla PetscErrorCode DMPlexCheck(DM dm) 8767b5a892a1SMatthew G. Knepley { 87687f9d8d6cSVaclav Hapla PetscInt cellHeight; 87697f9d8d6cSVaclav Hapla 8770b5a892a1SMatthew G. Knepley PetscFunctionBegin; 87717f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87729566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 87739566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 87749566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 87759566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 87767726db96SVaclav Hapla PetscCall(DMPlexCheckPointSF(dm, NULL)); 87779566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 8778b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 8779b5a892a1SMatthew G. Knepley } 8780b5a892a1SMatthew G. Knepley 8781068a5610SStefano Zampini typedef struct cell_stats 8782068a5610SStefano Zampini { 8783068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 8784068a5610SStefano Zampini PetscInt count; 8785068a5610SStefano Zampini } cell_stats_t; 8786068a5610SStefano Zampini 878725befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8788068a5610SStefano Zampini { 8789068a5610SStefano Zampini PetscInt i, N = *len; 8790068a5610SStefano Zampini 8791068a5610SStefano Zampini for (i = 0; i < N; i++) { 8792068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *) a; 8793068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *) b; 8794068a5610SStefano Zampini 8795068a5610SStefano Zampini B->min = PetscMin(A->min,B->min); 8796068a5610SStefano Zampini B->max = PetscMax(A->max,B->max); 8797068a5610SStefano Zampini B->sum += A->sum; 8798068a5610SStefano Zampini B->squaresum += A->squaresum; 8799068a5610SStefano Zampini B->count += A->count; 8800068a5610SStefano Zampini } 8801068a5610SStefano Zampini } 8802068a5610SStefano Zampini 8803068a5610SStefano Zampini /*@ 880443fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8805068a5610SStefano Zampini 88068261a58bSMatthew G. Knepley Collective on dm 88078261a58bSMatthew G. Knepley 8808068a5610SStefano Zampini Input Parameters: 8809068a5610SStefano Zampini + dm - The DMPlex object 881043fa8764SMatthew G. Knepley . output - If true, statistics will be displayed on stdout 881143fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8812068a5610SStefano Zampini 881395eb5ee5SVaclav Hapla Notes: 881495eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 881595eb5ee5SVaclav Hapla 881695eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8817068a5610SStefano Zampini 8818068a5610SStefano Zampini Level: developer 8819068a5610SStefano Zampini 8820db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 8821068a5610SStefano Zampini @*/ 882243fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8823068a5610SStefano Zampini { 8824068a5610SStefano Zampini DM dmCoarse; 882543fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 882643fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 882743fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 882843fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8829412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 883043fa8764SMatthew G. Knepley PetscMPIInt rank,size; 8831068a5610SStefano Zampini 8832068a5610SStefano Zampini PetscFunctionBegin; 8833068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8834068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 8835068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 8836068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 8837068a5610SStefano Zampini stats.count = 0; 8838068a5610SStefano Zampini 88399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 88409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 88419566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm,&cdim)); 88429566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 88439566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd)); 88449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd)); 8845412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 8846068a5610SStefano Zampini PetscInt i; 8847068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8848068a5610SStefano Zampini 88499566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ)); 885063a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 885143fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 8852068a5610SStefano Zampini frobJ += J[i] * J[i]; 8853068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 8854068a5610SStefano Zampini } 8855068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 8856068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 8857068a5610SStefano Zampini 8858068a5610SStefano Zampini stats.min = PetscMin(stats.min,cond); 8859068a5610SStefano Zampini stats.max = PetscMax(stats.max,cond); 8860068a5610SStefano Zampini stats.sum += cond; 8861068a5610SStefano Zampini stats.squaresum += cond2; 8862068a5610SStefano Zampini stats.count++; 88638261a58bSMatthew G. Knepley if (output && cond > limit) { 886443fa8764SMatthew G. Knepley PetscSection coordSection; 886543fa8764SMatthew G. Knepley Vec coordsLocal; 886643fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 886743fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 886843fa8764SMatthew G. Knepley 88699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 88709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 88719566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 887263a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double) cond)); 887343fa8764SMatthew G. Knepley for (i = 0; i < Nv/cdim; ++i) { 887463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 887543fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 88769566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 88779566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]))); 887843fa8764SMatthew G. Knepley } 88799566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 888043fa8764SMatthew G. Knepley } 88819566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 888243fa8764SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) { 888343fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 888443fa8764SMatthew G. Knepley 888543fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 888643fa8764SMatthew G. Knepley PetscReal len; 888743fa8764SMatthew G. Knepley 88889566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 888963a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double) len)); 889043fa8764SMatthew G. Knepley } 889143fa8764SMatthew G. Knepley } 88929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 88939566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 889443fa8764SMatthew G. Knepley } 8895068a5610SStefano Zampini } 88969566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 8897068a5610SStefano Zampini 8898068a5610SStefano Zampini if (size > 1) { 8899068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4,1}; 8900068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8901068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8902068a5610SStefano Zampini MPI_Op statReduce; 8903068a5610SStefano Zampini 89049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType)); 89059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 89069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 89079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm)); 89089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 89099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 8910068a5610SStefano Zampini } else { 89119566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats,&stats,1)); 8912068a5610SStefano Zampini } 8913dd400576SPatrick Sanan if (rank == 0) { 8914068a5610SStefano Zampini count = globalStats.count; 8915068a5610SStefano Zampini min = globalStats.min; 8916068a5610SStefano Zampini max = globalStats.max; 8917068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 8918068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8919068a5610SStefano Zampini } 8920068a5610SStefano Zampini 8921068a5610SStefano Zampini if (output) { 892263a3b9bcSJacob 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)); 8923068a5610SStefano Zampini } 89249566063dSJacob Faibussowitsch PetscCall(PetscFree2(J,invJ)); 8925068a5610SStefano Zampini 89269566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm,&dmCoarse)); 8927068a5610SStefano Zampini if (dmCoarse) { 8928068a5610SStefano Zampini PetscBool isplex; 8929068a5610SStefano Zampini 89309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex)); 89311baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse,output,condLimit)); 8932068a5610SStefano Zampini } 8933068a5610SStefano Zampini PetscFunctionReturn(0); 8934068a5610SStefano Zampini } 8935068a5610SStefano Zampini 8936f108dbd7SJacob Faibussowitsch /*@ 8937f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8938f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 8939f108dbd7SJacob Faibussowitsch 89406ed19f2fSJacob Faibussowitsch Collective on dm 8941f108dbd7SJacob Faibussowitsch 8942f108dbd7SJacob Faibussowitsch Input Parameters: 8943f108dbd7SJacob Faibussowitsch + dm - The DMPlex object 8944f108dbd7SJacob Faibussowitsch . fv - Optional PetscFV object for pre-computed cell/face centroid information 8945f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 8946f108dbd7SJacob Faibussowitsch 8947f108dbd7SJacob Faibussowitsch Output Parameters: 8948f108dbd7SJacob Faibussowitsch + OrthQual - Vec containing orthogonal quality per cell 8949f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8950f108dbd7SJacob Faibussowitsch 8951f108dbd7SJacob Faibussowitsch Options Database Keys: 8952f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8953f108dbd7SJacob Faibussowitsch supported. 8954f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8955f108dbd7SJacob Faibussowitsch 8956f108dbd7SJacob Faibussowitsch Notes: 8957f108dbd7SJacob Faibussowitsch Orthogonal quality is given by the following formula: 8958f108dbd7SJacob Faibussowitsch 8959f108dbd7SJacob Faibussowitsch \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8960f108dbd7SJacob Faibussowitsch 8961f108dbd7SJacob 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 8962f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8963f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8964f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 8965f108dbd7SJacob Faibussowitsch 8966f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 8967f108dbd7SJacob Faibussowitsch 8968f108dbd7SJacob Faibussowitsch This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8969f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8970f108dbd7SJacob Faibussowitsch 8971f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8972f108dbd7SJacob Faibussowitsch 8973f108dbd7SJacob Faibussowitsch Level: intermediate 8974f108dbd7SJacob Faibussowitsch 8975db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()` 8976f108dbd7SJacob Faibussowitsch @*/ 8977f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8978f108dbd7SJacob Faibussowitsch { 89796ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 89806ed19f2fSJacob Faibussowitsch PetscInt *idx; 89816ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 8982f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 89836ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 8984f108dbd7SJacob Faibussowitsch MPI_Comm comm; 8985f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 8986f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 8987f108dbd7SJacob Faibussowitsch IS glob; 8988f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 8989f108dbd7SJacob Faibussowitsch PetscViewer vwr; 8990f108dbd7SJacob Faibussowitsch 8991f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 8992f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89936ed19f2fSJacob Faibussowitsch if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8994f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQual, 4); 89956bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 89969566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 89979566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 899863a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 89996ed19f2fSJacob Faibussowitsch { 90006ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 90016ed19f2fSJacob Faibussowitsch 90029566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9003f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9004f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9005f108dbd7SJacob Faibussowitsch 90069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 900798921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9008f108dbd7SJacob Faibussowitsch } 90096ed19f2fSJacob Faibussowitsch } 9010f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 9011f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQualLabel, 5); 90129566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 90139566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 90146ed19f2fSJacob Faibussowitsch } else {*OrthQualLabel = NULL;} 90159566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 90169566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 90179566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 90189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 90199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 90209566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 90219566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 90229566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE)); 90239566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 90249566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 90259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 90269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 90279566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 90289566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 90299566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 90309566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 90319566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 90329566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 90336ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++,cell++) { 90346ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9035f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9036f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9037898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9038f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9039f108dbd7SJacob Faibussowitsch 90406ed19f2fSJacob Faibussowitsch idx[cellIter] = cell-cStart; 9041f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9042f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 90439566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 90449566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9045f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 90469566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 90476ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 90486ed19f2fSJacob Faibussowitsch PetscInt i; 90496ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9050f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9051f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9052f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9053f108dbd7SJacob Faibussowitsch 9054f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9055f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 90569566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9057f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 90586ed19f2fSJacob Faibussowitsch { 90596ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 90606ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 90616ed19f2fSJacob Faibussowitsch 90629566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 90639566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 90649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 90656ed19f2fSJacob Faibussowitsch } 9066f108dbd7SJacob Faibussowitsch 9067f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9068f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9069f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9070f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9071f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9072addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9073addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9074addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9075f108dbd7SJacob Faibussowitsch } 9076addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9077addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9078addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9079f108dbd7SJacob Faibussowitsch 9080f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9081f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9082f108dbd7SJacob Faibussowitsch ci[i] = ci[i]/normci; 9083f108dbd7SJacob Faibussowitsch fi[i] = fi[i]/normfi; 9084f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i]/normai; 9085f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9086f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9087f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9088f108dbd7SJacob Faibussowitsch } 9089f108dbd7SJacob Faibussowitsch if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9090f108dbd7SJacob Faibussowitsch minvalc = PetscRealPart(cArr[cellneighiter]); 9091f108dbd7SJacob Faibussowitsch } 9092f108dbd7SJacob Faibussowitsch if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9093f108dbd7SJacob Faibussowitsch minvalf = PetscRealPart(fArr[cellneighiter]); 9094f108dbd7SJacob Faibussowitsch } 9095f108dbd7SJacob Faibussowitsch } 90969566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 90979566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9098f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 90996ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9100f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 91019566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9102f108dbd7SJacob Faibussowitsch } 9103f108dbd7SJacob Faibussowitsch } 91049566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES)); 91059566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 91069566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 91079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 91089566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 91099566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9110f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 91119566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9112f108dbd7SJacob Faibussowitsch } 91139566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 91149566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vwr)); 91159566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 9116f108dbd7SJacob Faibussowitsch PetscFunctionReturn(0); 9117f108dbd7SJacob Faibussowitsch } 9118f108dbd7SJacob Faibussowitsch 91191eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 91201eb70e55SToby Isaac * interpolator construction */ 91211eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 91221eb70e55SToby Isaac { 91231eb70e55SToby Isaac PetscSection section, newSection, gsection; 91241eb70e55SToby Isaac PetscSF sf; 91251eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 91261eb70e55SToby Isaac 91271eb70e55SToby Isaac PetscFunctionBegin; 91281eb70e55SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 91291eb70e55SToby Isaac PetscValidPointer(odm,2); 91309566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 91319566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 91329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm))); 91331eb70e55SToby Isaac if (!ghasConstraints) { 91349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 91351eb70e55SToby Isaac *odm = dm; 91361eb70e55SToby Isaac PetscFunctionReturn(0); 91371eb70e55SToby Isaac } 91389566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 91399566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 91409566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 91419566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 91429566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 91439566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 91449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 91451eb70e55SToby Isaac PetscFunctionReturn(0); 91461eb70e55SToby Isaac } 91471eb70e55SToby Isaac 91481eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 91491eb70e55SToby Isaac { 91501eb70e55SToby Isaac DM dmco, dmfo; 91511eb70e55SToby Isaac Mat interpo; 91521eb70e55SToby Isaac Vec rscale; 91531eb70e55SToby Isaac Vec cglobalo, clocal; 91541eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 91551eb70e55SToby Isaac PetscBool regular; 91561eb70e55SToby Isaac 91571eb70e55SToby Isaac PetscFunctionBegin; 91589566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 91599566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 91609566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 91619566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 91629566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 91639566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 91649566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 91659566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 91669566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 91679566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 91689566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 91699566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 91709566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 91719566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 91729566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 91739566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 91749566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 91759566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 91769566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 91779566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 91789566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 91799566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 91809566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 91819566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 91821eb70e55SToby Isaac *shift = fglobal; 91839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 91849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 91859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 91869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 91879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 91889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 91899566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 91909566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 91911eb70e55SToby Isaac PetscFunctionReturn(0); 91921eb70e55SToby Isaac } 91931eb70e55SToby Isaac 91941eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 91951eb70e55SToby Isaac { 91961eb70e55SToby Isaac PetscObject shifto; 91971eb70e55SToby Isaac Vec shift; 91981eb70e55SToby Isaac 91991eb70e55SToby Isaac PetscFunctionBegin; 92001eb70e55SToby Isaac if (!interp) { 92011eb70e55SToby Isaac Vec rscale; 92021eb70e55SToby Isaac 92039566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 92049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 92051eb70e55SToby Isaac } else { 92069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 92071eb70e55SToby Isaac } 92089566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 92091eb70e55SToby Isaac if (!shifto) { 92109566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 92119566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift)); 92121eb70e55SToby Isaac shifto = (PetscObject) shift; 92139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 92141eb70e55SToby Isaac } 92151eb70e55SToby Isaac shift = (Vec) shifto; 92169566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 92179566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 92189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 92191eb70e55SToby Isaac PetscFunctionReturn(0); 92201eb70e55SToby Isaac } 92211eb70e55SToby Isaac 9222bceba477SMatthew G. Knepley /* Pointwise interpolation 9223bceba477SMatthew G. Knepley Just code FEM for now 9224bceba477SMatthew G. Knepley u^f = I u^c 92254ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 92264ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 92274ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9228bceba477SMatthew G. Knepley */ 9229bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9230bceba477SMatthew G. Knepley { 9231bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9232bceba477SMatthew G. Knepley PetscInt m, n; 9233a063dac3SMatthew G. Knepley void *ctx; 923468132eb9SMatthew G. Knepley DM cdm; 9235cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9236bceba477SMatthew G. Knepley 9237bceba477SMatthew G. Knepley PetscFunctionBegin; 92389566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 92399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 92409566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 92419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 924268132eb9SMatthew G. Knepley 92439566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 92449566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation)); 92459566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 92469566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 92479566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 924868132eb9SMatthew G. Knepley 92499566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 92509566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 92519566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 92529566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 92539566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 92544db47ee9SStefano Zampini if (scaling) { 92555d1c2e58SMatthew G. Knepley /* Use naive scaling */ 92569566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 92574db47ee9SStefano Zampini } 9258a063dac3SMatthew G. Knepley PetscFunctionReturn(0); 9259a063dac3SMatthew G. Knepley } 9260bceba477SMatthew G. Knepley 92616dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9262a063dac3SMatthew G. Knepley { 92636dbf9973SLawrence Mitchell VecScatter ctx; 926490748bafSMatthew G. Knepley 9265a063dac3SMatthew G. Knepley PetscFunctionBegin; 92669566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 92679566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 92689566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 9269bceba477SMatthew G. Knepley PetscFunctionReturn(0); 9270bceba477SMatthew G. Knepley } 9271bceba477SMatthew G. Knepley 92723e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 92733e9753d6SMatthew G. Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 92743e9753d6SMatthew G. Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 92753e9753d6SMatthew G. Knepley PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 92763e9753d6SMatthew G. Knepley { 927700635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 927800635df3SMatthew G. Knepley PetscInt c; 927900635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 92803e9753d6SMatthew G. Knepley } 92813e9753d6SMatthew G. Knepley 9282b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9283b4937a87SMatthew G. Knepley { 9284b4937a87SMatthew G. Knepley DM dmc; 9285b4937a87SMatthew G. Knepley PetscDS ds; 9286b4937a87SMatthew G. Knepley Vec ones, locmass; 9287b4937a87SMatthew G. Knepley IS cellIS; 9288b4937a87SMatthew G. Knepley PetscFormKey key; 9289b4937a87SMatthew G. Knepley PetscInt depth; 9290b4937a87SMatthew G. Knepley 9291b4937a87SMatthew G. Knepley PetscFunctionBegin; 92929566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 92939566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 92949566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 92959566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92969566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 92979566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 92989566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 92999566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 93009566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 93019566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 93029566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9303b4937a87SMatthew G. Knepley key.label = NULL; 9304b4937a87SMatthew G. Knepley key.value = 0; 9305b4937a87SMatthew G. Knepley key.field = 0; 9306b4937a87SMatthew G. Knepley key.part = 0; 93079566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 93089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 93099566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 93109566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 93119566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 93129566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 93139566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 93149566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 9315b4937a87SMatthew G. Knepley PetscFunctionReturn(0); 9316b4937a87SMatthew G. Knepley } 9317b4937a87SMatthew G. Knepley 9318bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9319bd041c0cSMatthew G. Knepley { 9320bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9321bd041c0cSMatthew G. Knepley PetscInt m, n; 9322bd041c0cSMatthew G. Knepley void *ctx; 9323bd041c0cSMatthew G. Knepley DM cdm; 9324bd041c0cSMatthew G. Knepley PetscBool regular; 9325bd041c0cSMatthew G. Knepley 9326bd041c0cSMatthew G. Knepley PetscFunctionBegin; 93273e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 93283e9753d6SMatthew G. Knepley DM dmc; 93293e9753d6SMatthew G. Knepley PetscDS ds; 9330b4937a87SMatthew G. Knepley PetscWeakForm wf; 93313e9753d6SMatthew G. Knepley Vec u; 93323e9753d6SMatthew G. Knepley IS cellIS; 933306ad1575SMatthew G. Knepley PetscFormKey key; 93343e9753d6SMatthew G. Knepley PetscInt depth; 93353e9753d6SMatthew G. Knepley 93369566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 93379566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 93389566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 93399566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 93409566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 93419566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 93429566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 93439566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmc, &u)); 93449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 93459566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 93469566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 93476528b96dSMatthew G. Knepley key.label = NULL; 93486528b96dSMatthew G. Knepley key.value = 0; 93496528b96dSMatthew G. Knepley key.field = 0; 935006ad1575SMatthew G. Knepley key.part = 0; 93519566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 93529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 93539566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmc, &u)); 93549566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 93553e9753d6SMatthew G. Knepley } else { 93569566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 93579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 93589566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 93599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9360bd041c0cSMatthew G. Knepley 93619566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass)); 93629566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 93639566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 93649566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9365bd041c0cSMatthew G. Knepley 93669566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 93679566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 93689566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 93699566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 93703e9753d6SMatthew G. Knepley } 93719566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 9372bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 9373bd041c0cSMatthew G. Knepley } 9374bd041c0cSMatthew G. Knepley 93750aef6b92SMatthew G. Knepley /*@ 93760aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93770aef6b92SMatthew G. Knepley 93780aef6b92SMatthew G. Knepley Input Parameter: 93790aef6b92SMatthew G. Knepley . dm - The DMPlex object 93800aef6b92SMatthew G. Knepley 93810aef6b92SMatthew G. Knepley Output Parameter: 93820aef6b92SMatthew G. Knepley . regular - The flag 93830aef6b92SMatthew G. Knepley 93840aef6b92SMatthew G. Knepley Level: intermediate 93850aef6b92SMatthew G. Knepley 9386db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()` 93870aef6b92SMatthew G. Knepley @*/ 93880aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 93890aef6b92SMatthew G. Knepley { 93900aef6b92SMatthew G. Knepley PetscFunctionBegin; 93910aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9392dadcf809SJacob Faibussowitsch PetscValidBoolPointer(regular, 2); 93930aef6b92SMatthew G. Knepley *regular = ((DM_Plex *) dm->data)->regularRefinement; 93940aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93950aef6b92SMatthew G. Knepley } 93960aef6b92SMatthew G. Knepley 93970aef6b92SMatthew G. Knepley /*@ 93980aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93990aef6b92SMatthew G. Knepley 94000aef6b92SMatthew G. Knepley Input Parameters: 94010aef6b92SMatthew G. Knepley + dm - The DMPlex object 94020aef6b92SMatthew G. Knepley - regular - The flag 94030aef6b92SMatthew G. Knepley 94040aef6b92SMatthew G. Knepley Level: intermediate 94050aef6b92SMatthew G. Knepley 9406db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()` 94070aef6b92SMatthew G. Knepley @*/ 94080aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 94090aef6b92SMatthew G. Knepley { 94100aef6b92SMatthew G. Knepley PetscFunctionBegin; 94110aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94120aef6b92SMatthew G. Knepley ((DM_Plex *) dm->data)->regularRefinement = regular; 94130aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 94140aef6b92SMatthew G. Knepley } 94150aef6b92SMatthew G. Knepley 9416f7c74593SToby Isaac /* anchors */ 9417a68b90caSToby Isaac /*@ 9418f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9419ebdb1bfaSJed Brown call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9420a68b90caSToby Isaac 9421e228b242SToby Isaac not collective 9422a68b90caSToby Isaac 9423f899ff85SJose E. Roman Input Parameter: 9424a68b90caSToby Isaac . dm - The DMPlex object 9425a68b90caSToby Isaac 9426a68b90caSToby Isaac Output Parameters: 9427a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9428a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9429a68b90caSToby Isaac 9430a68b90caSToby Isaac Level: intermediate 9431a68b90caSToby Isaac 9432db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9433a68b90caSToby Isaac @*/ 9434a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9435a68b90caSToby Isaac { 9436a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9437a68b90caSToby Isaac 9438a68b90caSToby Isaac PetscFunctionBegin; 9439a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94409566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 9441a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 9442a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 9443a68b90caSToby Isaac PetscFunctionReturn(0); 9444a68b90caSToby Isaac } 9445a68b90caSToby Isaac 9446a68b90caSToby Isaac /*@ 9447f7c74593SToby Isaac DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9448f7c74593SToby Isaac when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9449a68b90caSToby Isaac point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9450a68b90caSToby Isaac 9451a17985deSToby Isaac After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9452ebdb1bfaSJed Brown DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9453a68b90caSToby Isaac 9454e228b242SToby Isaac collective on dm 9455a68b90caSToby Isaac 9456a68b90caSToby Isaac Input Parameters: 9457a68b90caSToby Isaac + dm - The DMPlex object 9458e228b242SToby 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). 9459e228b242SToby Isaac - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9460a68b90caSToby Isaac 9461a68b90caSToby Isaac The reference counts of anchorSection and anchorIS are incremented. 9462a68b90caSToby Isaac 9463a68b90caSToby Isaac Level: intermediate 9464a68b90caSToby Isaac 9465db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9466a68b90caSToby Isaac @*/ 9467a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9468a68b90caSToby Isaac { 9469a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9470e228b242SToby Isaac PetscMPIInt result; 9471a68b90caSToby Isaac 9472a68b90caSToby Isaac PetscFunctionBegin; 9473a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9474e228b242SToby Isaac if (anchorSection) { 9475e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 94769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result)); 94771dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9478e228b242SToby Isaac } 9479e228b242SToby Isaac if (anchorIS) { 9480e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 94819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result)); 94821dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9483e228b242SToby Isaac } 9484a68b90caSToby Isaac 94859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 94869566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 9487a68b90caSToby Isaac plex->anchorSection = anchorSection; 9488a68b90caSToby Isaac 94899566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 94909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 9491a68b90caSToby Isaac plex->anchorIS = anchorIS; 9492a68b90caSToby Isaac 9493cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9494a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 9495a68b90caSToby Isaac const PetscInt *anchors; 9496a68b90caSToby Isaac 94979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 94989566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS,&size)); 94999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS,&anchors)); 9500a68b90caSToby Isaac for (a = 0; a < size; a++) { 9501a68b90caSToby Isaac PetscInt p; 9502a68b90caSToby Isaac 9503a68b90caSToby Isaac p = anchors[a]; 9504a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 9505a68b90caSToby Isaac PetscInt dof; 9506a68b90caSToby Isaac 95079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection,p,&dof)); 9508a68b90caSToby Isaac if (dof) { 9509a68b90caSToby Isaac 95109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS,&anchors)); 951163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %" PetscInt_FMT " cannot be constrained and an anchor",p); 9512a68b90caSToby Isaac } 9513a68b90caSToby Isaac } 9514a68b90caSToby Isaac } 95159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS,&anchors)); 9516a68b90caSToby Isaac } 9517f7c74593SToby Isaac /* reset the generic constraints */ 95189566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,NULL,NULL,NULL)); 9519a68b90caSToby Isaac PetscFunctionReturn(0); 9520a68b90caSToby Isaac } 9521a68b90caSToby Isaac 9522f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9523a68b90caSToby Isaac { 9524f7c74593SToby Isaac PetscSection anchorSection; 95256995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9526a68b90caSToby Isaac 9527a68b90caSToby Isaac PetscFunctionBegin; 9528a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95299566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL)); 95309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,cSec)); 95319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numFields)); 95326995de1eSToby Isaac if (numFields) { 9533719ab38cSToby Isaac PetscInt f; 95349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec,numFields)); 9535719ab38cSToby Isaac 9536719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 9537719ab38cSToby Isaac PetscInt numComp; 9538719ab38cSToby Isaac 95399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section,f,&numComp)); 95409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec,f,numComp)); 9541719ab38cSToby Isaac } 95426995de1eSToby Isaac } 95439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 95449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&sStart,&sEnd)); 95456995de1eSToby Isaac pStart = PetscMax(pStart,sStart); 95466995de1eSToby Isaac pEnd = PetscMin(pEnd,sEnd); 95476995de1eSToby Isaac pEnd = PetscMax(pStart,pEnd); 95489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec,pStart,pEnd)); 9549a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 95509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection,p,&dof)); 9551a68b90caSToby Isaac if (dof) { 95529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,p,&dof)); 95539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec,p,dof)); 9554a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 95559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,p,f,&dof)); 95569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec,p,f,dof)); 9557a68b90caSToby Isaac } 9558a68b90caSToby Isaac } 9559a68b90caSToby Isaac } 95609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 95619566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *cSec, "Constraint Section")); 9562a68b90caSToby Isaac PetscFunctionReturn(0); 9563a68b90caSToby Isaac } 9564a68b90caSToby Isaac 9565f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9566a68b90caSToby Isaac { 9567f7c74593SToby Isaac PetscSection aSec; 9568ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 95690ac89760SToby Isaac const PetscInt *anchors; 95700ac89760SToby Isaac PetscInt numFields, f; 957166ad2231SToby Isaac IS aIS; 9572e19f7ee6SMark Adams MatType mtype; 9573e19f7ee6SMark Adams PetscBool iscuda,iskokkos; 95740ac89760SToby Isaac 95750ac89760SToby Isaac PetscFunctionBegin; 95760ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 95789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 95799566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,cMat)); 95809566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat,m,n,m,n)); 95819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda)); 95829566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda)); 95839566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos)); 95849566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos)); 9585e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 9586e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9587e19f7ee6SMark Adams else mtype = MATSEQAIJ; 95889566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat,mtype)); 95899566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 95909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 95916995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 95929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec,&pStart,&pEnd)); 95939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&sStart,&sEnd)); 95949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&i)); 95950ac89760SToby Isaac i[0] = 0; 95969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numFields)); 95970ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 9598f19733c5SToby Isaac PetscInt rDof, rOff, r; 9599f19733c5SToby Isaac 96009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 9601f19733c5SToby Isaac if (!rDof) continue; 96029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96030ac89760SToby Isaac if (numFields) { 96040ac89760SToby Isaac for (f = 0; f < numFields; f++) { 96050ac89760SToby Isaac annz = 0; 9606f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 9607f19733c5SToby Isaac a = anchors[rOff + r]; 9608ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof)); 96100ac89760SToby Isaac annz += aDof; 96110ac89760SToby Isaac } 96129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof)); 96139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&off)); 96140ac89760SToby Isaac for (q = 0; q < dof; q++) { 96150ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 96160ac89760SToby Isaac } 96170ac89760SToby Isaac } 96182f7452b8SBarry Smith } else { 96190ac89760SToby Isaac annz = 0; 96209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96210ac89760SToby Isaac for (q = 0; q < dof; q++) { 9622ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 9623ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 96250ac89760SToby Isaac annz += aDof; 96260ac89760SToby Isaac } 96279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec,p,&off)); 96290ac89760SToby Isaac for (q = 0; q < dof; q++) { 96300ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 96310ac89760SToby Isaac } 96320ac89760SToby Isaac } 96330ac89760SToby Isaac } 96340ac89760SToby Isaac nnz = i[m]; 96359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&j)); 96360ac89760SToby Isaac offset = 0; 96370ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 96380ac89760SToby Isaac if (numFields) { 96390ac89760SToby Isaac for (f = 0; f < numFields; f++) { 96409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof)); 96410ac89760SToby Isaac for (q = 0; q < dof; q++) { 96420ac89760SToby Isaac PetscInt rDof, rOff, r; 96439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 96449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96450ac89760SToby Isaac for (r = 0; r < rDof; r++) { 96460ac89760SToby Isaac PetscInt s; 96470ac89760SToby Isaac 96480ac89760SToby Isaac a = anchors[rOff + r]; 9649ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof)); 96519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section,a,f,&aOff)); 96520ac89760SToby Isaac for (s = 0; s < aDof; s++) { 96530ac89760SToby Isaac j[offset++] = aOff + s; 96540ac89760SToby Isaac } 96550ac89760SToby Isaac } 96560ac89760SToby Isaac } 96570ac89760SToby Isaac } 96582f7452b8SBarry Smith } else { 96599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96600ac89760SToby Isaac for (q = 0; q < dof; q++) { 96610ac89760SToby Isaac PetscInt rDof, rOff, r; 96629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 96639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96640ac89760SToby Isaac for (r = 0; r < rDof; r++) { 96650ac89760SToby Isaac PetscInt s; 96660ac89760SToby Isaac 96670ac89760SToby Isaac a = anchors[rOff + r]; 9668ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 96709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,a,&aOff)); 96710ac89760SToby Isaac for (s = 0; s < aDof; s++) { 96720ac89760SToby Isaac j[offset++] = aOff + s; 96730ac89760SToby Isaac } 96740ac89760SToby Isaac } 96750ac89760SToby Isaac } 96760ac89760SToby Isaac } 96770ac89760SToby Isaac } 96789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL)); 96799566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 96809566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 96819566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 96820ac89760SToby Isaac PetscFunctionReturn(0); 96830ac89760SToby Isaac } 96840ac89760SToby Isaac 968566ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 968666ad2231SToby Isaac { 9687f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9688f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 968966ad2231SToby Isaac Mat cMat; 969066ad2231SToby Isaac 969166ad2231SToby Isaac PetscFunctionBegin; 969266ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 96939566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL)); 969466ad2231SToby Isaac if (anchorSection) { 969544a7f3ddSMatthew G. Knepley PetscInt Nf; 9696e228b242SToby Isaac 96979566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm,§ion)); 96989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec)); 96999566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat)); 97009566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm,&Nf)); 97019566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm,section,cSec,cMat)); 97029566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,cSec,cMat,NULL)); 97039566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 97049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 970566ad2231SToby Isaac } 970666ad2231SToby Isaac PetscFunctionReturn(0); 970766ad2231SToby Isaac } 9708a93c429eSMatthew G. Knepley 9709a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9710a93c429eSMatthew G. Knepley { 9711a93c429eSMatthew G. Knepley IS subis; 9712a93c429eSMatthew G. Knepley PetscSection section, subsection; 9713a93c429eSMatthew G. Knepley 9714a93c429eSMatthew G. Knepley PetscFunctionBegin; 97159566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 971628b400f6SJacob Faibussowitsch PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 971728b400f6SJacob Faibussowitsch PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9718a93c429eSMatthew G. Knepley /* Create subdomain */ 97199566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 9720a93c429eSMatthew G. Knepley /* Create submodel */ 97219566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 97229566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 97239566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 97249566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 97259566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 9726a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 9727a93c429eSMatthew G. Knepley if (is) { 9728a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 9729a93c429eSMatthew G. Knepley IS spIS; 9730a93c429eSMatthew G. Knepley const PetscInt *spmap; 9731a93c429eSMatthew G. Knepley PetscInt *subIndices; 9732a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9733a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9734a93c429eSMatthew G. Knepley 97359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 97369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 97379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 97389566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 97399566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 97409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 9741a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9742a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 9743a93c429eSMatthew G. Knepley 97449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 9745a93c429eSMatthew G. Knepley if (gdof > 0) { 9746a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9747a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 9748a93c429eSMatthew G. Knepley 97499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 97509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 9751a93c429eSMatthew G. Knepley pSubSize += fdof-fcdof; 9752a93c429eSMatthew G. Knepley } 9753a93c429eSMatthew G. Knepley subSize += pSubSize; 9754a93c429eSMatthew G. Knepley if (pSubSize) { 9755a93c429eSMatthew G. Knepley if (bs < 0) { 9756a93c429eSMatthew G. Knepley bs = pSubSize; 9757a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 9758a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 9759a93c429eSMatthew G. Knepley bs = 1; 9760a93c429eSMatthew G. Knepley } 9761a93c429eSMatthew G. Knepley } 9762a93c429eSMatthew G. Knepley } 9763a93c429eSMatthew G. Knepley } 9764a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 9765a93c429eSMatthew G. Knepley bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 97669566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 9767a93c429eSMatthew G. Knepley if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9768a93c429eSMatthew G. Knepley else {bs = bsMinMax[0];} 97699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 9770a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9771a93c429eSMatthew G. Knepley PetscInt gdof, goff; 9772a93c429eSMatthew G. Knepley 97739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 9774a93c429eSMatthew G. Knepley if (gdof > 0) { 9775a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 9776a93c429eSMatthew G. Knepley 97779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 9778a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9779a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 9780a93c429eSMatthew G. Knepley 9781a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 9782a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 97839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 97849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 9785a93c429eSMatthew G. Knepley poff += fdof-fcdof; 9786a93c429eSMatthew G. Knepley } 97879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 97889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 9789a93c429eSMatthew G. Knepley for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9790a93c429eSMatthew G. Knepley subIndices[subOff] = goff+poff+fc; 9791a93c429eSMatthew G. Knepley } 9792a93c429eSMatthew G. Knepley } 9793a93c429eSMatthew G. Knepley } 9794a93c429eSMatthew G. Knepley } 97959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 97969566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 9797a93c429eSMatthew G. Knepley if (bs > 1) { 9798a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 9799a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 9800a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 9801a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 9802a93c429eSMatthew G. Knepley if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9803a93c429eSMatthew G. Knepley } 9804a93c429eSMatthew G. Knepley } 98059566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 9806a93c429eSMatthew G. Knepley } 9807a93c429eSMatthew G. Knepley /* Attach nullspace */ 9808a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9809a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9810a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 9811a93c429eSMatthew G. Knepley } 9812a93c429eSMatthew G. Knepley if (f < Nf) { 9813a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 98149566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 98156823f3c5SBlaise Bourdin 98169566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace)); 98179566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 9818a93c429eSMatthew G. Knepley } 9819a93c429eSMatthew G. Knepley } 9820a93c429eSMatthew G. Knepley PetscFunctionReturn(0); 9821a93c429eSMatthew G. Knepley } 9822c0f0dcc3SMatthew G. Knepley 9823c0f0dcc3SMatthew G. Knepley /*@ 9824c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 9825c0f0dcc3SMatthew G. Knepley 9826c0f0dcc3SMatthew G. Knepley Input Parameter: 9827c0f0dcc3SMatthew G. Knepley - dm - The DM 9828c0f0dcc3SMatthew G. Knepley 9829c0f0dcc3SMatthew G. Knepley Level: developer 9830c0f0dcc3SMatthew G. Knepley 9831c0f0dcc3SMatthew G. Knepley Options Database Keys: 9832c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor 9833c0f0dcc3SMatthew G. Knepley 9834db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()` 9835c0f0dcc3SMatthew G. Knepley @*/ 9836c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9837c0f0dcc3SMatthew G. Knepley { 9838e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG) 9839c0f0dcc3SMatthew G. Knepley PetscStageLog stageLog; 9840c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 9841c0f0dcc3SMatthew G. Knepley PetscLogStage stage; 9842c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 9843c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 9844c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 9845c0f0dcc3SMatthew G. Knepley const char *name; 9846e5ed2c37SJose E. Roman #endif 9847c0f0dcc3SMatthew G. Knepley 9848c0f0dcc3SMatthew G. Knepley PetscFunctionBegin; 9849c0f0dcc3SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9850c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG) 98519566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 98529566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 98539566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 98549566063dSJacob Faibussowitsch PetscCall(PetscLogGetStageLog(&stageLog)); 98559566063dSJacob Faibussowitsch PetscCall(PetscStageLogGetCurrent(stageLog, &stage)); 98569566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 98579566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 9858c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart)*Nf*eventInfo.count; 9859c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops/eventInfo.time; 9860c0f0dcc3SMatthew G. Knepley cellRate = N/eventInfo.time; 986163a3b9bcSJacob 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))); 9862c0f0dcc3SMatthew G. Knepley #else 9863c0f0dcc3SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9864c0f0dcc3SMatthew G. Knepley #endif 9865c0f0dcc3SMatthew G. Knepley PetscFunctionReturn(0); 9866c0f0dcc3SMatthew G. Knepley } 9867