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)); 6212c40f234SMatthew G. Knepley } else { 6229566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(v, viewer)); 6232c40f234SMatthew G. Knepley } 6242c40f234SMatthew G. Knepley PetscFunctionReturn(0); 6252c40f234SMatthew G. Knepley } 6262c40f234SMatthew G. Knepley 6272c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 6282c40f234SMatthew G. Knepley { 6292c40f234SMatthew G. Knepley DM dm; 6306823f3c5SBlaise Bourdin PetscBool ishdf5,isexodusii; 6312c40f234SMatthew G. Knepley 6322c40f234SMatthew G. Knepley PetscFunctionBegin; 6339566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63428b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 6369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6372c40f234SMatthew G. Knepley if (ishdf5) { 638878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6399566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 640b136c2c9SMatthew G. Knepley #else 641b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 642878b459fSMatthew G. Knepley #endif 6436823f3c5SBlaise Bourdin } else if (isexodusii) { 6446823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6459566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 6466823f3c5SBlaise Bourdin #else 6476823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6486823f3c5SBlaise Bourdin #endif 6492c40f234SMatthew G. Knepley } else { 6509566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(v, viewer)); 651552f7358SJed Brown } 652552f7358SJed Brown PetscFunctionReturn(0); 653552f7358SJed Brown } 654552f7358SJed Brown 655d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 656d930f514SMatthew G. Knepley { 657d930f514SMatthew G. Knepley DM dm; 658d930f514SMatthew G. Knepley PetscViewerFormat format; 659d930f514SMatthew G. Knepley PetscBool ishdf5; 660d930f514SMatthew G. Knepley 661d930f514SMatthew G. Knepley PetscFunctionBegin; 6629566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 66328b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6649566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 666d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 667a8ad634aSStefano Zampini if (dm->useNatural) { 668d930f514SMatthew G. Knepley if (dm->sfNatural) { 669d930f514SMatthew G. Knepley if (ishdf5) { 670d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 671d930f514SMatthew G. Knepley Vec v; 672d930f514SMatthew G. Knepley const char *vecname; 673d930f514SMatthew G. Knepley 6749566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &v)); 6759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname)); 6769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) v, vecname)); 6779566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 6789566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 6799566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 6809566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dm, &v)); 681d930f514SMatthew G. Knepley #else 682d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 683d930f514SMatthew G. Knepley #endif 684d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 685d930f514SMatthew G. Knepley } 686a8ad634aSStefano Zampini } else { 6879566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(originalv, viewer)); 688a8ad634aSStefano Zampini } 689d930f514SMatthew G. Knepley } 690d930f514SMatthew G. Knepley PetscFunctionReturn(0); 691d930f514SMatthew G. Knepley } 692d930f514SMatthew G. Knepley 6937cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 694731e8ddeSMatthew G. Knepley { 695731e8ddeSMatthew G. Knepley PetscSection coordSection; 696731e8ddeSMatthew G. Knepley Vec coordinates; 697ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 698731e8ddeSMatthew G. Knepley const char *name[4]; 699731e8ddeSMatthew G. Knepley const PetscScalar *a; 700731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 701731e8ddeSMatthew G. Knepley 702731e8ddeSMatthew G. Knepley PetscFunctionBegin; 7039566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 7049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 7059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 7079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 7089566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 7099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 7109566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 711731e8ddeSMatthew G. Knepley name[0] = "vertex"; 712731e8ddeSMatthew G. Knepley name[1] = "edge"; 713731e8ddeSMatthew G. Knepley name[dim-1] = "face"; 714731e8ddeSMatthew G. Knepley name[dim] = "cell"; 715731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 716731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 717ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 718731e8ddeSMatthew G. Knepley 7199566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 72063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 7219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 723731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 724731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 725731e8ddeSMatthew G. Knepley 726731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 7279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 728731e8ddeSMatthew G. Knepley if (!dof) continue; 7299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 7309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 73163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 732731e8ddeSMatthew G. Knepley for (p = 0; p < dof/dim; ++p) { 7339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 734731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 7359566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 7369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]))); 737731e8ddeSMatthew G. Knepley } 7389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 739731e8ddeSMatthew G. Knepley } 7409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 741731e8ddeSMatthew G. Knepley } 7429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 744731e8ddeSMatthew G. Knepley } 7459566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 746731e8ddeSMatthew G. Knepley PetscFunctionReturn(0); 747731e8ddeSMatthew G. Knepley } 748731e8ddeSMatthew G. Knepley 74919ad8254SMatthew G. Knepley typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem; 75019ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 75119ad8254SMatthew G. Knepley 75219ad8254SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 75319ad8254SMatthew G. Knepley { 75419ad8254SMatthew G. Knepley PetscInt i; 75519ad8254SMatthew G. Knepley 75619ad8254SMatthew G. Knepley PetscFunctionBegin; 75719ad8254SMatthew G. Knepley if (dim > 3) { 7589566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]))); 75919ad8254SMatthew G. Knepley } else { 760*bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 76119ad8254SMatthew G. Knepley 76219ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 76319ad8254SMatthew G. Knepley switch (cs) { 76419ad8254SMatthew G. Knepley case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break; 76519ad8254SMatthew G. Knepley case CS_POLAR: 76663a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 76719ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 76819ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 76919ad8254SMatthew G. Knepley break; 77019ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 77163a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 77219ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 77319ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 77419ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 77519ad8254SMatthew G. Knepley break; 77619ad8254SMatthew G. Knepley case CS_SPHERICAL: 77763a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 77819ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 77919ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 78019ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 78119ad8254SMatthew G. Knepley break; 78219ad8254SMatthew G. Knepley } 7839566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i])); 78419ad8254SMatthew G. Knepley } 78519ad8254SMatthew G. Knepley PetscFunctionReturn(0); 78619ad8254SMatthew G. Knepley } 78719ad8254SMatthew G. Knepley 7887cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 789552f7358SJed Brown { 790552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 791552f7358SJed Brown DM cdm; 792552f7358SJed Brown PetscSection coordSection; 793552f7358SJed Brown Vec coordinates; 794552f7358SJed Brown PetscViewerFormat format; 795552f7358SJed Brown 796552f7358SJed Brown PetscFunctionBegin; 7979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 7989566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 7999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8009566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 801552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 802552f7358SJed Brown const char *name; 803f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 8049318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 805552f7358SJed Brown PetscMPIInt rank, size; 806552f7358SJed Brown 8079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 8099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 8109566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8119566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 8129566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8139566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 81463a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 81563a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 81663a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 81763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 8189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 81963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 820552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 821552f7358SJed Brown PetscInt dof, off, s; 822552f7358SJed Brown 8239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 825552f7358SJed Brown for (s = off; s < off+dof; ++s) { 82663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 827552f7358SJed Brown } 828552f7358SJed Brown } 8299566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 83063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 83163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 832552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 833552f7358SJed Brown PetscInt dof, off, c; 834552f7358SJed Brown 8359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 8369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 837552f7358SJed Brown for (c = off; c < off+dof; ++c) { 83863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c])); 839552f7358SJed Brown } 840552f7358SJed Brown } 8419566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8433d2e540fSStefano Zampini if (coordSection && coordinates) { 84419ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 84519ad8254SMatthew G. Knepley const PetscScalar *array; 84619ad8254SMatthew G. Knepley PetscInt Nf, Nc, pStart, pEnd, p; 84719ad8254SMatthew G. Knepley PetscMPIInt rank; 84819ad8254SMatthew G. Knepley const char *name; 84919ad8254SMatthew G. Knepley 8509566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL)); 8519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 8529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 85363a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 8549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 8559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 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)); 8629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 8639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 86419ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 86519ad8254SMatthew G. Knepley PetscInt dof, off; 86619ad8254SMatthew G. Knepley 8679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 8689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 86963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 8709566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 8719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 87219ad8254SMatthew G. Knepley } 8739566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 8749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 8759566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 8763d2e540fSStefano Zampini } 8779566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 8789566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 8799318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 8809318fe57SMatthew G. Knepley DMLabel label; 8819318fe57SMatthew G. Knepley PetscBool isdepth; 8829318fe57SMatthew G. Knepley const char *name; 8839318fe57SMatthew G. Knepley 8849566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 8859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 8869318fe57SMatthew G. Knepley if (isdepth) continue; 8879566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 8889566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 8899318fe57SMatthew G. Knepley } 890552f7358SJed Brown if (size > 1) { 891552f7358SJed Brown PetscSF sf; 892552f7358SJed Brown 8939566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 8949566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 895552f7358SJed Brown } 8969566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 897552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 8980588280cSMatthew G. Knepley const char *name, *color; 8990588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 9000588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 901fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 902552f7358SJed Brown PetscReal scale = 2.0; 90378081901SStefano Zampini PetscReal tikzscale = 1.0; 904b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 9050588280cSMatthew G. Knepley double tcoords[3]; 906552f7358SJed Brown PetscScalar *coords; 907b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 908552f7358SJed Brown PetscMPIInt rank, size; 9090588280cSMatthew G. Knepley char **names, **colors, **lcolors; 910b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 911fe1cc32dSStefano Zampini PetscBT wp = NULL; 912fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 913552f7358SJed Brown 9149566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9159566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9169566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 9170588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 9180588280cSMatthew G. Knepley numColors = 10; 9190588280cSMatthew G. Knepley numLColors = 10; 9209566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 9219566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 9229566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 9239566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 924b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 925b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 926b7f6ffafSMatthew G. Knepley n = 4; 9279566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 9281dca8a05SBarry 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); 9299566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 9301dca8a05SBarry 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); 9319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 9320588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 9339566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 9340588280cSMatthew G. Knepley if (!useColors) { 9350588280cSMatthew G. Knepley numColors = 3; 9369566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 9370588280cSMatthew G. Knepley } 9389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 9390588280cSMatthew G. Knepley if (!useColors) { 9400588280cSMatthew G. Knepley numLColors = 4; 9419566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 9420588280cSMatthew G. Knepley } 9439566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 944b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 9459566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 9461dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 947202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 9489566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 949fe1cc32dSStefano Zampini 950fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 9519566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 955fe1cc32dSStefano Zampini if (lflg) { 956fe1cc32dSStefano Zampini DMLabel lbl; 957fe1cc32dSStefano Zampini 9589566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 959fe1cc32dSStefano Zampini if (lbl) { 960fe1cc32dSStefano Zampini PetscInt val, defval; 961fe1cc32dSStefano Zampini 9629566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 9639566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd-pStart, &wp)); 964fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 965fe1cc32dSStefano Zampini PetscInt *closure = NULL; 966fe1cc32dSStefano Zampini PetscInt closureSize; 967fe1cc32dSStefano Zampini 9689566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 969fe1cc32dSStefano Zampini if (val == defval) continue; 970fe1cc32dSStefano Zampini 9719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 972fe1cc32dSStefano Zampini for (p = 0; p < closureSize*2; p += 2) { 9739566063dSJacob Faibussowitsch PetscCall(PetscBTSet(wp, closure[p] - pStart)); 974fe1cc32dSStefano Zampini } 9759566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 976fe1cc32dSStefano Zampini } 977fe1cc32dSStefano Zampini } 978fe1cc32dSStefano Zampini } 979fe1cc32dSStefano Zampini 9809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 9839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 9840588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 985552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 986552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 987552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 9885f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 9890588280cSMatthew G. Knepley if (size > 1) { 9909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 991770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 99263a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size-1) ? ", and " : ", ")); 99363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p%numColors], p)); 994770b213bSMatthew G Knepley } 9959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 9960588280cSMatthew G. Knepley } 997b7f6ffafSMatthew G. Knepley if (drawHasse) { 998b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 999b7f6ffafSMatthew G. Knepley 100063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 100163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd-1)); 100263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd-vStart)); 10039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.)); 100463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 100563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd-1)); 10069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.)); 100763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd-eStart)); 100863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 100963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd-1)); 101063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd-cStart)); 10119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.)); 1012b7f6ffafSMatthew G. Knepley } 10139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale)); 1014fe1cc32dSStefano Zampini 1015552f7358SJed Brown /* Plot vertices */ 10169566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1018552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1019552f7358SJed Brown PetscInt off, dof, d; 10200588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1021552f7358SJed Brown 1022fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,v - pStart)) continue; 10239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 10249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 10259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 102663a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3",v,dof); 10270588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10280588280cSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1029c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 10300588280cSMatthew G. Knepley } 10310588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 10320588280cSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1033552f7358SJed Brown for (d = 0; d < dof; ++d) { 10349566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d])); 1036552f7358SJed Brown } 1037b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0%numColors]; 1038b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 10390588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10400588280cSMatthew G. Knepley PetscInt val; 10419566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 10420588280cSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 10430588280cSMatthew G. Knepley } 1044b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 104563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1046b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 104763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 1048b7f6ffafSMatthew G. Knepley } else { 104963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 10500588280cSMatthew G. Knepley } 1051552f7358SJed Brown } 10529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 10539566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1054b7f6ffafSMatthew G. Knepley /* Plot edges */ 1055b7f6ffafSMatthew G. Knepley if (plotEdges) { 10569566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 10579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1058b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1059b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1060b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1061b7f6ffafSMatthew G. Knepley 1062b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp,e - pStart)) continue; 10639566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 106463a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 10659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 10669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 10679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 10689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 10699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1070b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1071b7f6ffafSMatthew G. Knepley tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 1072b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1073b7f6ffafSMatthew G. Knepley } 1074b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1075b7f6ffafSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1076b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10779566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1079b7f6ffafSMatthew G. Knepley } 1080b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1%numColors]; 1081b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 1082b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1083b7f6ffafSMatthew G. Knepley PetscInt val; 10849566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 1085b7f6ffafSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 1086b7f6ffafSMatthew G. Knepley } 108763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1088b7f6ffafSMatthew G. Knepley } 10899566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 10909566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1092b7f6ffafSMatthew G. Knepley } 1093846a3e8bSMatthew G. Knepley /* Plot cells */ 1094b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1095846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1096846a3e8bSMatthew G. Knepley const PetscInt *cone; 1097846a3e8bSMatthew G. Knepley 1098fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1099846a3e8bSMatthew G. Knepley color = colors[rank%numColors]; 1100846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1101846a3e8bSMatthew G. Knepley PetscInt val; 11029566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 1103846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 1104846a3e8bSMatthew G. Knepley } 11059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 110663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1107846a3e8bSMatthew G. Knepley } 1108846a3e8bSMatthew G. Knepley } else { 1109b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1110846a3e8bSMatthew G. Knepley 1111b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1112b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1113fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 11149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1115b7f6ffafSMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1116b7f6ffafSMatthew G. Knepley ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1117b7f6ffafSMatthew G. Knepley ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1118b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1119b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1120b7f6ffafSMatthew G. Knepley 11219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 11229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1123b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1124b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1125b7f6ffafSMatthew G. Knepley 11269566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 112763a3b9bcSJacob 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)); 1128b7f6ffafSMatthew G. Knepley } 1129b7f6ffafSMatthew G. Knepley } else { 1130b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1131b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1132b7f6ffafSMatthew G. Knepley 11339566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1134846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 1135846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1136846a3e8bSMatthew G. Knepley 1137b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1138846a3e8bSMatthew G. Knepley } 11399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors])); 1140b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1141b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v%Nv]; 1142b7f6ffafSMatthew G. Knepley 1143b7f6ffafSMatthew G. Knepley if (v > 0) { 1144b7f6ffafSMatthew G. Knepley if (plotEdges) { 1145b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1146b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1147b7f6ffafSMatthew G. Knepley 1148b7f6ffafSMatthew G. Knepley endpoints[0] = closure[v-1]; endpoints[1] = vertex; 11499566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 115063a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 115163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 11529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 1153b7f6ffafSMatthew G. Knepley } else { 11549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1155b7f6ffafSMatthew G. Knepley } 1156b7f6ffafSMatthew G. Knepley } 115763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1158b7f6ffafSMatthew G. Knepley } 11599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 11609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1161846a3e8bSMatthew G. Knepley } 1162846a3e8bSMatthew G. Knepley } 1163b7f6ffafSMatthew G. Knepley } 11649566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1165846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1166846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1167846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1168846a3e8bSMatthew G. Knepley PetscInt *closure = NULL; 1169846a3e8bSMatthew G. Knepley PetscInt closureSize, dof, d, n = 0; 1170846a3e8bSMatthew G. Knepley 1171fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,c - pStart)) continue; 11729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 11739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1174846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 1175846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1176846a3e8bSMatthew G. Knepley PetscInt off; 1177846a3e8bSMatthew G. Knepley 1178846a3e8bSMatthew G. Knepley if ((point < vStart) || (point >= vEnd)) continue; 11799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 11809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 1181846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1182846a3e8bSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1183846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1184846a3e8bSMatthew G. Knepley } 1185846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1186846a3e8bSMatthew G. Knepley if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1187846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1188846a3e8bSMatthew G. Knepley ++n; 1189846a3e8bSMatthew G. Knepley } 1190846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 11919566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1192846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11939566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d])); 1195846a3e8bSMatthew G. Knepley } 1196b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth%numColors]; 1197b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 1198846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1199846a3e8bSMatthew G. Knepley PetscInt val; 12009566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 1201846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1202846a3e8bSMatthew G. Knepley } 1203b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 120463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1205b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 120663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 1207b7f6ffafSMatthew G. Knepley } else { 120863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1209846a3e8bSMatthew G. Knepley } 1210846a3e8bSMatthew G. Knepley } 12119566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 1212b7f6ffafSMatthew G. Knepley if (drawHasse) { 1213b7f6ffafSMatthew G. Knepley color = colors[depth%numColors]; 12149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 12159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 12169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 12189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1219552f7358SJed Brown 1220b7f6ffafSMatthew G. Knepley color = colors[1%numColors]; 12219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 12229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 12239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 12259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1226b7f6ffafSMatthew G. Knepley 1227b7f6ffafSMatthew G. Knepley color = colors[0%numColors]; 12289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 12299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 12309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 12319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 12329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1233b7f6ffafSMatthew G. Knepley 1234b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1235b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1236b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1237b7f6ffafSMatthew G. Knepley 12389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 12399566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1240b7f6ffafSMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 124163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank)); 1242552f7358SJed Brown } 12430588280cSMatthew G. Knepley } 12440588280cSMatthew G. Knepley } 12459566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 12479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 124863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 12499566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 12509566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 12519566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 12529566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 12539566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 12540f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 12550f7d6e4aSStefano Zampini Vec cown,acown; 12560f7d6e4aSStefano Zampini VecScatter sct; 12570f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 12580f7d6e4aSStefano Zampini IS gid,acis; 12590f7d6e4aSStefano Zampini MPI_Comm comm,ncomm = MPI_COMM_NULL; 12600f7d6e4aSStefano Zampini MPI_Group ggroup,ngroup; 12610f7d6e4aSStefano Zampini PetscScalar *array,nid; 12620f7d6e4aSStefano Zampini const PetscInt *idxs; 12630f7d6e4aSStefano Zampini PetscInt *idxs2,*start,*adjacency,*work; 12640f7d6e4aSStefano Zampini PetscInt64 lm[3],gm[3]; 12650f7d6e4aSStefano Zampini PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 12660f7d6e4aSStefano Zampini PetscMPIInt d1,d2,rank; 12670f7d6e4aSStefano Zampini 12689566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm,&comm)); 12699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 1270b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 12719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm)); 12720f7d6e4aSStefano Zampini #endif 12730f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 12749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm,&ggroup)); 12759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm,&ngroup)); 12760f7d6e4aSStefano Zampini d1 = 0; 12779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2)); 12780f7d6e4aSStefano Zampini nid = d2; 12799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 12809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 12819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 12820f7d6e4aSStefano Zampini } else nid = 0.0; 12830f7d6e4aSStefano Zampini 12840f7d6e4aSStefano Zampini /* Get connectivity */ 12859566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm,&cellHeight)); 12869566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid)); 12870f7d6e4aSStefano Zampini 12880f7d6e4aSStefano Zampini /* filter overlapped local cells */ 12899566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd)); 12909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid,&idxs)); 12919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid,&cum)); 12929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum,&idxs2)); 12930f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 12940f7d6e4aSStefano Zampini if (idxs[c-cStart] < 0) continue; 12950f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c-cStart]; 12960f7d6e4aSStefano Zampini } 12979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid,&idxs)); 129863a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,numVertices,cum); 12999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13009566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid)); 13010f7d6e4aSStefano Zampini 13020f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 13039566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis)); 13049566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown)); 13059566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown)); 13069566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown,&array)); 13070f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 13089566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown,&array)); 13099566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown,acis,acown,NULL,&sct)); 13109566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD)); 13119566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD)); 13129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 13139566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 13149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 13150f7d6e4aSStefano Zampini 13160f7d6e4aSStefano Zampini /* compute edgeCut */ 13170f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 13189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum,&work)); 13199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid,&g2l)); 13209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH)); 13219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 13229566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown,&array)); 13230f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 13240f7d6e4aSStefano Zampini PetscInt totl; 13250f7d6e4aSStefano Zampini 13260f7d6e4aSStefano Zampini totl = start[c+1]-start[c]; 13279566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work)); 13280f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 13290f7d6e4aSStefano Zampini if (work[i] < 0) { 13300f7d6e4aSStefano Zampini ect += 1; 13310f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 13320f7d6e4aSStefano Zampini } 13330f7d6e4aSStefano Zampini } 13340f7d6e4aSStefano Zampini } 13359566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 13369566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown,&array)); 13370f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 13380f7d6e4aSStefano Zampini lm[1] = -numVertices; 13391c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm)); 134063a3b9bcSJacob 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])); 13410f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 13420f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 13430f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 13441c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm)); 134563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,", empty %" PetscInt_FMT ")\n",(PetscInt)gm[2])); 1346b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 134763a3b9bcSJacob 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.)); 13480f7d6e4aSStefano Zampini #else 134963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Edge Cut: %" PetscInt_FMT " (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0)); 13500f7d6e4aSStefano Zampini #endif 13519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 13529566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 13539566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 13549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1355552f7358SJed Brown } else { 1356412e9a14SMatthew G. Knepley const char *name; 1357d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1358412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1359d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1360ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 13619318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1362412e9a14SMatthew G. Knepley MPI_Comm comm; 1363412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1364552f7358SJed Brown 13659566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 13669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 13679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 13689566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13699566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 13709566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 137163a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 137263a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 137363a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 13749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 13751c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 13769566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd)); 1377d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 13789566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 13799566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1380412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1381412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1382412e9a14SMatthew G. Knepley 13839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 13849566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1385412e9a14SMatthew G. Knepley ict = ct0; 13869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1387412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType) ict; 1388412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1389412e9a14SMatthew G. Knepley DMPolytopeType ct; 1390412e9a14SMatthew G. Knepley 13919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1392412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1393412e9a14SMatthew G. Knepley else ++Nc[1]; 1394412e9a14SMatthew G. Knepley } 1395ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 13969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 13979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 13989566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 139963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1400834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1401dd400576SPatrick Sanan if (rank == 0) { 140263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]+hybsizes[p])); 140363a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 140463a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1405834065abSMatthew G. Knepley } 1406cbb7f117SMark Adams } 1407ca7bf7eeSMatthew G. Knepley } else { 1408ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1409ca7bf7eeSMatthew G. Knepley 1410ca7bf7eeSMatthew G. Knepley locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1]; 14119566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 1412ca7bf7eeSMatthew G. Knepley locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1]; 14139566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1414ca7bf7eeSMatthew G. Knepley if (d == depth) { 1415ca7bf7eeSMatthew G. Knepley locMinMax[0] = gcNum; locMinMax[1] = gcNum; 14169566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1417ca7bf7eeSMatthew G. Knepley } 141863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 14199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 14209566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 14219566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1422ca7bf7eeSMatthew G. Knepley } 14239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1424552f7358SJed Brown } 14259566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 14269318fe57SMatthew G. Knepley { 14279318fe57SMatthew G. Knepley const PetscReal *maxCell; 14289318fe57SMatthew G. Knepley const PetscReal *L; 14299318fe57SMatthew G. Knepley const DMBoundaryType *bd; 14309318fe57SMatthew G. Knepley PetscBool per, localized; 14319318fe57SMatthew G. Knepley 14329566063dSJacob Faibussowitsch PetscCall(DMGetPeriodicity(dm, &per, &maxCell, &L, &bd)); 14339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 14349318fe57SMatthew G. Knepley if (per) { 14359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh (")); 14369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 14379318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 14389566063dSJacob Faibussowitsch if (bd && d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 14399566063dSJacob Faibussowitsch if (bd) PetscCall(PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]])); 14409318fe57SMatthew G. Knepley } 14419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized")); 14429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14439318fe57SMatthew G. Knepley } 14449318fe57SMatthew G. Knepley } 14459566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 14469566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1447a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1448a57dd577SMatthew G Knepley DMLabel label; 1449a57dd577SMatthew G Knepley const char *name; 1450a57dd577SMatthew G Knepley IS valueIS; 1451a57dd577SMatthew G Knepley const PetscInt *values; 1452a57dd577SMatthew G Knepley PetscInt numValues, v; 1453a57dd577SMatthew G Knepley 14549566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 14559566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 14569566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 145763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 14589566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 14599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 14609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1461a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1462a57dd577SMatthew G Knepley PetscInt size; 1463a57dd577SMatthew G Knepley 14649566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 14659566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 146663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1467a57dd577SMatthew G Knepley } 14689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 14699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 14719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1472a57dd577SMatthew G Knepley } 1473c1cad2e7SMatthew G. Knepley { 1474c1cad2e7SMatthew G. Knepley char **labelNames; 1475c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1476c1cad2e7SMatthew G. Knepley PetscBool flg; 1477c1cad2e7SMatthew G. Knepley 14789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 14799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1480c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1481c1cad2e7SMatthew G. Knepley DMLabel label; 1482c1cad2e7SMatthew G. Knepley 14839566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1484c1cad2e7SMatthew G. Knepley if (flg) { 14859566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 14869566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1487c1cad2e7SMatthew G. Knepley } 14889566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1489c1cad2e7SMatthew G. Knepley } 14909566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1491c1cad2e7SMatthew G. Knepley } 149234aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 149334aa8a36SMatthew G. Knepley if (dm->Nf) { 149434aa8a36SMatthew G. Knepley PetscInt f; 149534aa8a36SMatthew G. Knepley 149634aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 149734aa8a36SMatthew G. Knepley const char *name; 149834aa8a36SMatthew G. Knepley 14999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 15009566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 15019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15029566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 150334aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 15049566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 15059566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 150634aa8a36SMatthew G. Knepley } else { 15079566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 15089566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 150934aa8a36SMatthew G. Knepley } 15109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 151134aa8a36SMatthew G. Knepley } 151234aa8a36SMatthew G. Knepley } 15139566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 15148e7ff633SMatthew G. Knepley if (cdm) { 15159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 15169566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 15179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 15188e7ff633SMatthew G. Knepley } 1519552f7358SJed Brown } 1520552f7358SJed Brown PetscFunctionReturn(0); 1521552f7358SJed Brown } 1522552f7358SJed Brown 1523e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1524e5c487bfSMatthew G. Knepley { 1525e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1526e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1527a12d352dSMatthew G. Knepley PetscInt cdim; 1528e5c487bfSMatthew G. Knepley 1529e5c487bfSMatthew G. Knepley PetscFunctionBegin; 15309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 15319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 15329566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1533e5c487bfSMatthew G. Knepley switch (ct) { 1534a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1535a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1536a12d352dSMatthew G. Knepley switch (cdim) { 1537a12d352dSMatthew G. Knepley case 1: 1538a12d352dSMatthew G. Knepley { 1539a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1540a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1541a12d352dSMatthew G. Knepley 15429566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 15439566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK)); 15449566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK)); 1545a12d352dSMatthew G. Knepley } 1546a12d352dSMatthew G. Knepley break; 1547a12d352dSMatthew G. Knepley case 2: 1548a12d352dSMatthew G. Knepley { 1549a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1550a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1551a12d352dSMatthew G. Knepley const PetscReal l = 0.1/PetscSqrtReal(dx*dx + dy*dy); 1552a12d352dSMatthew G. Knepley 15539566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15549566063dSJacob 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)); 15559566063dSJacob 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)); 1556a12d352dSMatthew G. Knepley } 1557a12d352dSMatthew G. Knepley break; 155863a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1559a12d352dSMatthew G. Knepley } 1560a12d352dSMatthew G. Knepley break; 1561e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 15629566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1563e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1564e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15655f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15669566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15679566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15689566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1569e5c487bfSMatthew G. Knepley break; 1570e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 15719566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1572e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1573e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15745f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15759566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1576e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1577e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15785f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15799566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15809566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15819566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 15829566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1583e5c487bfSMatthew G. Knepley break; 158498921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1585e5c487bfSMatthew G. Knepley } 1586e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1587e5c487bfSMatthew G. Knepley } 1588e5c487bfSMatthew G. Knepley 1589e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1590e5c487bfSMatthew G. Knepley { 1591e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1592e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1593e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1594e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1595e5c487bfSMatthew G. Knepley 1596e5c487bfSMatthew G. Knepley PetscFunctionBegin; 15979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 15989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1599e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1600e5c487bfSMatthew G. Knepley switch (ct) { 1601e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 1602e5c487bfSMatthew G. Knepley { 1603e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1604e5c487bfSMatthew G. Knepley 1605e5c487bfSMatthew G. Knepley for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1606e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1607e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e*2+0]; 1608e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e*2+1]; 1609e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1610e5c487bfSMatthew G. Knepley refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1611e5c487bfSMatthew G. Knepley refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1612e5c487bfSMatthew G. Knepley } 16139566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords)); 1614e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 16159566063dSJacob 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)); 16169566063dSJacob 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)); 1617e5c487bfSMatthew G. Knepley } 1618e5c487bfSMatthew G. Knepley } 1619e5c487bfSMatthew G. Knepley } 1620e5c487bfSMatthew G. Knepley break; 162198921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1622e5c487bfSMatthew G. Knepley } 1623e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1624e5c487bfSMatthew G. Knepley } 1625e5c487bfSMatthew G. Knepley 16267cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1627e412dcbdSMatthew G. Knepley { 1628e412dcbdSMatthew G. Knepley PetscDraw draw; 1629e412dcbdSMatthew G. Knepley DM cdm; 1630e412dcbdSMatthew G. Knepley PetscSection coordSection; 1631e412dcbdSMatthew G. Knepley Vec coordinates; 1632e412dcbdSMatthew G. Knepley const PetscScalar *coords; 163329494db1SLisandro Dalcin PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1634e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1635e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1636e5c487bfSMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1637e412dcbdSMatthew G. Knepley 1638e412dcbdSMatthew G. Knepley PetscFunctionBegin; 16399566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 164063a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 16419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 16429566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords)); 16439566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 16449566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 16459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 16469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 16479566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1648e412dcbdSMatthew G. Knepley 16499566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 16509566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 1651e412dcbdSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 16529566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1653e412dcbdSMatthew G. Knepley 16549566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 16559566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 1656e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 16570c81f2a8SMatthew G. Knepley bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 16580c81f2a8SMatthew G. Knepley bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1659e412dcbdSMatthew G. Knepley } 16609566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 16611c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm))); 16621c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm))); 16639566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 16649566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1665e412dcbdSMatthew G. Knepley 1666cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1667cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1668ba2698f1SMatthew G. Knepley PetscInt numCoords; 1669cf3064d3SMatthew G. Knepley 16709566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords)); 1671e5c487bfSMatthew G. Knepley if (drawAffine) { 16729566063dSJacob Faibussowitsch PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 1673e5c487bfSMatthew G. Knepley } else { 16749566063dSJacob Faibussowitsch PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1675cf3064d3SMatthew G. Knepley } 16769566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 1677cf3064d3SMatthew G. Knepley } 16789566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 16799566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 16809566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 16819566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 1682e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 1683e412dcbdSMatthew G. Knepley } 1684e412dcbdSMatthew G. Knepley 16851e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 16861e50132fSMatthew G. Knepley #include <exodusII.h> 16876823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 16881e50132fSMatthew G. Knepley #endif 16891e50132fSMatthew G. Knepley 1690552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1691552f7358SJed Brown { 16921e50132fSMatthew G. Knepley PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1693002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1694552f7358SJed Brown 1695552f7358SJed Brown PetscFunctionBegin; 1696552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1697552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 16989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii)); 16999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 17009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 17019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 17029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 17039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus)); 1704552f7358SJed Brown if (iascii) { 17058135c375SStefano Zampini PetscViewerFormat format; 17069566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 17078135c375SStefano Zampini if (format == PETSC_VIEWER_ASCII_GLVIS) { 17089566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 17098135c375SStefano Zampini } else { 17109566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(dm, viewer)); 17118135c375SStefano Zampini } 1712c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1713c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 17149566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1715c6ccd67eSMatthew G. Knepley #else 1716c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1717552f7358SJed Brown #endif 1718e412dcbdSMatthew G. Knepley } else if (isvtk) { 17199566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject) dm,viewer)); 1720e412dcbdSMatthew G. Knepley } else if (isdraw) { 17219566063dSJacob Faibussowitsch PetscCall(DMPlexView_Draw(dm, viewer)); 17228135c375SStefano Zampini } else if (isglvis) { 17239566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 17241e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17251e50132fSMatthew G. Knepley } else if (isexodus) { 17266823f3c5SBlaise Bourdin /* 17276823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 17286823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 17296823f3c5SBlaise Bourdin with ID 1, containig all cells. 17306823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 17316823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 17326823f3c5SBlaise Bourdin */ 17336823f3c5SBlaise Bourdin PetscInt numCS; 17349566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm,"Cell Sets",&numCS)); 17356823f3c5SBlaise Bourdin if (!numCS) { 17361e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 17379566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 17389566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 17399566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 17406823f3c5SBlaise Bourdin } 17419566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 17421e50132fSMatthew G. Knepley #endif 174362201deeSVaclav Hapla } else { 174498921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1745fcf6c8fdSToby Isaac } 1746cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 17479566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg)); 1748cb3ba0daSMatthew G. Knepley if (flg) { 1749cb3ba0daSMatthew G. Knepley Vec ranks; 17509566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 17519566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 17529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1753cb3ba0daSMatthew G. Knepley } 1754002a2709SMatthew G. Knepley /* Optionally view a label */ 17559566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1756002a2709SMatthew G. Knepley if (flg) { 1757002a2709SMatthew G. Knepley DMLabel label; 1758002a2709SMatthew G. Knepley Vec val; 1759002a2709SMatthew G. Knepley 17609566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 176128b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 17629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 17639566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 17649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1765002a2709SMatthew G. Knepley } 1766552f7358SJed Brown PetscFunctionReturn(0); 1767552f7358SJed Brown } 1768552f7358SJed Brown 17697f96f51bSksagiyam /*@ 17707f96f51bSksagiyam DMPlexTopologyView - Saves a DMPlex topology into a file 17717f96f51bSksagiyam 17727f96f51bSksagiyam Collective on DM 17737f96f51bSksagiyam 17747f96f51bSksagiyam Input Parameters: 17757f96f51bSksagiyam + dm - The DM whose topology is to be saved 17767f96f51bSksagiyam - viewer - The PetscViewer for saving 17777f96f51bSksagiyam 17787f96f51bSksagiyam Level: advanced 17797f96f51bSksagiyam 1780db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()` 17817f96f51bSksagiyam @*/ 17827f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 17837f96f51bSksagiyam { 17847f96f51bSksagiyam PetscBool ishdf5; 17857f96f51bSksagiyam 17867f96f51bSksagiyam PetscFunctionBegin; 17877f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17887f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 17909566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0)); 17917f96f51bSksagiyam if (ishdf5) { 17927f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 17937f96f51bSksagiyam PetscViewerFormat format; 17949566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 17957f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 17967f96f51bSksagiyam IS globalPointNumbering; 17977f96f51bSksagiyam 17989566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 17999566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 180198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 18027f96f51bSksagiyam #else 18037f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 18047f96f51bSksagiyam #endif 18057f96f51bSksagiyam } 18069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0)); 18077f96f51bSksagiyam PetscFunctionReturn(0); 18087f96f51bSksagiyam } 18097f96f51bSksagiyam 181077b8e257Sksagiyam /*@ 181177b8e257Sksagiyam DMPlexCoordinatesView - Saves DMPlex coordinates into a file 181277b8e257Sksagiyam 181377b8e257Sksagiyam Collective on DM 181477b8e257Sksagiyam 181577b8e257Sksagiyam Input Parameters: 181677b8e257Sksagiyam + dm - The DM whose coordinates are to be saved 181777b8e257Sksagiyam - viewer - The PetscViewer for saving 181877b8e257Sksagiyam 181977b8e257Sksagiyam Level: advanced 182077b8e257Sksagiyam 1821db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()` 182277b8e257Sksagiyam @*/ 182377b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 182477b8e257Sksagiyam { 182577b8e257Sksagiyam PetscBool ishdf5; 182677b8e257Sksagiyam 182777b8e257Sksagiyam PetscFunctionBegin; 182877b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 182977b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 18319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0)); 183277b8e257Sksagiyam if (ishdf5) { 183377b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 183477b8e257Sksagiyam PetscViewerFormat format; 18359566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 183677b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18379566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 183898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 183977b8e257Sksagiyam #else 184077b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 184177b8e257Sksagiyam #endif 184277b8e257Sksagiyam } 18439566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0)); 184477b8e257Sksagiyam PetscFunctionReturn(0); 184577b8e257Sksagiyam } 184677b8e257Sksagiyam 1847bd6565f1Sksagiyam /*@ 1848bd6565f1Sksagiyam DMPlexLabelsView - Saves DMPlex labels into a file 1849bd6565f1Sksagiyam 1850bd6565f1Sksagiyam Collective on DM 1851bd6565f1Sksagiyam 1852bd6565f1Sksagiyam Input Parameters: 1853bd6565f1Sksagiyam + dm - The DM whose labels are to be saved 1854bd6565f1Sksagiyam - viewer - The PetscViewer for saving 1855bd6565f1Sksagiyam 1856bd6565f1Sksagiyam Level: advanced 1857bd6565f1Sksagiyam 1858db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()` 1859bd6565f1Sksagiyam @*/ 1860bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1861bd6565f1Sksagiyam { 1862bd6565f1Sksagiyam PetscBool ishdf5; 1863bd6565f1Sksagiyam 1864bd6565f1Sksagiyam PetscFunctionBegin; 1865bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1866bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 18689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0)); 1869bd6565f1Sksagiyam if (ishdf5) { 1870bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 1871bd6565f1Sksagiyam IS globalPointNumbering; 1872bd6565f1Sksagiyam PetscViewerFormat format; 1873bd6565f1Sksagiyam 18749566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 1875bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18769566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18779566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 187998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1880bd6565f1Sksagiyam #else 1881bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1882bd6565f1Sksagiyam #endif 1883bd6565f1Sksagiyam } 18849566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0)); 1885bd6565f1Sksagiyam PetscFunctionReturn(0); 1886bd6565f1Sksagiyam } 1887bd6565f1Sksagiyam 1888021affd3Sksagiyam /*@ 1889021affd3Sksagiyam DMPlexSectionView - Saves a section associated with a DMPlex 1890021affd3Sksagiyam 1891021affd3Sksagiyam Collective on DM 1892021affd3Sksagiyam 1893021affd3Sksagiyam Input Parameters: 1894021affd3Sksagiyam + dm - The DM that contains the topology on which the section to be saved is defined 1895021affd3Sksagiyam . viewer - The PetscViewer for saving 1896021affd3Sksagiyam - sectiondm - The DM that contains the section to be saved 1897021affd3Sksagiyam 1898021affd3Sksagiyam Level: advanced 1899021affd3Sksagiyam 1900021affd3Sksagiyam Notes: 1901021affd3Sksagiyam 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. 1902021affd3Sksagiyam 1903021affd3Sksagiyam 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. 1904021affd3Sksagiyam 1905db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()` 1906021affd3Sksagiyam @*/ 1907021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1908021affd3Sksagiyam { 1909021affd3Sksagiyam PetscBool ishdf5; 1910021affd3Sksagiyam 1911021affd3Sksagiyam PetscFunctionBegin; 1912021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1913021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1914021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 19169566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0)); 1917021affd3Sksagiyam if (ishdf5) { 1918021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 19199566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 1920021affd3Sksagiyam #else 1921021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1922021affd3Sksagiyam #endif 1923021affd3Sksagiyam } 19249566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0)); 1925021affd3Sksagiyam PetscFunctionReturn(0); 1926021affd3Sksagiyam } 1927021affd3Sksagiyam 19283e97647fSksagiyam /*@ 19293e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 19303e97647fSksagiyam 19313e97647fSksagiyam Collective on DM 19323e97647fSksagiyam 19333e97647fSksagiyam Input Parameters: 19343e97647fSksagiyam + dm - The DM that represents the topology 19353e97647fSksagiyam . viewer - The PetscViewer to save data with 19363e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined 19373e97647fSksagiyam - vec - The global vector to be saved 19383e97647fSksagiyam 19393e97647fSksagiyam Level: advanced 19403e97647fSksagiyam 19413e97647fSksagiyam Notes: 19423e97647fSksagiyam 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. 19433e97647fSksagiyam 19443e97647fSksagiyam Typical calling sequence 19453e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 19463e97647fSksagiyam $ DMSetType(dm, DMPLEX); 19473e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 19483e97647fSksagiyam $ DMClone(dm, §iondm); 19493e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 19503e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 19513e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 19523e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 19533e97647fSksagiyam $ PetscSectionSetUp(section); 19543e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 19553e97647fSksagiyam $ PetscSectionDestroy(§ion); 19563e97647fSksagiyam $ DMGetGlobalVector(sectiondm, &vec); 19573e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 19583e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 19593e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 19603e97647fSksagiyam $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 19613e97647fSksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 19623e97647fSksagiyam $ DMDestroy(§iondm); 19633e97647fSksagiyam $ DMDestroy(&dm); 19643e97647fSksagiyam 1965db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 19663e97647fSksagiyam @*/ 19673e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 19683e97647fSksagiyam { 19693e97647fSksagiyam PetscBool ishdf5; 19703e97647fSksagiyam 19713e97647fSksagiyam PetscFunctionBegin; 19723e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19733e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19743e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19753e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 19763e97647fSksagiyam /* Check consistency */ 19773e97647fSksagiyam { 19783e97647fSksagiyam PetscSection section; 19793e97647fSksagiyam PetscBool includesConstraints; 19803e97647fSksagiyam PetscInt m, m1; 19813e97647fSksagiyam 19829566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 19839566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 19849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 19859566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 19869566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 198763a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 19883e97647fSksagiyam } 19899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19909566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0)); 19913e97647fSksagiyam if (ishdf5) { 19923e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 19939566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 19943e97647fSksagiyam #else 19953e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 19963e97647fSksagiyam #endif 19973e97647fSksagiyam } 19989566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0)); 19993e97647fSksagiyam PetscFunctionReturn(0); 20003e97647fSksagiyam } 20013e97647fSksagiyam 20023e97647fSksagiyam /*@ 20033e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 20043e97647fSksagiyam 20053e97647fSksagiyam Collective on DM 20063e97647fSksagiyam 20073e97647fSksagiyam Input Parameters: 20083e97647fSksagiyam + dm - The DM that represents the topology 20093e97647fSksagiyam . viewer - The PetscViewer to save data with 20103e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 20113e97647fSksagiyam - vec - The local vector to be saved 20123e97647fSksagiyam 20133e97647fSksagiyam Level: advanced 20143e97647fSksagiyam 20153e97647fSksagiyam Notes: 20163e97647fSksagiyam 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. 20173e97647fSksagiyam 20183e97647fSksagiyam Typical calling sequence 20193e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 20203e97647fSksagiyam $ DMSetType(dm, DMPLEX); 20213e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 20223e97647fSksagiyam $ DMClone(dm, §iondm); 20233e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 20243e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 20253e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 20263e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 20273e97647fSksagiyam $ PetscSectionSetUp(section); 20283e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 20293e97647fSksagiyam $ DMGetLocalVector(sectiondm, &vec); 20303e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 20313e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 20323e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 20333e97647fSksagiyam $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 20343e97647fSksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 20353e97647fSksagiyam $ DMDestroy(§iondm); 20363e97647fSksagiyam $ DMDestroy(&dm); 20373e97647fSksagiyam 2038db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 20393e97647fSksagiyam @*/ 20403e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 20413e97647fSksagiyam { 20423e97647fSksagiyam PetscBool ishdf5; 20433e97647fSksagiyam 20443e97647fSksagiyam PetscFunctionBegin; 20453e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20463e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20473e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 20483e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 20493e97647fSksagiyam /* Check consistency */ 20503e97647fSksagiyam { 20513e97647fSksagiyam PetscSection section; 20523e97647fSksagiyam PetscBool includesConstraints; 20533e97647fSksagiyam PetscInt m, m1; 20543e97647fSksagiyam 20559566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 20569566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 20579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 20589566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 20599566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 206063a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 20613e97647fSksagiyam } 20629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0)); 20643e97647fSksagiyam if (ishdf5) { 20653e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 20669566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20673e97647fSksagiyam #else 20683e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20693e97647fSksagiyam #endif 20703e97647fSksagiyam } 20719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0)); 20723e97647fSksagiyam PetscFunctionReturn(0); 20733e97647fSksagiyam } 20743e97647fSksagiyam 20752c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 20762c40f234SMatthew G. Knepley { 2077d4f5a9a0SVaclav Hapla PetscBool ishdf5; 20782c40f234SMatthew G. Knepley 20792c40f234SMatthew G. Knepley PetscFunctionBegin; 20802c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20812c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 2083d4f5a9a0SVaclav Hapla if (ishdf5) { 20842c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 20859c48423bSVaclav Hapla PetscViewerFormat format; 20869566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20879c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 20889566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2089509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20909566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 209198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2092b458e8f1SJose E. Roman PetscFunctionReturn(0); 20932c40f234SMatthew G. Knepley #else 20942c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2095552f7358SJed Brown #endif 209698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2097552f7358SJed Brown } 2098552f7358SJed Brown 2099ea8e1828Sksagiyam /*@ 2100ea8e1828Sksagiyam DMPlexTopologyLoad - Loads a topology into a DMPlex 2101ea8e1828Sksagiyam 2102ea8e1828Sksagiyam Collective on DM 2103ea8e1828Sksagiyam 2104ea8e1828Sksagiyam Input Parameters: 2105ea8e1828Sksagiyam + dm - The DM into which the topology is loaded 2106ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology 2107ea8e1828Sksagiyam 2108dec9e869Sksagiyam Output Parameters: 2109f84dd6b4Sksagiyam . 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 2110dec9e869Sksagiyam 2111ea8e1828Sksagiyam Level: advanced 2112ea8e1828Sksagiyam 2113db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 2114ea8e1828Sksagiyam @*/ 2115f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2116ea8e1828Sksagiyam { 2117ea8e1828Sksagiyam PetscBool ishdf5; 2118ea8e1828Sksagiyam 2119ea8e1828Sksagiyam PetscFunctionBegin; 2120ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2121ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2122f84dd6b4Sksagiyam if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 21239566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 21249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0)); 2125ea8e1828Sksagiyam if (ishdf5) { 2126ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2127ea8e1828Sksagiyam PetscViewerFormat format; 21289566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2129ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21309566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 213198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2132ea8e1828Sksagiyam #else 2133ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2134ea8e1828Sksagiyam #endif 2135ea8e1828Sksagiyam } 21369566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0)); 2137ea8e1828Sksagiyam PetscFunctionReturn(0); 2138ea8e1828Sksagiyam } 2139ea8e1828Sksagiyam 21403e701f1cSksagiyam /*@ 21413e701f1cSksagiyam DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 21423e701f1cSksagiyam 21433e701f1cSksagiyam Collective on DM 21443e701f1cSksagiyam 21453e701f1cSksagiyam Input Parameters: 21463e701f1cSksagiyam + dm - The DM into which the coordinates are loaded 2147c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates 2148c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 21493e701f1cSksagiyam 21503e701f1cSksagiyam Level: advanced 21513e701f1cSksagiyam 2152db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 21533e701f1cSksagiyam @*/ 2154c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 21553e701f1cSksagiyam { 21563e701f1cSksagiyam PetscBool ishdf5; 21573e701f1cSksagiyam 21583e701f1cSksagiyam PetscFunctionBegin; 21593e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21603e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2161c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 21629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 21639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0)); 21643e701f1cSksagiyam if (ishdf5) { 21653e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 21663e701f1cSksagiyam PetscViewerFormat format; 21679566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 21683e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21699566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 217098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 21713e701f1cSksagiyam #else 21723e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21733e701f1cSksagiyam #endif 21743e701f1cSksagiyam } 21759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0)); 21763e701f1cSksagiyam PetscFunctionReturn(0); 21773e701f1cSksagiyam } 21783e701f1cSksagiyam 2179b08ad5deSksagiyam /*@ 2180b08ad5deSksagiyam DMPlexLabelsLoad - Loads labels into a DMPlex 2181b08ad5deSksagiyam 2182b08ad5deSksagiyam Collective on DM 2183b08ad5deSksagiyam 2184b08ad5deSksagiyam Input Parameters: 2185b08ad5deSksagiyam + dm - The DM into which the labels are loaded 2186e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels 2187e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2188b08ad5deSksagiyam 2189b08ad5deSksagiyam Level: advanced 2190b08ad5deSksagiyam 2191e6368b79SVaclav Hapla Notes: 2192e6368b79SVaclav Hapla The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs. 2193e6368b79SVaclav Hapla 2194db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()` 2195b08ad5deSksagiyam @*/ 2196e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2197b08ad5deSksagiyam { 2198b08ad5deSksagiyam PetscBool ishdf5; 2199b08ad5deSksagiyam 2200b08ad5deSksagiyam PetscFunctionBegin; 2201b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2202b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2203e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 22059566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0)); 2206b08ad5deSksagiyam if (ishdf5) { 2207b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2208b08ad5deSksagiyam PetscViewerFormat format; 2209b08ad5deSksagiyam 22109566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2211b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22129566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 221398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2214b08ad5deSksagiyam #else 2215b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2216b08ad5deSksagiyam #endif 2217b08ad5deSksagiyam } 22189566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0)); 2219b08ad5deSksagiyam PetscFunctionReturn(0); 2220b08ad5deSksagiyam } 2221b08ad5deSksagiyam 2222f84dd6b4Sksagiyam /*@ 2223f84dd6b4Sksagiyam DMPlexSectionLoad - Loads section into a DMPlex 2224f84dd6b4Sksagiyam 2225f84dd6b4Sksagiyam Collective on DM 2226f84dd6b4Sksagiyam 2227f84dd6b4Sksagiyam Input Parameters: 2228f84dd6b4Sksagiyam + dm - The DM that represents the topology 2229f84dd6b4Sksagiyam . viewer - The PetscViewer that represents the on-disk section (sectionA) 2230f84dd6b4Sksagiyam . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2231f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2232f84dd6b4Sksagiyam 2233f84dd6b4Sksagiyam Output Parameters 2234f84dd6b4Sksagiyam + 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) 2235f84dd6b4Sksagiyam - 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) 2236f84dd6b4Sksagiyam 2237f84dd6b4Sksagiyam Level: advanced 2238f84dd6b4Sksagiyam 2239f84dd6b4Sksagiyam Notes: 2240f84dd6b4Sksagiyam 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. 2241f84dd6b4Sksagiyam 2242f84dd6b4Sksagiyam 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. 2243f84dd6b4Sksagiyam 2244f84dd6b4Sksagiyam 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. 2245f84dd6b4Sksagiyam 2246f84dd6b4Sksagiyam Example using 2 processes: 2247f84dd6b4Sksagiyam $ NX (number of points on dm): 4 2248f84dd6b4Sksagiyam $ sectionA : the on-disk section 2249f84dd6b4Sksagiyam $ vecA : a vector associated with sectionA 2250f84dd6b4Sksagiyam $ sectionB : sectiondm's local section constructed in this function 2251f84dd6b4Sksagiyam $ vecB (local) : a vector associated with sectiondm's local section 2252f84dd6b4Sksagiyam $ vecB (global) : a vector associated with sectiondm's global section 2253f84dd6b4Sksagiyam $ 2254f84dd6b4Sksagiyam $ rank 0 rank 1 2255f84dd6b4Sksagiyam $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2256f84dd6b4Sksagiyam $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2257f84dd6b4Sksagiyam $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2258f84dd6b4Sksagiyam $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2259f84dd6b4Sksagiyam $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2260f84dd6b4Sksagiyam $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2261f84dd6b4Sksagiyam $ sectionB->atlasDof : 1 0 1 | 1 3 2262f84dd6b4Sksagiyam $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2263f84dd6b4Sksagiyam $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2264f84dd6b4Sksagiyam $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2265f84dd6b4Sksagiyam $ 2266f84dd6b4Sksagiyam $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2267f84dd6b4Sksagiyam 2268db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()` 2269f84dd6b4Sksagiyam @*/ 2270f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2271f84dd6b4Sksagiyam { 2272f84dd6b4Sksagiyam PetscBool ishdf5; 2273f84dd6b4Sksagiyam 2274f84dd6b4Sksagiyam PetscFunctionBegin; 2275f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2276f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2277f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2278f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2279f84dd6b4Sksagiyam if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2280f84dd6b4Sksagiyam if (localDofSF) PetscValidPointer(localDofSF, 6); 22819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 22829566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0)); 2283f84dd6b4Sksagiyam if (ishdf5) { 2284f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 22859566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2286f84dd6b4Sksagiyam #else 2287f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2288f84dd6b4Sksagiyam #endif 2289f84dd6b4Sksagiyam } 22909566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0)); 2291f84dd6b4Sksagiyam PetscFunctionReturn(0); 2292f84dd6b4Sksagiyam } 2293f84dd6b4Sksagiyam 22948be3dfe1Sksagiyam /*@ 22958be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 22968be3dfe1Sksagiyam 22978be3dfe1Sksagiyam Collective on DM 22988be3dfe1Sksagiyam 22998be3dfe1Sksagiyam Input Parameters: 23008be3dfe1Sksagiyam + dm - The DM that represents the topology 23018be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23028be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined 23038be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23048be3dfe1Sksagiyam - vec - The global vector to set values of 23058be3dfe1Sksagiyam 23068be3dfe1Sksagiyam Level: advanced 23078be3dfe1Sksagiyam 23088be3dfe1Sksagiyam Notes: 23098be3dfe1Sksagiyam 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. 23108be3dfe1Sksagiyam 23118be3dfe1Sksagiyam Typical calling sequence 23128be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23138be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23148be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23158be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23168be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23178be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23188be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 23198be3dfe1Sksagiyam $ DMGetGlobalVector(sectiondm, &vec); 23208be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23218be3dfe1Sksagiyam $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 23228be3dfe1Sksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 23238be3dfe1Sksagiyam $ PetscSFDestroy(&gsf); 23248be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 23258be3dfe1Sksagiyam $ DMDestroy(§iondm); 23268be3dfe1Sksagiyam $ DMDestroy(&dm); 23278be3dfe1Sksagiyam 2328db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()` 23298be3dfe1Sksagiyam @*/ 23308be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 23318be3dfe1Sksagiyam { 23328be3dfe1Sksagiyam PetscBool ishdf5; 23338be3dfe1Sksagiyam 23348be3dfe1Sksagiyam PetscFunctionBegin; 23358be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23368be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23378be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 23388be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 23398be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 23408be3dfe1Sksagiyam /* Check consistency */ 23418be3dfe1Sksagiyam { 23428be3dfe1Sksagiyam PetscSection section; 23438be3dfe1Sksagiyam PetscBool includesConstraints; 23448be3dfe1Sksagiyam PetscInt m, m1; 23458be3dfe1Sksagiyam 23469566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 23479566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 23489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 23499566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 23509566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 235163a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 23528be3dfe1Sksagiyam } 23539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 23549566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0)); 23558be3dfe1Sksagiyam if (ishdf5) { 23568be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 23579566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 23588be3dfe1Sksagiyam #else 23598be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23608be3dfe1Sksagiyam #endif 23618be3dfe1Sksagiyam } 23629566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0)); 23638be3dfe1Sksagiyam PetscFunctionReturn(0); 23648be3dfe1Sksagiyam } 23658be3dfe1Sksagiyam 23668be3dfe1Sksagiyam /*@ 23678be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 23688be3dfe1Sksagiyam 23698be3dfe1Sksagiyam Collective on DM 23708be3dfe1Sksagiyam 23718be3dfe1Sksagiyam Input Parameters: 23728be3dfe1Sksagiyam + dm - The DM that represents the topology 23738be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23748be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined 23758be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23768be3dfe1Sksagiyam - vec - The local vector to set values of 23778be3dfe1Sksagiyam 23788be3dfe1Sksagiyam Level: advanced 23798be3dfe1Sksagiyam 23808be3dfe1Sksagiyam Notes: 23818be3dfe1Sksagiyam 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. 23828be3dfe1Sksagiyam 23838be3dfe1Sksagiyam Typical calling sequence 23848be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23858be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23868be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23878be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23888be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23898be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23908be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 23918be3dfe1Sksagiyam $ DMGetLocalVector(sectiondm, &vec); 23928be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23938be3dfe1Sksagiyam $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 23948be3dfe1Sksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 23958be3dfe1Sksagiyam $ PetscSFDestroy(&lsf); 23968be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 23978be3dfe1Sksagiyam $ DMDestroy(§iondm); 23988be3dfe1Sksagiyam $ DMDestroy(&dm); 23998be3dfe1Sksagiyam 2400db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()` 24018be3dfe1Sksagiyam @*/ 24028be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 24038be3dfe1Sksagiyam { 24048be3dfe1Sksagiyam PetscBool ishdf5; 24058be3dfe1Sksagiyam 24068be3dfe1Sksagiyam PetscFunctionBegin; 24078be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24088be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24098be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24108be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24118be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24128be3dfe1Sksagiyam /* Check consistency */ 24138be3dfe1Sksagiyam { 24148be3dfe1Sksagiyam PetscSection section; 24158be3dfe1Sksagiyam PetscBool includesConstraints; 24168be3dfe1Sksagiyam PetscInt m, m1; 24178be3dfe1Sksagiyam 24189566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 24199566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 24209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24219566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 24229566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 242363a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 24248be3dfe1Sksagiyam } 24259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 24269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0)); 24278be3dfe1Sksagiyam if (ishdf5) { 24288be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 24299566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 24308be3dfe1Sksagiyam #else 24318be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24328be3dfe1Sksagiyam #endif 24338be3dfe1Sksagiyam } 24349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0)); 24358be3dfe1Sksagiyam PetscFunctionReturn(0); 24368be3dfe1Sksagiyam } 24378be3dfe1Sksagiyam 2438552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm) 2439552f7358SJed Brown { 2440552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2441552f7358SJed Brown 2442552f7358SJed Brown PetscFunctionBegin; 24439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL)); 24449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL)); 24459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL)); 24469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL)); 24470d644c17SKarl Rupp if (--mesh->refct > 0) PetscFunctionReturn(0); 24489566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 24499566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 24509566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 24519566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 24529566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 24539566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 24549566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->facesTmp)); 24559566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 24569566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 24579566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 24589566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 24599566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 24609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 24619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 24629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 24639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 24649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 24659566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 24669566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 24679566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 24689566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 24699566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 24709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 24719566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 24729566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 24739566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2474552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 24759566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 2476552f7358SJed Brown PetscFunctionReturn(0); 2477552f7358SJed Brown } 2478552f7358SJed Brown 2479b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2480552f7358SJed Brown { 24818d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2482acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 2483552f7358SJed Brown PetscInt localSize; 2484837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2485b412c318SBarry Smith MatType mtype; 24861428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2487552f7358SJed Brown 2488552f7358SJed Brown PetscFunctionBegin; 24899566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2490b412c318SBarry Smith mtype = dm->mattype; 24919566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 24929566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 24939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 24949566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 24959566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 24969566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 24979566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 24989566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2499acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 25009566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 25019566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 25029566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 25039566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 25049566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 25059566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 25069566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 25079566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2508552f7358SJed Brown if (!isShell) { 2509837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2510e432b41dSStefano Zampini PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2]; 2511fad22124SMatthew G Knepley PetscInt pStart, pEnd, p, dof, cdof; 2512552f7358SJed Brown 25139566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm,<og)); 25149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2515e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2516a9d99c84SMatthew G. Knepley PetscInt bdof; 2517a9d99c84SMatthew G. Knepley 25189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 25199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 25201d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof+1) : dof; 25211d17a0a3SMatthew G. Knepley bdof = cdof && (dof-cdof) ? 1 : dof; 25221d17a0a3SMatthew G. Knepley if (dof) { 25231d17a0a3SMatthew G. Knepley if (bs < 0) {bs = bdof;} 2524e432b41dSStefano Zampini else if (bs != bdof) {bs = 1; break;} 2525552f7358SJed Brown } 25262a28c762SMatthew G Knepley } 25272a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2528e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2529e432b41dSStefano Zampini bsLocal[1] = bs; 25309566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 2531e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2532e432b41dSStefano Zampini else bs = bsMinMax[0]; 25336fd5c86aSStefano Zampini bs = PetscMax(1,bs); 25349566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J,ltog,ltog)); 25350682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 25369566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 25379566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 25380682b8bbSJed Brown } else { 25399566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu)); 25409566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 25419566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2542552f7358SJed Brown } 2543aa0f6e3cSJed Brown } 25449566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 2545552f7358SJed Brown PetscFunctionReturn(0); 2546552f7358SJed Brown } 2547552f7358SJed Brown 25487cd05799SMatthew G. Knepley /*@ 2549a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2550be36d101SStefano Zampini 2551be36d101SStefano Zampini Not collective 2552be36d101SStefano Zampini 2553be36d101SStefano Zampini Input Parameter: 2554be36d101SStefano Zampini . mesh - The DMPlex 2555be36d101SStefano Zampini 2556be36d101SStefano Zampini Output Parameters: 2557be36d101SStefano Zampini . subsection - The subdomain section 2558be36d101SStefano Zampini 2559be36d101SStefano Zampini Level: developer 2560be36d101SStefano Zampini 2561be36d101SStefano Zampini .seealso: 25627cd05799SMatthew G. Knepley @*/ 2563be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2564be36d101SStefano Zampini { 2565be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex*) dm->data; 2566be36d101SStefano Zampini 2567be36d101SStefano Zampini PetscFunctionBegin; 2568be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2569be36d101SStefano Zampini if (!mesh->subdomainSection) { 2570be36d101SStefano Zampini PetscSection section; 2571be36d101SStefano Zampini PetscSF sf; 2572be36d101SStefano Zampini 25739566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sf)); 25749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm,§ion)); 25759566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection)); 25769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2577be36d101SStefano Zampini } 2578be36d101SStefano Zampini *subsection = mesh->subdomainSection; 2579be36d101SStefano Zampini PetscFunctionReturn(0); 2580be36d101SStefano Zampini } 2581be36d101SStefano Zampini 2582552f7358SJed Brown /*@ 2583552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2584552f7358SJed Brown 2585552f7358SJed Brown Not collective 2586552f7358SJed Brown 2587552f7358SJed Brown Input Parameter: 2588552f7358SJed Brown . mesh - The DMPlex 2589552f7358SJed Brown 2590552f7358SJed Brown Output Parameters: 2591552f7358SJed Brown + pStart - The first mesh point 2592552f7358SJed Brown - pEnd - The upper bound for mesh points 2593552f7358SJed Brown 2594552f7358SJed Brown Level: beginner 2595552f7358SJed Brown 2596db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()` 2597552f7358SJed Brown @*/ 2598552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2599552f7358SJed Brown { 2600552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2601552f7358SJed Brown 2602552f7358SJed Brown PetscFunctionBegin; 2603552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 2605552f7358SJed Brown PetscFunctionReturn(0); 2606552f7358SJed Brown } 2607552f7358SJed Brown 2608552f7358SJed Brown /*@ 2609552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2610552f7358SJed Brown 2611552f7358SJed Brown Not collective 2612552f7358SJed Brown 2613552f7358SJed Brown Input Parameters: 2614552f7358SJed Brown + mesh - The DMPlex 2615552f7358SJed Brown . pStart - The first mesh point 2616552f7358SJed Brown - pEnd - The upper bound for mesh points 2617552f7358SJed Brown 2618552f7358SJed Brown Output Parameters: 2619552f7358SJed Brown 2620552f7358SJed Brown Level: beginner 2621552f7358SJed Brown 2622db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()` 2623552f7358SJed Brown @*/ 2624552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2625552f7358SJed Brown { 2626552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2627552f7358SJed Brown 2628552f7358SJed Brown PetscFunctionBegin; 2629552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 26319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 2632552f7358SJed Brown PetscFunctionReturn(0); 2633552f7358SJed Brown } 2634552f7358SJed Brown 2635552f7358SJed Brown /*@ 2636eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2637552f7358SJed Brown 2638552f7358SJed Brown Not collective 2639552f7358SJed Brown 2640552f7358SJed Brown Input Parameters: 2641552f7358SJed Brown + mesh - The DMPlex 2642eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2643552f7358SJed Brown 2644552f7358SJed Brown Output Parameter: 2645552f7358SJed Brown . size - The cone size for point p 2646552f7358SJed Brown 2647552f7358SJed Brown Level: beginner 2648552f7358SJed Brown 2649db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2650552f7358SJed Brown @*/ 2651552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2652552f7358SJed Brown { 2653552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2654552f7358SJed Brown 2655552f7358SJed Brown PetscFunctionBegin; 2656552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2657dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 26589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 2659552f7358SJed Brown PetscFunctionReturn(0); 2660552f7358SJed Brown } 2661552f7358SJed Brown 2662552f7358SJed Brown /*@ 2663eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2664552f7358SJed Brown 2665552f7358SJed Brown Not collective 2666552f7358SJed Brown 2667552f7358SJed Brown Input Parameters: 2668552f7358SJed Brown + mesh - The DMPlex 2669eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2670552f7358SJed Brown - size - The cone size for point p 2671552f7358SJed Brown 2672552f7358SJed Brown Output Parameter: 2673552f7358SJed Brown 2674552f7358SJed Brown Note: 2675552f7358SJed Brown This should be called after DMPlexSetChart(). 2676552f7358SJed Brown 2677552f7358SJed Brown Level: beginner 2678552f7358SJed Brown 2679db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2680552f7358SJed Brown @*/ 2681552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2682552f7358SJed Brown { 2683552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2684552f7358SJed Brown 2685552f7358SJed Brown PetscFunctionBegin; 2686552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 2688552f7358SJed Brown PetscFunctionReturn(0); 2689552f7358SJed Brown } 2690552f7358SJed Brown 2691f5a469b9SMatthew G. Knepley /*@ 2692eaf898f9SPatrick Sanan DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2693f5a469b9SMatthew G. Knepley 2694f5a469b9SMatthew G. Knepley Not collective 2695f5a469b9SMatthew G. Knepley 2696f5a469b9SMatthew G. Knepley Input Parameters: 2697f5a469b9SMatthew G. Knepley + mesh - The DMPlex 2698eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2699f5a469b9SMatthew G. Knepley - size - The additional cone size for point p 2700f5a469b9SMatthew G. Knepley 2701f5a469b9SMatthew G. Knepley Output Parameter: 2702f5a469b9SMatthew G. Knepley 2703f5a469b9SMatthew G. Knepley Note: 2704f5a469b9SMatthew G. Knepley This should be called after DMPlexSetChart(). 2705f5a469b9SMatthew G. Knepley 2706f5a469b9SMatthew G. Knepley Level: beginner 2707f5a469b9SMatthew G. Knepley 2708db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2709f5a469b9SMatthew G. Knepley @*/ 2710f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2711f5a469b9SMatthew G. Knepley { 2712f5a469b9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 2713f5a469b9SMatthew G. Knepley PetscFunctionBegin; 2714f5a469b9SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27159566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->coneSection, p, size)); 2716f5a469b9SMatthew G. Knepley PetscFunctionReturn(0); 2717f5a469b9SMatthew G. Knepley } 2718f5a469b9SMatthew G. Knepley 2719552f7358SJed Brown /*@C 2720eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2721552f7358SJed Brown 2722552f7358SJed Brown Not collective 2723552f7358SJed Brown 2724552f7358SJed Brown Input Parameters: 2725833c876bSVaclav Hapla + dm - The DMPlex 2726eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2727552f7358SJed Brown 2728552f7358SJed Brown Output Parameter: 2729552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 2730552f7358SJed Brown 2731552f7358SJed Brown Level: beginner 2732552f7358SJed Brown 27333813dfbdSMatthew G Knepley Fortran Notes: 27343813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 27353813dfbdSMatthew G Knepley include petsc.h90 in your code. 2736922102d1SVaclav Hapla You must also call DMPlexRestoreCone() after you finish using the returned array. 2737922102d1SVaclav Hapla DMPlexRestoreCone() is not needed/available in C. 27383813dfbdSMatthew G Knepley 2739db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()` 2740552f7358SJed Brown @*/ 2741552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2742552f7358SJed Brown { 2743552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2744552f7358SJed Brown PetscInt off; 2745552f7358SJed Brown 2746552f7358SJed Brown PetscFunctionBegin; 2747552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2748552f7358SJed Brown PetscValidPointer(cone, 3); 27499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 2750552f7358SJed Brown *cone = &mesh->cones[off]; 2751552f7358SJed Brown PetscFunctionReturn(0); 2752552f7358SJed Brown } 2753552f7358SJed Brown 27540ce7577fSVaclav Hapla /*@C 27550ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 27560ce7577fSVaclav Hapla 27570ce7577fSVaclav Hapla Not collective 27580ce7577fSVaclav Hapla 27590ce7577fSVaclav Hapla Input Parameters: 27600ce7577fSVaclav Hapla + dm - The DMPlex 27610ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 27620ce7577fSVaclav Hapla 2763d8d19677SJose E. Roman Output Parameters: 27640ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones 27650ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p 27660ce7577fSVaclav Hapla 27670ce7577fSVaclav Hapla Level: intermediate 27680ce7577fSVaclav Hapla 2769db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()` 27700ce7577fSVaclav Hapla @*/ 27710ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 27720ce7577fSVaclav Hapla { 27730ce7577fSVaclav Hapla PetscSection cs, newcs; 27740ce7577fSVaclav Hapla PetscInt *cones; 27750ce7577fSVaclav Hapla PetscInt *newarr=NULL; 27760ce7577fSVaclav Hapla PetscInt n; 27770ce7577fSVaclav Hapla 27780ce7577fSVaclav Hapla PetscFunctionBegin; 27799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 27809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 27819566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL)); 27820ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 27830ce7577fSVaclav Hapla if (pCones) { 27849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 27859566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 27860ce7577fSVaclav Hapla } 27870ce7577fSVaclav Hapla PetscFunctionReturn(0); 27880ce7577fSVaclav Hapla } 27890ce7577fSVaclav Hapla 2790af9eab45SVaclav Hapla /*@ 2791af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2792d4636a37SVaclav Hapla 2793d4636a37SVaclav Hapla Not collective 2794d4636a37SVaclav Hapla 2795d4636a37SVaclav Hapla Input Parameters: 2796d4636a37SVaclav Hapla + dm - The DMPlex 2797af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2798d4636a37SVaclav Hapla 2799d4636a37SVaclav Hapla Output Parameter: 2800af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 2801d4636a37SVaclav Hapla 2802d4636a37SVaclav Hapla Level: advanced 2803d4636a37SVaclav Hapla 2804af9eab45SVaclav Hapla Notes: 2805af9eab45SVaclav Hapla Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2806af9eab45SVaclav Hapla There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2807af9eab45SVaclav Hapla 2808db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()` 2809d4636a37SVaclav Hapla @*/ 2810af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2811d4636a37SVaclav Hapla { 2812af9eab45SVaclav Hapla IS *expandedPointsAll; 2813af9eab45SVaclav Hapla PetscInt depth; 2814d4636a37SVaclav Hapla 2815d4636a37SVaclav Hapla PetscFunctionBegin; 2816af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2817af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2818af9eab45SVaclav Hapla PetscValidPointer(expandedPoints, 3); 28199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2820af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 28219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 28229566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2823af9eab45SVaclav Hapla PetscFunctionReturn(0); 2824af9eab45SVaclav Hapla } 2825af9eab45SVaclav Hapla 2826af9eab45SVaclav Hapla /*@ 2827af9eab45SVaclav 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). 2828af9eab45SVaclav Hapla 2829af9eab45SVaclav Hapla Not collective 2830af9eab45SVaclav Hapla 2831af9eab45SVaclav Hapla Input Parameters: 2832af9eab45SVaclav Hapla + dm - The DMPlex 2833af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2834af9eab45SVaclav Hapla 2835d8d19677SJose E. Roman Output Parameters: 2836af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2837af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 2838af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2839af9eab45SVaclav Hapla 2840af9eab45SVaclav Hapla Level: advanced 2841af9eab45SVaclav Hapla 2842af9eab45SVaclav Hapla Notes: 2843af9eab45SVaclav Hapla Like DMPlexGetConeTuple() but recursive. 2844af9eab45SVaclav Hapla 2845af9eab45SVaclav 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. 2846af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2847af9eab45SVaclav Hapla 2848af9eab45SVaclav 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: 2849af9eab45SVaclav Hapla (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2850af9eab45SVaclav Hapla (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2851af9eab45SVaclav Hapla 2852db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2853af9eab45SVaclav Hapla @*/ 2854af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2855af9eab45SVaclav Hapla { 2856af9eab45SVaclav Hapla const PetscInt *arr0=NULL, *cone=NULL; 2857af9eab45SVaclav Hapla PetscInt *arr=NULL, *newarr=NULL; 2858af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 2859af9eab45SVaclav Hapla IS *expandedPoints_; 2860af9eab45SVaclav Hapla PetscSection *sections_; 2861af9eab45SVaclav Hapla 2862af9eab45SVaclav Hapla PetscFunctionBegin; 2863af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2864af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2865af9eab45SVaclav Hapla if (depth) PetscValidIntPointer(depth, 3); 2866af9eab45SVaclav Hapla if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2867af9eab45SVaclav Hapla if (sections) PetscValidPointer(sections, 5); 28689566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 28699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 28709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 28719566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 28729566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 2873af9eab45SVaclav Hapla arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2874af9eab45SVaclav Hapla for (d=depth_-1; d>=0; d--) { 28759566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 28769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 2877af9eab45SVaclav Hapla for (i=0; i<n; i++) { 28789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d+1, &start, &end)); 2879af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 28809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 28819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 2882af9eab45SVaclav Hapla } else { 28839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 2884af9eab45SVaclav Hapla } 2885af9eab45SVaclav Hapla } 28869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 28879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 28889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 2889af9eab45SVaclav Hapla for (i=0; i<n; i++) { 28909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 28919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 2892af9eab45SVaclav Hapla if (cn > 1) { 28939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 28949566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt))); 2895af9eab45SVaclav Hapla } else { 2896af9eab45SVaclav Hapla newarr[co] = arr[i]; 2897af9eab45SVaclav Hapla } 2898af9eab45SVaclav Hapla } 28999566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 2900af9eab45SVaclav Hapla arr = newarr; 2901af9eab45SVaclav Hapla n = newn; 2902af9eab45SVaclav Hapla } 29039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 2904af9eab45SVaclav Hapla *depth = depth_; 2905af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 2906af9eab45SVaclav Hapla else { 29079566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 29089566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 2909af9eab45SVaclav Hapla } 2910af9eab45SVaclav Hapla if (sections) *sections = sections_; 2911af9eab45SVaclav Hapla else { 29129566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 29139566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 2914af9eab45SVaclav Hapla } 2915af9eab45SVaclav Hapla PetscFunctionReturn(0); 2916af9eab45SVaclav Hapla } 2917af9eab45SVaclav Hapla 2918af9eab45SVaclav Hapla /*@ 2919af9eab45SVaclav Hapla DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2920af9eab45SVaclav Hapla 2921af9eab45SVaclav Hapla Not collective 2922af9eab45SVaclav Hapla 2923af9eab45SVaclav Hapla Input Parameters: 2924af9eab45SVaclav Hapla + dm - The DMPlex 2925af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2926af9eab45SVaclav Hapla 2927d8d19677SJose E. Roman Output Parameters: 2928af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2929af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 2930af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2931af9eab45SVaclav Hapla 2932af9eab45SVaclav Hapla Level: advanced 2933af9eab45SVaclav Hapla 2934af9eab45SVaclav Hapla Notes: 2935af9eab45SVaclav Hapla See DMPlexGetConeRecursive() for details. 2936af9eab45SVaclav Hapla 2937db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2938af9eab45SVaclav Hapla @*/ 2939af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2940af9eab45SVaclav Hapla { 2941af9eab45SVaclav Hapla PetscInt d, depth_; 2942af9eab45SVaclav Hapla 2943af9eab45SVaclav Hapla PetscFunctionBegin; 29449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29451dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2946af9eab45SVaclav Hapla if (depth) *depth = 0; 2947af9eab45SVaclav Hapla if (expandedPoints) { 29489566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 29499566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 2950af9eab45SVaclav Hapla } 2951af9eab45SVaclav Hapla if (sections) { 29529566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 29539566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 2954af9eab45SVaclav Hapla } 2955d4636a37SVaclav Hapla PetscFunctionReturn(0); 2956d4636a37SVaclav Hapla } 2957d4636a37SVaclav Hapla 2958552f7358SJed Brown /*@ 295992371b87SBarry 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 2960552f7358SJed Brown 2961552f7358SJed Brown Not collective 2962552f7358SJed Brown 2963552f7358SJed Brown Input Parameters: 2964552f7358SJed Brown + mesh - The DMPlex 2965eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2966552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 2967552f7358SJed Brown 2968552f7358SJed Brown Output Parameter: 2969552f7358SJed Brown 2970552f7358SJed Brown Note: 2971552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2972552f7358SJed Brown 2973552f7358SJed Brown Level: beginner 2974552f7358SJed Brown 2975db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 2976552f7358SJed Brown @*/ 2977552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2978552f7358SJed Brown { 2979552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2980552f7358SJed Brown PetscInt pStart, pEnd; 2981552f7358SJed Brown PetscInt dof, off, c; 2982552f7358SJed Brown 2983552f7358SJed Brown PetscFunctionBegin; 2984552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 29869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 2987dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(cone, 3); 29889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 298963a3b9bcSJacob 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); 2990552f7358SJed Brown for (c = 0; c < dof; ++c) { 299163a3b9bcSJacob 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); 2992552f7358SJed Brown mesh->cones[off+c] = cone[c]; 2993552f7358SJed Brown } 2994552f7358SJed Brown PetscFunctionReturn(0); 2995552f7358SJed Brown } 2996552f7358SJed Brown 2997552f7358SJed Brown /*@C 2998eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2999552f7358SJed Brown 3000552f7358SJed Brown Not collective 3001552f7358SJed Brown 3002552f7358SJed Brown Input Parameters: 3003552f7358SJed Brown + mesh - The DMPlex 3004eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3005552f7358SJed Brown 3006552f7358SJed Brown Output Parameter: 3007552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 3008b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3009552f7358SJed Brown 3010552f7358SJed Brown Level: beginner 3011552f7358SJed Brown 3012b5a892a1SMatthew G. Knepley Notes: 3013b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3014b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3015b5a892a1SMatthew G. Knepley of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 3016b5a892a1SMatthew G. Knepley with the identity. 3017b5a892a1SMatthew G. Knepley 30183813dfbdSMatthew G Knepley Fortran Notes: 30193813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 30203813dfbdSMatthew G Knepley include petsc.h90 in your code. 30213b12b3d8SVaclav Hapla You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 3022922102d1SVaclav Hapla DMPlexRestoreConeOrientation() is not needed/available in C. 30233813dfbdSMatthew G Knepley 3024db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3025552f7358SJed Brown @*/ 3026552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3027552f7358SJed Brown { 3028552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3029552f7358SJed Brown PetscInt off; 3030552f7358SJed Brown 3031552f7358SJed Brown PetscFunctionBegin; 3032552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 303376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3034552f7358SJed Brown PetscInt dof; 30359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3036552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 3037552f7358SJed Brown } 30389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30390d644c17SKarl Rupp 3040552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 3041552f7358SJed Brown PetscFunctionReturn(0); 3042552f7358SJed Brown } 3043552f7358SJed Brown 3044552f7358SJed Brown /*@ 3045eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3046552f7358SJed Brown 3047552f7358SJed Brown Not collective 3048552f7358SJed Brown 3049552f7358SJed Brown Input Parameters: 3050552f7358SJed Brown + mesh - The DMPlex 3051eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3052b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3053552f7358SJed Brown Output Parameter: 3054552f7358SJed Brown 3055b5a892a1SMatthew G. Knepley Notes: 3056552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3057552f7358SJed Brown 3058b5a892a1SMatthew G. Knepley The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3059b5a892a1SMatthew G. Knepley 3060552f7358SJed Brown Level: beginner 3061552f7358SJed Brown 3062db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3063552f7358SJed Brown @*/ 3064552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3065552f7358SJed Brown { 3066552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3067552f7358SJed Brown PetscInt pStart, pEnd; 3068552f7358SJed Brown PetscInt dof, off, c; 3069552f7358SJed Brown 3070552f7358SJed Brown PetscFunctionBegin; 3071552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 30739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3074dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(coneOrientation, 3); 30759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 307663a3b9bcSJacob 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); 3077552f7358SJed Brown for (c = 0; c < dof; ++c) { 3078552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3079552f7358SJed Brown 30809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof)); 30811dca8a05SBarry 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); 3082552f7358SJed Brown mesh->coneOrientations[off+c] = o; 3083552f7358SJed Brown } 3084552f7358SJed Brown PetscFunctionReturn(0); 3085552f7358SJed Brown } 3086552f7358SJed Brown 30877cd05799SMatthew G. Knepley /*@ 3088eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 30897cd05799SMatthew G. Knepley 30907cd05799SMatthew G. Knepley Not collective 30917cd05799SMatthew G. Knepley 30927cd05799SMatthew G. Knepley Input Parameters: 30937cd05799SMatthew G. Knepley + mesh - The DMPlex 3094eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 30957cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 30967cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 30977cd05799SMatthew G. Knepley 30987cd05799SMatthew G. Knepley Level: beginner 30997cd05799SMatthew G. Knepley 3100db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31017cd05799SMatthew G. Knepley @*/ 3102552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3103552f7358SJed Brown { 3104552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3105552f7358SJed Brown PetscInt pStart, pEnd; 3106552f7358SJed Brown PetscInt dof, off; 3107552f7358SJed Brown 3108552f7358SJed Brown PetscFunctionBegin; 3109552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 311163a3b9bcSJacob 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); 311263a3b9bcSJacob 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); 31139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 311563a3b9bcSJacob 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); 3116552f7358SJed Brown mesh->cones[off+conePos] = conePoint; 3117552f7358SJed Brown PetscFunctionReturn(0); 3118552f7358SJed Brown } 3119552f7358SJed Brown 31207cd05799SMatthew G. Knepley /*@ 3121eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 31227cd05799SMatthew G. Knepley 31237cd05799SMatthew G. Knepley Not collective 31247cd05799SMatthew G. Knepley 31257cd05799SMatthew G. Knepley Input Parameters: 31267cd05799SMatthew G. Knepley + mesh - The DMPlex 3127eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31287cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31297cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 31307cd05799SMatthew G. Knepley 31317cd05799SMatthew G. Knepley Level: beginner 31327cd05799SMatthew G. Knepley 3133b5a892a1SMatthew G. Knepley Notes: 3134b5a892a1SMatthew G. Knepley The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3135b5a892a1SMatthew G. Knepley 3136db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31377cd05799SMatthew G. Knepley @*/ 313877c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 313977c88f5bSMatthew G Knepley { 314077c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 314177c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 314277c88f5bSMatthew G Knepley PetscInt dof, off; 314377c88f5bSMatthew G Knepley 314477c88f5bSMatthew G Knepley PetscFunctionBegin; 314577c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 314763a3b9bcSJacob 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); 31489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 315063a3b9bcSJacob 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); 315177c88f5bSMatthew G Knepley mesh->coneOrientations[off+conePos] = coneOrientation; 315277c88f5bSMatthew G Knepley PetscFunctionReturn(0); 315377c88f5bSMatthew G Knepley } 315477c88f5bSMatthew G Knepley 3155552f7358SJed Brown /*@ 3156eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3157552f7358SJed Brown 3158552f7358SJed Brown Not collective 3159552f7358SJed Brown 3160552f7358SJed Brown Input Parameters: 3161552f7358SJed Brown + mesh - The DMPlex 3162eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3163552f7358SJed Brown 3164552f7358SJed Brown Output Parameter: 3165552f7358SJed Brown . size - The support size for point p 3166552f7358SJed Brown 3167552f7358SJed Brown Level: beginner 3168552f7358SJed Brown 3169db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3170552f7358SJed Brown @*/ 3171552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3172552f7358SJed Brown { 3173552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3174552f7358SJed Brown 3175552f7358SJed Brown PetscFunctionBegin; 3176552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3177dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 31789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 3179552f7358SJed Brown PetscFunctionReturn(0); 3180552f7358SJed Brown } 3181552f7358SJed Brown 3182552f7358SJed Brown /*@ 3183eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3184552f7358SJed Brown 3185552f7358SJed Brown Not collective 3186552f7358SJed Brown 3187552f7358SJed Brown Input Parameters: 3188552f7358SJed Brown + mesh - The DMPlex 3189eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3190552f7358SJed Brown - size - The support size for point p 3191552f7358SJed Brown 3192552f7358SJed Brown Output Parameter: 3193552f7358SJed Brown 3194552f7358SJed Brown Note: 3195552f7358SJed Brown This should be called after DMPlexSetChart(). 3196552f7358SJed Brown 3197552f7358SJed Brown Level: beginner 3198552f7358SJed Brown 3199db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3200552f7358SJed Brown @*/ 3201552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3202552f7358SJed Brown { 3203552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3204552f7358SJed Brown 3205552f7358SJed Brown PetscFunctionBegin; 3206552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 3208552f7358SJed Brown PetscFunctionReturn(0); 3209552f7358SJed Brown } 3210552f7358SJed Brown 3211552f7358SJed Brown /*@C 3212eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3213552f7358SJed Brown 3214552f7358SJed Brown Not collective 3215552f7358SJed Brown 3216552f7358SJed Brown Input Parameters: 3217552f7358SJed Brown + mesh - The DMPlex 3218eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3219552f7358SJed Brown 3220552f7358SJed Brown Output Parameter: 3221552f7358SJed Brown . support - An array of points which are on the out-edges for point p 3222552f7358SJed Brown 3223552f7358SJed Brown Level: beginner 3224552f7358SJed Brown 32253813dfbdSMatthew G Knepley Fortran Notes: 32263813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 32273813dfbdSMatthew G Knepley include petsc.h90 in your code. 32283b12b3d8SVaclav Hapla You must also call DMPlexRestoreSupport() after you finish using the returned array. 3229922102d1SVaclav Hapla DMPlexRestoreSupport() is not needed/available in C. 32303813dfbdSMatthew G Knepley 3231db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3232552f7358SJed Brown @*/ 3233552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3234552f7358SJed Brown { 3235552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3236552f7358SJed Brown PetscInt off; 3237552f7358SJed Brown 3238552f7358SJed Brown PetscFunctionBegin; 3239552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3240552f7358SJed Brown PetscValidPointer(support, 3); 32419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3242552f7358SJed Brown *support = &mesh->supports[off]; 3243552f7358SJed Brown PetscFunctionReturn(0); 3244552f7358SJed Brown } 3245552f7358SJed Brown 3246552f7358SJed Brown /*@ 324792371b87SBarry 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 3248552f7358SJed Brown 3249552f7358SJed Brown Not collective 3250552f7358SJed Brown 3251552f7358SJed Brown Input Parameters: 3252552f7358SJed Brown + mesh - The DMPlex 3253eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 325492371b87SBarry Smith - support - An array of points which are on the out-edges for point p 3255552f7358SJed Brown 3256552f7358SJed Brown Output Parameter: 3257552f7358SJed Brown 3258552f7358SJed Brown Note: 3259552f7358SJed Brown This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3260552f7358SJed Brown 3261552f7358SJed Brown Level: beginner 3262552f7358SJed Brown 3263db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3264552f7358SJed Brown @*/ 3265552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3266552f7358SJed Brown { 3267552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3268552f7358SJed Brown PetscInt pStart, pEnd; 3269552f7358SJed Brown PetscInt dof, off, c; 3270552f7358SJed Brown 3271552f7358SJed Brown PetscFunctionBegin; 3272552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 32749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 3275dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(support, 3); 32769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 327763a3b9bcSJacob 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); 3278552f7358SJed Brown for (c = 0; c < dof; ++c) { 327963a3b9bcSJacob 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); 3280552f7358SJed Brown mesh->supports[off+c] = support[c]; 3281552f7358SJed Brown } 3282552f7358SJed Brown PetscFunctionReturn(0); 3283552f7358SJed Brown } 3284552f7358SJed Brown 32857cd05799SMatthew G. Knepley /*@ 3286eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 32877cd05799SMatthew G. Knepley 32887cd05799SMatthew G. Knepley Not collective 32897cd05799SMatthew G. Knepley 32907cd05799SMatthew G. Knepley Input Parameters: 32917cd05799SMatthew G. Knepley + mesh - The DMPlex 3292eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 32937cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 32947cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 32957cd05799SMatthew G. Knepley 32967cd05799SMatthew G. Knepley Level: beginner 32977cd05799SMatthew G. Knepley 3298db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 32997cd05799SMatthew G. Knepley @*/ 3300552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3301552f7358SJed Brown { 3302552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3303552f7358SJed Brown PetscInt pStart, pEnd; 3304552f7358SJed Brown PetscInt dof, off; 3305552f7358SJed Brown 3306552f7358SJed Brown PetscFunctionBegin; 3307552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 33109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 331163a3b9bcSJacob 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); 331263a3b9bcSJacob 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); 331363a3b9bcSJacob 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); 3314552f7358SJed Brown mesh->supports[off+supportPos] = supportPoint; 3315552f7358SJed Brown PetscFunctionReturn(0); 3316552f7358SJed Brown } 3317552f7358SJed Brown 3318b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3319b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3320b5a892a1SMatthew G. Knepley { 3321b5a892a1SMatthew G. Knepley switch (ct) { 3322b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3323b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3324b5a892a1SMatthew G. Knepley break; 3325b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3326b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3327b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3328b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3329b5a892a1SMatthew G. Knepley break; 3330b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3331b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3332b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3333b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3334b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3335b5a892a1SMatthew G. Knepley break; 3336b5a892a1SMatthew G. Knepley default: return o; 3337b5a892a1SMatthew G. Knepley } 3338b5a892a1SMatthew G. Knepley return o; 3339b5a892a1SMatthew G. Knepley } 3340b5a892a1SMatthew G. Knepley 3341b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3342b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3343b5a892a1SMatthew G. Knepley { 3344b5a892a1SMatthew G. Knepley switch (ct) { 3345b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3346b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3347b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3348b5a892a1SMatthew G. Knepley break; 3349b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3350b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3351b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3352b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3353b5a892a1SMatthew G. Knepley break; 3354b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3355b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3356b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3357b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3358b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3359b5a892a1SMatthew G. Knepley break; 3360b5a892a1SMatthew G. Knepley default: return o; 3361b5a892a1SMatthew G. Knepley } 3362b5a892a1SMatthew G. Knepley return o; 3363b5a892a1SMatthew G. Knepley } 3364b5a892a1SMatthew G. Knepley 3365b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3366b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3367b5a892a1SMatthew G. Knepley { 3368b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3369b5a892a1SMatthew G. Knepley 3370b5a892a1SMatthew G. Knepley PetscFunctionBegin; 33719566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3372b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3373b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3374b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3375b5a892a1SMatthew G. Knepley 33769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 33779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 33789566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3379b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3380b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3381b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3382b5a892a1SMatthew G. Knepley 33839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3384b5a892a1SMatthew G. Knepley switch (ct) { 3385b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 33869566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 33879566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3388b5a892a1SMatthew G. Knepley break; 3389b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 33909566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 33919566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 33929566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3393b5a892a1SMatthew G. Knepley break; 3394b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 33959566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 33969566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 33979566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 33989566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3399b5a892a1SMatthew G. Knepley break; 3400b5a892a1SMatthew G. Knepley default: break; 3401b5a892a1SMatthew G. Knepley } 3402b5a892a1SMatthew G. Knepley } 3403b5a892a1SMatthew G. Knepley } 3404b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3405b5a892a1SMatthew G. Knepley } 3406b5a892a1SMatthew G. Knepley 3407012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3408b5a892a1SMatthew G. Knepley { 3409b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3410b5a892a1SMatthew G. Knepley PetscInt *closure; 3411b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3412b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3413b5a892a1SMatthew G. Knepley 3414b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3415b5a892a1SMatthew G. Knepley if (ornt) { 34169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3417b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3418b5a892a1SMatthew G. Knepley } 3419b5a892a1SMatthew G. Knepley if (*points) { 3420b5a892a1SMatthew G. Knepley closure = *points; 3421b5a892a1SMatthew G. Knepley } else { 3422b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 34239566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 34249566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure)); 3425b5a892a1SMatthew G. Knepley } 3426b5a892a1SMatthew G. Knepley if (useCone) { 34279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &tmpSize)); 34289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &tmp)); 34299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO)); 3430b5a892a1SMatthew G. Knepley } else { 34319566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize)); 34329566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &tmp)); 3433b5a892a1SMatthew G. Knepley } 3434b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3435b5a892a1SMatthew G. Knepley closure[off++] = p; 3436b5a892a1SMatthew G. Knepley closure[off++] = 0; 3437b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3438b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3439b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3440b5a892a1SMatthew G. Knepley } 3441b5a892a1SMatthew G. Knepley } else { 34425f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3443b5a892a1SMatthew G. Knepley 3444b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3445b5a892a1SMatthew G. Knepley closure[off++] = p; 3446b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3447b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3448b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3449b5a892a1SMatthew G. Knepley 34509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3451b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3452b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3453b5a892a1SMatthew G. Knepley } 3454b5a892a1SMatthew G. Knepley } 3455b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize+1; 3456b5a892a1SMatthew G. Knepley if (points) *points = closure; 3457b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3458b5a892a1SMatthew G. Knepley } 3459b5a892a1SMatthew G. Knepley 3460b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3461b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3462b5a892a1SMatthew G. Knepley { 3463b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3464b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3465b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3466b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3467b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3468b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3469b5a892a1SMatthew G. Knepley 3470b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 34719566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 34729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 34739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 34749566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &ornt)); 34759566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3476b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3477b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3478b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 3479b5a892a1SMatthew G. Knepley if (*points) {pts = *points;} 34809566063dSJacob Faibussowitsch else PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts)); 3481b5a892a1SMatthew G. Knepley c = 0; 3482b5a892a1SMatthew G. Knepley pts[c++] = point; 3483b5a892a1SMatthew G. Knepley pts[c++] = o; 34849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft)); 34859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure)); 3486b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 34879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure)); 3488b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 34899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3490b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 34919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft)); 3492b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d*2+0]]; 3493b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3494b5a892a1SMatthew G. Knepley } 3495b5a892a1SMatthew G. Knepley if (dim >= 3) { 3496b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3497b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d*2+0]]; 3498b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3499b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3500b5a892a1SMatthew G. Knepley 35019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3502b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 35039566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize)); 35049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, fpoint, &fcone)); 35059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt)); 3506b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3507b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc*2+0]]; 3508b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc*2+1]; 3509b5a892a1SMatthew G. Knepley 3510b5a892a1SMatthew G. Knepley for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3511b5a892a1SMatthew G. Knepley if (i == c) { 35129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3513b5a892a1SMatthew G. Knepley pts[c++] = cp; 3514b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3515b5a892a1SMatthew G. Knepley } 3516b5a892a1SMatthew G. Knepley } 3517b5a892a1SMatthew G. Knepley } 3518b5a892a1SMatthew G. Knepley } 3519b5a892a1SMatthew G. Knepley *numPoints = c/2; 3520b5a892a1SMatthew G. Knepley *points = pts; 3521b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3522b5a892a1SMatthew G. Knepley } 3523b5a892a1SMatthew G. Knepley 3524b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3525b5a892a1SMatthew G. Knepley { 3526b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3527b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3528b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3529b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3530b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3531b5a892a1SMatthew G. Knepley 3532b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 35339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3534b5a892a1SMatthew G. Knepley if (depth == 1) { 35359566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 3536b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3537b5a892a1SMatthew G. Knepley } 35389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3539b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3540b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 35419566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 3542b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3543b5a892a1SMatthew G. Knepley } 35449566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3545b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3546b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3547b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 35489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3549b5a892a1SMatthew G. Knepley if (*points) {closure = *points;} 35509566063dSJacob Faibussowitsch else PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure)); 3551b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3552b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3553b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3554b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3555b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3556b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3557b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3558b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3559b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3560b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3561b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3562b5a892a1SMatthew G. Knepley const PetscInt *tmp, *tmpO; 3563b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3564b5a892a1SMatthew G. Knepley 3565b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3566b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 356763a3b9bcSJacob 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); 3568b5a892a1SMatthew G. Knepley } 3569b5a892a1SMatthew G. Knepley if (useCone) { 35709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &tmpSize)); 35719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &tmp)); 35729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO)); 3573b5a892a1SMatthew G. Knepley } else { 35749566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize)); 35759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &tmp)); 3576b5a892a1SMatthew G. Knepley tmpO = NULL; 3577b5a892a1SMatthew G. Knepley } 3578b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3579b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3580b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3581b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 35829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3583b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3584b5a892a1SMatthew G. Knepley PetscInt c; 3585b5a892a1SMatthew G. Knepley 3586b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3587b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3588b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3589b5a892a1SMatthew G. Knepley } 3590b5a892a1SMatthew G. Knepley if (c == closureSize) { 3591b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3592b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3593b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3594b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3595b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3596b5a892a1SMatthew G. Knepley } 3597b5a892a1SMatthew G. Knepley } 3598b5a892a1SMatthew G. Knepley } 35999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3600b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize/2; 3601b5a892a1SMatthew G. Knepley if (points) *points = closure; 3602b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3603b5a892a1SMatthew G. Knepley } 3604b5a892a1SMatthew G. Knepley 3605552f7358SJed Brown /*@C 3606eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3607552f7358SJed Brown 3608552f7358SJed Brown Not collective 3609552f7358SJed Brown 3610552f7358SJed Brown Input Parameters: 3611b5a892a1SMatthew G. Knepley + dm - The DMPlex 3612b5a892a1SMatthew G. Knepley . p - The mesh point 36136b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star 3614552f7358SJed Brown 36156b867d5aSJose E. Roman Input/Output Parameter: 36166b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 36176b867d5aSJose E. Roman if NULL on input, internal storage will be returned, otherwise the provided array is used 36186b867d5aSJose E. Roman 36196b867d5aSJose E. Roman Output Parameter: 36206b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3621552f7358SJed Brown 3622552f7358SJed Brown Note: 36230298fd71SBarry Smith If using internal storage (points is NULL on input), each call overwrites the last output. 3624552f7358SJed Brown 36253813dfbdSMatthew G Knepley Fortran Notes: 3626b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36273813dfbdSMatthew G Knepley 36283813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36293813dfbdSMatthew G Knepley 3630552f7358SJed Brown Level: beginner 3631552f7358SJed Brown 3632db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3633552f7358SJed Brown @*/ 3634552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3635552f7358SJed Brown { 3636b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3637552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3638b5a892a1SMatthew G. Knepley if (numPoints) PetscValidIntPointer(numPoints, 4); 3639b5a892a1SMatthew G. Knepley if (points) PetscValidPointer(points, 5); 36409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 36419bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 36429bf0dad6SMatthew G. Knepley } 36439bf0dad6SMatthew G. Knepley 3644552f7358SJed Brown /*@C 3645eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3646552f7358SJed Brown 3647552f7358SJed Brown Not collective 3648552f7358SJed Brown 3649552f7358SJed Brown Input Parameters: 3650b5a892a1SMatthew G. Knepley + dm - The DMPlex 3651b5a892a1SMatthew G. Knepley . p - The mesh point 3652b5a892a1SMatthew G. Knepley . useCone - PETSC_TRUE for the closure, otherwise return the star 3653b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3654b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3655552f7358SJed Brown 3656552f7358SJed Brown Note: 36570298fd71SBarry Smith If not using internal storage (points is not NULL on input), this call is unnecessary 3658552f7358SJed Brown 36593813dfbdSMatthew G Knepley Fortran Notes: 3660b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36613813dfbdSMatthew G Knepley 36623813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36633813dfbdSMatthew G Knepley 3664552f7358SJed Brown Level: beginner 3665552f7358SJed Brown 3666db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3667552f7358SJed Brown @*/ 3668552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3669552f7358SJed Brown { 3670b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3671552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36724ff43b2cSJed Brown if (numPoints) *numPoints = 0; 36739566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 3674552f7358SJed Brown PetscFunctionReturn(0); 3675552f7358SJed Brown } 3676552f7358SJed Brown 3677552f7358SJed Brown /*@ 3678eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3679552f7358SJed Brown 3680552f7358SJed Brown Not collective 3681552f7358SJed Brown 3682552f7358SJed Brown Input Parameter: 3683552f7358SJed Brown . mesh - The DMPlex 3684552f7358SJed Brown 3685552f7358SJed Brown Output Parameters: 3686552f7358SJed Brown + maxConeSize - The maximum number of in-edges 3687552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 3688552f7358SJed Brown 3689552f7358SJed Brown Level: beginner 3690552f7358SJed Brown 3691db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3692552f7358SJed Brown @*/ 3693552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3694552f7358SJed Brown { 3695552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3696552f7358SJed Brown 3697552f7358SJed Brown PetscFunctionBegin; 3698552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36996302a7fbSVaclav Hapla if (maxConeSize) { 37006302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 37016302a7fbSVaclav Hapla } 37026302a7fbSVaclav Hapla if (maxSupportSize) { 37036302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 37046302a7fbSVaclav Hapla } 3705552f7358SJed Brown PetscFunctionReturn(0); 3706552f7358SJed Brown } 3707552f7358SJed Brown 3708552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm) 3709552f7358SJed Brown { 3710552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 37116302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 3712552f7358SJed Brown 3713552f7358SJed Brown PetscFunctionBegin; 3714552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 37169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 37179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 37189566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 37199566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt))); 37206302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 37216302a7fbSVaclav Hapla if (maxSupportSize) { 37229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 37239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 37249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 37259566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt))); 3726552f7358SJed Brown } 3727552f7358SJed Brown PetscFunctionReturn(0); 3728552f7358SJed Brown } 3729552f7358SJed Brown 3730276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3731552f7358SJed Brown { 3732552f7358SJed Brown PetscFunctionBegin; 37339566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 37349566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 3735c2939958SSatish Balay if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3736736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 3737f94b4a02SBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 3738f94b4a02SBlaise Bourdin PetscSection section, sectionSeq; 3739f94b4a02SBlaise Bourdin 37403dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 37419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dm->sfMigration)); 37429566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection((*subdm), §ion)); 37439566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv)); 37449566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq)); 37459566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 3746f94b4a02SBlaise Bourdin 37479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural)); 3748c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 37499566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionSeq)); 37509566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 3751f94b4a02SBlaise Bourdin } 3752552f7358SJed Brown PetscFunctionReturn(0); 3753552f7358SJed Brown } 3754552f7358SJed Brown 37552adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 37562adcc780SMatthew G. Knepley { 37573dcd263cSBlaise Bourdin PetscInt i = 0; 37582adcc780SMatthew G. Knepley 37592adcc780SMatthew G. Knepley PetscFunctionBegin; 37609566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 37619566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 3762c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 37633dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 37643dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 37653dcd263cSBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 37663dcd263cSBlaise Bourdin PetscSection section, sectionSeq; 37673dcd263cSBlaise Bourdin 37683dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 37699566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dms[i]->sfMigration)); 3770c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 37719566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection((*superdm), §ion)); 37729566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv)); 37739566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq)); 37749566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 37753dcd263cSBlaise Bourdin 37769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural)); 3777c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 37789566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionSeq)); 37799566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 37803dcd263cSBlaise Bourdin break; 37813dcd263cSBlaise Bourdin } 37823dcd263cSBlaise Bourdin } 37832adcc780SMatthew G. Knepley PetscFunctionReturn(0); 37842adcc780SMatthew G. Knepley } 37852adcc780SMatthew G. Knepley 3786552f7358SJed Brown /*@ 3787eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3788552f7358SJed Brown 3789552f7358SJed Brown Not collective 3790552f7358SJed Brown 3791552f7358SJed Brown Input Parameter: 3792552f7358SJed Brown . mesh - The DMPlex 3793552f7358SJed Brown 3794552f7358SJed Brown Output Parameter: 3795552f7358SJed Brown 3796552f7358SJed Brown Note: 3797552f7358SJed Brown This should be called after all calls to DMPlexSetCone() 3798552f7358SJed Brown 3799552f7358SJed Brown Level: beginner 3800552f7358SJed Brown 3801db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 3802552f7358SJed Brown @*/ 3803552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm) 3804552f7358SJed Brown { 3805552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3806552f7358SJed Brown PetscInt *offsets; 3807552f7358SJed Brown PetscInt supportSize; 3808552f7358SJed Brown PetscInt pStart, pEnd, p; 3809552f7358SJed Brown 3810552f7358SJed Brown PetscFunctionBegin; 3811552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 381228b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 38139566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0)); 3814552f7358SJed Brown /* Calculate support sizes */ 38159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3816552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3817552f7358SJed Brown PetscInt dof, off, c; 3818552f7358SJed Brown 38199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3821552f7358SJed Brown for (c = off; c < off+dof; ++c) { 38229566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 3823552f7358SJed Brown } 3824552f7358SJed Brown } 38259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 3826552f7358SJed Brown /* Calculate supports */ 38279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 38289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 38299566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 3830552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3831552f7358SJed Brown PetscInt dof, off, c; 3832552f7358SJed Brown 38339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3835552f7358SJed Brown for (c = off; c < off+dof; ++c) { 3836552f7358SJed Brown const PetscInt q = mesh->cones[c]; 3837552f7358SJed Brown PetscInt offS; 3838552f7358SJed Brown 38399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 38400d644c17SKarl Rupp 3841552f7358SJed Brown mesh->supports[offS+offsets[q]] = p; 3842552f7358SJed Brown ++offsets[q]; 3843552f7358SJed Brown } 3844552f7358SJed Brown } 38459566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 38469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0)); 3847552f7358SJed Brown PetscFunctionReturn(0); 3848552f7358SJed Brown } 3849552f7358SJed Brown 3850277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3851277ea44aSLisandro Dalcin { 3852277ea44aSLisandro Dalcin IS stratumIS; 3853277ea44aSLisandro Dalcin 3854277ea44aSLisandro Dalcin PetscFunctionBegin; 3855277ea44aSLisandro Dalcin if (pStart >= pEnd) PetscFunctionReturn(0); 385676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3857277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 3858277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 38599566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 3860277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 38619566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3862277ea44aSLisandro Dalcin if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3863277ea44aSLisandro Dalcin } 386463a3b9bcSJacob 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); 3865277ea44aSLisandro Dalcin } 38669566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS)); 38679566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 38689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 3869277ea44aSLisandro Dalcin PetscFunctionReturn(0); 3870277ea44aSLisandro Dalcin } 3871277ea44aSLisandro Dalcin 3872552f7358SJed Brown /*@ 3873a8d69d7bSBarry Smith DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 38746dd80730SBarry Smith can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3875552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3876552f7358SJed Brown the DAG. 3877552f7358SJed Brown 3878bf4602e4SToby Isaac Collective on dm 3879552f7358SJed Brown 3880552f7358SJed Brown Input Parameter: 3881552f7358SJed Brown . mesh - The DMPlex 3882552f7358SJed Brown 3883552f7358SJed Brown Output Parameter: 3884552f7358SJed Brown 3885552f7358SJed Brown Notes: 3886b1bb481bSMatthew Knepley Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3887b1bb481bSMatthew 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 3888b1bb481bSMatthew Knepley until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3889c58f1c22SToby Isaac manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3890150b719bSJed Brown via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3891552f7358SJed Brown 3892b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3893b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3894b1bb481bSMatthew 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 3895b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 3896b1bb481bSMatthew Knepley $ cone(c0) = {e0, v2} 3897b1bb481bSMatthew Knepley $ cone(e0) = {v0, v1} 3898b1bb481bSMatthew Knepley If DMPlexStratify() is run on this mesh, it will give depths 3899b1bb481bSMatthew Knepley $ depth 0 = {v0, v1, v2} 3900b1bb481bSMatthew Knepley $ depth 1 = {e0, c0} 3901b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3902b1bb481bSMatthew Knepley 3903150b719bSJed Brown DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3904552f7358SJed Brown 3905552f7358SJed Brown Level: beginner 3906552f7358SJed Brown 3907db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 3908552f7358SJed Brown @*/ 3909552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm) 3910552f7358SJed Brown { 3911df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 3912aa50250dSMatthew G. Knepley DMLabel label; 3913552f7358SJed Brown PetscInt pStart, pEnd, p; 3914552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 3915552f7358SJed Brown 3916552f7358SJed Brown PetscFunctionBegin; 3917552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39189566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0)); 3919277ea44aSLisandro Dalcin 3920277ea44aSLisandro Dalcin /* Create depth label */ 39219566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 39229566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 39239566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 3924277ea44aSLisandro Dalcin 3925277ea44aSLisandro Dalcin { 3926552f7358SJed Brown /* Initialize roots and count leaves */ 3927277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3928277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3929552f7358SJed Brown PetscInt coneSize, supportSize; 3930552f7358SJed Brown 3931277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39339566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3934552f7358SJed Brown if (!coneSize && supportSize) { 3935277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3936277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3937552f7358SJed Brown ++numRoots; 3938552f7358SJed Brown } else if (!supportSize && coneSize) { 3939552f7358SJed Brown ++numLeaves; 3940552f7358SJed Brown } else if (!supportSize && !coneSize) { 3941552f7358SJed Brown /* Isolated points */ 3942277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3943277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3944552f7358SJed Brown } 3945552f7358SJed Brown } 39469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1)); 3947277ea44aSLisandro Dalcin } 3948277ea44aSLisandro Dalcin 3949552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 3950277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3951277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3952552f7358SJed Brown PetscInt coneSize, supportSize; 3953552f7358SJed Brown 3954277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39569566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3957552f7358SJed Brown if (!supportSize && coneSize) { 3958277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3959277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3960552f7358SJed Brown } 3961552f7358SJed Brown } 39629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1)); 3963552f7358SJed Brown } else { 3964277ea44aSLisandro Dalcin PetscInt level = 0; 3965277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 3966552f7358SJed Brown 39679566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3968277ea44aSLisandro Dalcin while (qEnd > qStart) { 3969277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3970277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 397174ef644bSMatthew G. Knepley 3972277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 397374ef644bSMatthew G. Knepley const PetscInt *support; 397474ef644bSMatthew G. Knepley PetscInt supportSize, s; 397574ef644bSMatthew G. Knepley 39769566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 39779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &support)); 397874ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 3979277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 3980277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 3981552f7358SJed Brown } 3982552f7358SJed Brown } 39839566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &level)); 39849566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1)); 39859566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 398674ef644bSMatthew G. Knepley } 398774ef644bSMatthew G. Knepley } 3988bf4602e4SToby Isaac { /* just in case there is an empty process */ 3989bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 3990bf4602e4SToby Isaac 39919566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 39929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 3993bf4602e4SToby Isaac for (v = numValues; v < maxValues; v++) { 39949566063dSJacob Faibussowitsch PetscCall(DMLabelAddStratum(label, v)); 3995bf4602e4SToby Isaac } 3996bf4602e4SToby Isaac } 39979566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject) label, &mesh->depthState)); 39989566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0)); 3999552f7358SJed Brown PetscFunctionReturn(0); 4000552f7358SJed Brown } 4001552f7358SJed Brown 4002412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4003ba2698f1SMatthew G. Knepley { 4004412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4005412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4006ba2698f1SMatthew G. Knepley 4007412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 40089566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 40099566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 40109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4011ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4012ba2698f1SMatthew G. Knepley if (depth <= 1) { 4013ba2698f1SMatthew G. Knepley switch (pdepth) { 4014ba2698f1SMatthew G. Knepley case 0: ct = DM_POLYTOPE_POINT;break; 4015ba2698f1SMatthew G. Knepley case 1: 4016ba2698f1SMatthew G. Knepley switch (coneSize) { 4017ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4018ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4019ba2698f1SMatthew G. Knepley case 4: 4020ba2698f1SMatthew G. Knepley switch (dim) { 4021ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 4022ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 4023ba2698f1SMatthew G. Knepley default: break; 4024ba2698f1SMatthew G. Knepley } 4025ba2698f1SMatthew G. Knepley break; 4026da9060c4SMatthew G. Knepley case 5: ct = DM_POLYTOPE_PYRAMID;break; 4027ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4028ba2698f1SMatthew G. Knepley case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 4029ba2698f1SMatthew G. Knepley default: break; 4030ba2698f1SMatthew G. Knepley } 4031ba2698f1SMatthew G. Knepley } 4032ba2698f1SMatthew G. Knepley } else { 4033ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4034ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4035ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4036ba2698f1SMatthew G. Knepley switch (dim) { 4037ba2698f1SMatthew G. Knepley case 1: 4038ba2698f1SMatthew G. Knepley switch (coneSize) { 4039ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4040ba2698f1SMatthew G. Knepley default: break; 4041ba2698f1SMatthew G. Knepley } 4042ba2698f1SMatthew G. Knepley break; 4043ba2698f1SMatthew G. Knepley case 2: 4044ba2698f1SMatthew G. Knepley switch (coneSize) { 4045ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4046ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4047ba2698f1SMatthew G. Knepley default: break; 4048ba2698f1SMatthew G. Knepley } 4049ba2698f1SMatthew G. Knepley break; 4050ba2698f1SMatthew G. Knepley case 3: 4051ba2698f1SMatthew G. Knepley switch (coneSize) { 4052ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4053da9060c4SMatthew G. Knepley case 5: 4054da9060c4SMatthew G. Knepley { 4055da9060c4SMatthew G. Knepley const PetscInt *cone; 4056da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4057da9060c4SMatthew G. Knepley 40589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 40599566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4060da9060c4SMatthew G. Knepley switch (faceConeSize) { 4061da9060c4SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4062da9060c4SMatthew G. Knepley case 4: ct = DM_POLYTOPE_PYRAMID;break; 4063da9060c4SMatthew G. Knepley } 4064da9060c4SMatthew G. Knepley } 4065da9060c4SMatthew G. Knepley break; 4066ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4067ba2698f1SMatthew G. Knepley default: break; 4068ba2698f1SMatthew G. Knepley } 4069ba2698f1SMatthew G. Knepley break; 4070ba2698f1SMatthew G. Knepley default: break; 4071ba2698f1SMatthew G. Knepley } 4072ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4073ba2698f1SMatthew G. Knepley switch (coneSize) { 4074ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4075ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4076ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4077ba2698f1SMatthew G. Knepley default: break; 4078ba2698f1SMatthew G. Knepley } 4079ba2698f1SMatthew G. Knepley } 4080ba2698f1SMatthew G. Knepley } 4081412e9a14SMatthew G. Knepley *pt = ct; 4082412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4083ba2698f1SMatthew G. Knepley } 4084412e9a14SMatthew G. Knepley 4085412e9a14SMatthew G. Knepley /*@ 4086412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4087412e9a14SMatthew G. Knepley 4088412e9a14SMatthew G. Knepley Collective on dm 4089412e9a14SMatthew G. Knepley 4090412e9a14SMatthew G. Knepley Input Parameter: 4091412e9a14SMatthew G. Knepley . mesh - The DMPlex 4092412e9a14SMatthew G. Knepley 4093412e9a14SMatthew G. Knepley DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4094412e9a14SMatthew G. Knepley 4095412e9a14SMatthew G. Knepley Level: developer 4096412e9a14SMatthew G. Knepley 4097412e9a14SMatthew G. Knepley Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4098412e9a14SMatthew G. Knepley internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4099412e9a14SMatthew G. Knepley automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4100412e9a14SMatthew G. Knepley 4101db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4102412e9a14SMatthew G. Knepley @*/ 4103412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm) 4104412e9a14SMatthew G. Knepley { 4105412e9a14SMatthew G. Knepley DM_Plex *mesh; 4106412e9a14SMatthew G. Knepley DMLabel ctLabel; 4107412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4108412e9a14SMatthew G. Knepley 4109412e9a14SMatthew G. Knepley PetscFunctionBegin; 4110412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4111412e9a14SMatthew G. Knepley mesh = (DM_Plex *) dm->data; 41129566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 41139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 41149566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4115412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4116327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4117412e9a14SMatthew G. Knepley PetscInt pdepth; 4118412e9a14SMatthew G. Knepley 41199566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 41209566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 412163a3b9bcSJacob Faibussowitsch PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 41229566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 4123412e9a14SMatthew G. Knepley } 41249566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState)); 41259566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view")); 4126ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4127ba2698f1SMatthew G. Knepley } 4128ba2698f1SMatthew G. Knepley 4129552f7358SJed Brown /*@C 4130552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4131552f7358SJed Brown 4132552f7358SJed Brown Not Collective 4133552f7358SJed Brown 4134552f7358SJed Brown Input Parameters: 4135552f7358SJed Brown + dm - The DMPlex object 4136552f7358SJed Brown . numPoints - The number of input points for the join 4137552f7358SJed Brown - points - The input points 4138552f7358SJed Brown 4139552f7358SJed Brown Output Parameters: 4140552f7358SJed Brown + numCoveredPoints - The number of points in the join 4141552f7358SJed Brown - coveredPoints - The points in the join 4142552f7358SJed Brown 4143552f7358SJed Brown Level: intermediate 4144552f7358SJed Brown 4145552f7358SJed Brown Note: Currently, this is restricted to a single level join 4146552f7358SJed Brown 41473813dfbdSMatthew G Knepley Fortran Notes: 41483813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 41493813dfbdSMatthew G Knepley include petsc.h90 in your code. 41503813dfbdSMatthew G Knepley 41513813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 41523813dfbdSMatthew G Knepley 4153db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4154552f7358SJed Brown @*/ 4155552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4156552f7358SJed Brown { 4157552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4158552f7358SJed Brown PetscInt *join[2]; 4159552f7358SJed Brown PetscInt joinSize, i = 0; 4160552f7358SJed Brown PetscInt dof, off, p, c, m; 41616302a7fbSVaclav Hapla PetscInt maxSupportSize; 4162552f7358SJed Brown 4163552f7358SJed Brown PetscFunctionBegin; 4164552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 416548bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 416648bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 416748bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 41686302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41696302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 41706302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4171552f7358SJed Brown /* Copy in support of first point */ 41729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 41739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4174552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4175552f7358SJed Brown join[i][joinSize] = mesh->supports[off+joinSize]; 4176552f7358SJed Brown } 4177552f7358SJed Brown /* Check each successive support */ 4178552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4179552f7358SJed Brown PetscInt newJoinSize = 0; 4180552f7358SJed Brown 41819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 41829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4183552f7358SJed Brown for (c = 0; c < dof; ++c) { 4184552f7358SJed Brown const PetscInt point = mesh->supports[off+c]; 4185552f7358SJed Brown 4186552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4187552f7358SJed Brown if (point == join[i][m]) { 4188552f7358SJed Brown join[1-i][newJoinSize++] = point; 4189552f7358SJed Brown break; 4190552f7358SJed Brown } 4191552f7358SJed Brown } 4192552f7358SJed Brown } 4193552f7358SJed Brown joinSize = newJoinSize; 4194552f7358SJed Brown i = 1-i; 4195552f7358SJed Brown } 4196552f7358SJed Brown *numCoveredPoints = joinSize; 4197552f7358SJed Brown *coveredPoints = join[i]; 41986302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1-i])); 4199552f7358SJed Brown PetscFunctionReturn(0); 4200552f7358SJed Brown } 4201552f7358SJed Brown 4202552f7358SJed Brown /*@C 4203552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4204552f7358SJed Brown 4205552f7358SJed Brown Not Collective 4206552f7358SJed Brown 4207552f7358SJed Brown Input Parameters: 4208552f7358SJed Brown + dm - The DMPlex object 4209552f7358SJed Brown . numPoints - The number of input points for the join 4210552f7358SJed Brown - points - The input points 4211552f7358SJed Brown 4212552f7358SJed Brown Output Parameters: 4213552f7358SJed Brown + numCoveredPoints - The number of points in the join 4214552f7358SJed Brown - coveredPoints - The points in the join 4215552f7358SJed Brown 42163813dfbdSMatthew G Knepley Fortran Notes: 42173813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42183813dfbdSMatthew G Knepley include petsc.h90 in your code. 42193813dfbdSMatthew G Knepley 42203813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42213813dfbdSMatthew G Knepley 4222552f7358SJed Brown Level: intermediate 4223552f7358SJed Brown 4224db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4225552f7358SJed Brown @*/ 4226552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4227552f7358SJed Brown { 4228552f7358SJed Brown PetscFunctionBegin; 4229552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4230d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4231d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4232d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 42339566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4234d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4235552f7358SJed Brown PetscFunctionReturn(0); 4236552f7358SJed Brown } 4237552f7358SJed Brown 4238552f7358SJed Brown /*@C 4239552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4240552f7358SJed Brown 4241552f7358SJed Brown Not Collective 4242552f7358SJed Brown 4243552f7358SJed Brown Input Parameters: 4244552f7358SJed Brown + dm - The DMPlex object 4245552f7358SJed Brown . numPoints - The number of input points for the join 4246552f7358SJed Brown - points - The input points 4247552f7358SJed Brown 4248552f7358SJed Brown Output Parameters: 4249552f7358SJed Brown + numCoveredPoints - The number of points in the join 4250552f7358SJed Brown - coveredPoints - The points in the join 4251552f7358SJed Brown 42523813dfbdSMatthew G Knepley Fortran Notes: 42533813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42543813dfbdSMatthew G Knepley include petsc.h90 in your code. 42553813dfbdSMatthew G Knepley 42563813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42573813dfbdSMatthew G Knepley 4258552f7358SJed Brown Level: intermediate 4259552f7358SJed Brown 4260db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4261552f7358SJed Brown @*/ 4262552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4263552f7358SJed Brown { 4264552f7358SJed Brown PetscInt *offsets, **closures; 4265552f7358SJed Brown PetscInt *join[2]; 4266552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 426724c766afSToby Isaac PetscInt p, d, c, m, ms; 4268552f7358SJed Brown 4269552f7358SJed Brown PetscFunctionBegin; 4270552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 427148bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 427248bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 427348bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 4274552f7358SJed Brown 42759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 42769566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 42779566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 42786302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 427924c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 42809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 42819566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4282552f7358SJed Brown 4283552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4284552f7358SJed Brown PetscInt closureSize; 4285552f7358SJed Brown 42869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 42870d644c17SKarl Rupp 4288552f7358SJed Brown offsets[p*(depth+2)+0] = 0; 4289552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4290552f7358SJed Brown PetscInt pStart, pEnd, i; 4291552f7358SJed Brown 42929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4293552f7358SJed Brown for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4294552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4295552f7358SJed Brown offsets[p*(depth+2)+d+1] = i; 4296552f7358SJed Brown break; 4297552f7358SJed Brown } 4298552f7358SJed Brown } 4299552f7358SJed Brown if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4300552f7358SJed Brown } 430163a3b9bcSJacob 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); 4302552f7358SJed Brown } 4303552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4304552f7358SJed Brown PetscInt dof; 4305552f7358SJed Brown 4306552f7358SJed Brown /* Copy in support of first point */ 4307552f7358SJed Brown dof = offsets[d+1] - offsets[d]; 4308552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4309552f7358SJed Brown join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4310552f7358SJed Brown } 4311552f7358SJed Brown /* Check each successive cone */ 4312552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4313552f7358SJed Brown PetscInt newJoinSize = 0; 4314552f7358SJed Brown 4315552f7358SJed Brown dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4316552f7358SJed Brown for (c = 0; c < dof; ++c) { 4317552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4318552f7358SJed Brown 4319552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4320552f7358SJed Brown if (point == join[i][m]) { 4321552f7358SJed Brown join[1-i][newJoinSize++] = point; 4322552f7358SJed Brown break; 4323552f7358SJed Brown } 4324552f7358SJed Brown } 4325552f7358SJed Brown } 4326552f7358SJed Brown joinSize = newJoinSize; 4327552f7358SJed Brown i = 1-i; 4328552f7358SJed Brown } 4329552f7358SJed Brown if (joinSize) break; 4330552f7358SJed Brown } 4331552f7358SJed Brown *numCoveredPoints = joinSize; 4332552f7358SJed Brown *coveredPoints = join[i]; 4333552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 43349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 4335552f7358SJed Brown } 43369566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 43379566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 43386302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1-i])); 4339552f7358SJed Brown PetscFunctionReturn(0); 4340552f7358SJed Brown } 4341552f7358SJed Brown 4342552f7358SJed Brown /*@C 4343552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4344552f7358SJed Brown 4345552f7358SJed Brown Not Collective 4346552f7358SJed Brown 4347552f7358SJed Brown Input Parameters: 4348552f7358SJed Brown + dm - The DMPlex object 4349552f7358SJed Brown . numPoints - The number of input points for the meet 4350552f7358SJed Brown - points - The input points 4351552f7358SJed Brown 4352552f7358SJed Brown Output Parameters: 4353552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4354552f7358SJed Brown - coveredPoints - The points in the meet 4355552f7358SJed Brown 4356552f7358SJed Brown Level: intermediate 4357552f7358SJed Brown 4358552f7358SJed Brown Note: Currently, this is restricted to a single level meet 4359552f7358SJed Brown 43603813dfbdSMatthew G Knepley Fortran Notes: 43613813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 43623813dfbdSMatthew G Knepley include petsc.h90 in your code. 43633813dfbdSMatthew G Knepley 43643813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 43653813dfbdSMatthew G Knepley 4366db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4367552f7358SJed Brown @*/ 4368552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4369552f7358SJed Brown { 4370552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4371552f7358SJed Brown PetscInt *meet[2]; 4372552f7358SJed Brown PetscInt meetSize, i = 0; 4373552f7358SJed Brown PetscInt dof, off, p, c, m; 43746302a7fbSVaclav Hapla PetscInt maxConeSize; 4375552f7358SJed Brown 4376552f7358SJed Brown PetscFunctionBegin; 4377552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4378dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4379dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveringPoints, 4); 4380064a246eSJacob Faibussowitsch PetscValidPointer(coveringPoints, 5); 43816302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 43826302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 43836302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4384552f7358SJed Brown /* Copy in cone of first point */ 43859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 43869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4387552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4388552f7358SJed Brown meet[i][meetSize] = mesh->cones[off+meetSize]; 4389552f7358SJed Brown } 4390552f7358SJed Brown /* Check each successive cone */ 4391552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4392552f7358SJed Brown PetscInt newMeetSize = 0; 4393552f7358SJed Brown 43949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 43959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4396552f7358SJed Brown for (c = 0; c < dof; ++c) { 4397552f7358SJed Brown const PetscInt point = mesh->cones[off+c]; 4398552f7358SJed Brown 4399552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4400552f7358SJed Brown if (point == meet[i][m]) { 4401552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4402552f7358SJed Brown break; 4403552f7358SJed Brown } 4404552f7358SJed Brown } 4405552f7358SJed Brown } 4406552f7358SJed Brown meetSize = newMeetSize; 4407552f7358SJed Brown i = 1-i; 4408552f7358SJed Brown } 4409552f7358SJed Brown *numCoveringPoints = meetSize; 4410552f7358SJed Brown *coveringPoints = meet[i]; 44116302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1-i])); 4412552f7358SJed Brown PetscFunctionReturn(0); 4413552f7358SJed Brown } 4414552f7358SJed Brown 4415552f7358SJed Brown /*@C 4416552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4417552f7358SJed Brown 4418552f7358SJed Brown Not Collective 4419552f7358SJed Brown 4420552f7358SJed Brown Input Parameters: 4421552f7358SJed Brown + dm - The DMPlex object 4422552f7358SJed Brown . numPoints - The number of input points for the meet 4423552f7358SJed Brown - points - The input points 4424552f7358SJed Brown 4425552f7358SJed Brown Output Parameters: 4426552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4427552f7358SJed Brown - coveredPoints - The points in the meet 4428552f7358SJed Brown 4429552f7358SJed Brown Level: intermediate 4430552f7358SJed Brown 44313813dfbdSMatthew G Knepley Fortran Notes: 44323813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44333813dfbdSMatthew G Knepley include petsc.h90 in your code. 44343813dfbdSMatthew G Knepley 44353813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44363813dfbdSMatthew G Knepley 4437db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4438552f7358SJed Brown @*/ 4439552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4440552f7358SJed Brown { 4441552f7358SJed Brown PetscFunctionBegin; 4442552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4443d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4444d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4445d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints,5); 44469566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4447d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4448552f7358SJed Brown PetscFunctionReturn(0); 4449552f7358SJed Brown } 4450552f7358SJed Brown 4451552f7358SJed Brown /*@C 4452552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4453552f7358SJed Brown 4454552f7358SJed Brown Not Collective 4455552f7358SJed Brown 4456552f7358SJed Brown Input Parameters: 4457552f7358SJed Brown + dm - The DMPlex object 4458552f7358SJed Brown . numPoints - The number of input points for the meet 4459552f7358SJed Brown - points - The input points 4460552f7358SJed Brown 4461552f7358SJed Brown Output Parameters: 4462552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4463552f7358SJed Brown - coveredPoints - The points in the meet 4464552f7358SJed Brown 4465552f7358SJed Brown Level: intermediate 4466552f7358SJed Brown 44673813dfbdSMatthew G Knepley Fortran Notes: 44683813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44693813dfbdSMatthew G Knepley include petsc.h90 in your code. 44703813dfbdSMatthew G Knepley 44713813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44723813dfbdSMatthew G Knepley 4473db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4474552f7358SJed Brown @*/ 4475552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4476552f7358SJed Brown { 4477552f7358SJed Brown PetscInt *offsets, **closures; 4478552f7358SJed Brown PetscInt *meet[2]; 4479552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 448024c766afSToby Isaac PetscInt p, h, c, m, mc; 4481552f7358SJed Brown 4482552f7358SJed Brown PetscFunctionBegin; 4483552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4484dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4485dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveredPoints, 4); 4486064a246eSJacob Faibussowitsch PetscValidPointer(coveredPoints, 5); 4487552f7358SJed Brown 44889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 44899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 44909566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 44916302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 449224c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 44939566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 44949566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4495552f7358SJed Brown 4496552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4497552f7358SJed Brown PetscInt closureSize; 4498552f7358SJed Brown 44999566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 45000d644c17SKarl Rupp 4501552f7358SJed Brown offsets[p*(height+2)+0] = 0; 4502552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4503552f7358SJed Brown PetscInt pStart, pEnd, i; 4504552f7358SJed Brown 45059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4506552f7358SJed Brown for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4507552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4508552f7358SJed Brown offsets[p*(height+2)+h+1] = i; 4509552f7358SJed Brown break; 4510552f7358SJed Brown } 4511552f7358SJed Brown } 4512552f7358SJed Brown if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4513552f7358SJed Brown } 451463a3b9bcSJacob 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); 4515552f7358SJed Brown } 4516552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4517552f7358SJed Brown PetscInt dof; 4518552f7358SJed Brown 4519552f7358SJed Brown /* Copy in cone of first point */ 4520552f7358SJed Brown dof = offsets[h+1] - offsets[h]; 4521552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4522552f7358SJed Brown meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4523552f7358SJed Brown } 4524552f7358SJed Brown /* Check each successive cone */ 4525552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4526552f7358SJed Brown PetscInt newMeetSize = 0; 4527552f7358SJed Brown 4528552f7358SJed Brown dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4529552f7358SJed Brown for (c = 0; c < dof; ++c) { 4530552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4531552f7358SJed Brown 4532552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4533552f7358SJed Brown if (point == meet[i][m]) { 4534552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4535552f7358SJed Brown break; 4536552f7358SJed Brown } 4537552f7358SJed Brown } 4538552f7358SJed Brown } 4539552f7358SJed Brown meetSize = newMeetSize; 4540552f7358SJed Brown i = 1-i; 4541552f7358SJed Brown } 4542552f7358SJed Brown if (meetSize) break; 4543552f7358SJed Brown } 4544552f7358SJed Brown *numCoveredPoints = meetSize; 4545552f7358SJed Brown *coveredPoints = meet[i]; 4546552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 45479566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 4548552f7358SJed Brown } 45499566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 45509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 45516302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1-i])); 4552552f7358SJed Brown PetscFunctionReturn(0); 4553552f7358SJed Brown } 4554552f7358SJed Brown 45554e3744c5SMatthew G. Knepley /*@C 45564e3744c5SMatthew G. Knepley DMPlexEqual - Determine if two DMs have the same topology 45574e3744c5SMatthew G. Knepley 45584e3744c5SMatthew G. Knepley Not Collective 45594e3744c5SMatthew G. Knepley 45604e3744c5SMatthew G. Knepley Input Parameters: 45614e3744c5SMatthew G. Knepley + dmA - A DMPlex object 45624e3744c5SMatthew G. Knepley - dmB - A DMPlex object 45634e3744c5SMatthew G. Knepley 45644e3744c5SMatthew G. Knepley Output Parameters: 45654e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical 45664e3744c5SMatthew G. Knepley 45674e3744c5SMatthew G. Knepley Level: intermediate 45684e3744c5SMatthew G. Knepley 45694e3744c5SMatthew G. Knepley Notes: 45704e3744c5SMatthew G. Knepley We are not solving graph isomorphism, so we do not permutation. 45714e3744c5SMatthew G. Knepley 4572db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 45734e3744c5SMatthew G. Knepley @*/ 45744e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 45754e3744c5SMatthew G. Knepley { 45764e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 45774e3744c5SMatthew G. Knepley 45784e3744c5SMatthew G. Knepley PetscFunctionBegin; 45794e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 45804e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4581dadcf809SJacob Faibussowitsch PetscValidBoolPointer(equal, 3); 45824e3744c5SMatthew G. Knepley 45834e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 45849566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 45859566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 45864e3744c5SMatthew G. Knepley if (depth != depthB) PetscFunctionReturn(0); 45879566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 45889566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 45894e3744c5SMatthew G. Knepley if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 45904e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 45914e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 45924e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 45934e3744c5SMatthew G. Knepley 45949566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 45959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 45969566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 45979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 45989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 45999566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 46004e3744c5SMatthew G. Knepley if (coneSize != coneSizeB) PetscFunctionReturn(0); 46014e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 46024e3744c5SMatthew G. Knepley if (cone[c] != coneB[c]) PetscFunctionReturn(0); 46034e3744c5SMatthew G. Knepley if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 46044e3744c5SMatthew G. Knepley } 46059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 46069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 46079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 46089566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 46094e3744c5SMatthew G. Knepley if (supportSize != supportSizeB) PetscFunctionReturn(0); 46104e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 46114e3744c5SMatthew G. Knepley if (support[s] != supportB[s]) PetscFunctionReturn(0); 46124e3744c5SMatthew G. Knepley } 46134e3744c5SMatthew G. Knepley } 46144e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 46154e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 46164e3744c5SMatthew G. Knepley } 46174e3744c5SMatthew G. Knepley 46187cd05799SMatthew G. Knepley /*@C 46197cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 46207cd05799SMatthew G. Knepley 46217cd05799SMatthew G. Knepley Not Collective 46227cd05799SMatthew G. Knepley 46237cd05799SMatthew G. Knepley Input Parameters: 46247cd05799SMatthew G. Knepley + dm - The DMPlex 46257cd05799SMatthew G. Knepley . cellDim - The cell dimension 46267cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 46277cd05799SMatthew G. Knepley 46287cd05799SMatthew G. Knepley Output Parameters: 46297cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 46307cd05799SMatthew G. Knepley 46317cd05799SMatthew G. Knepley Level: developer 46327cd05799SMatthew G. Knepley 46337cd05799SMatthew G. Knepley Notes: 46347cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 46357cd05799SMatthew G. Knepley 4636db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 46377cd05799SMatthew G. Knepley @*/ 463818ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4639a6dfd86eSKarl Rupp { 464082f516ccSBarry Smith MPI_Comm comm; 4641552f7358SJed Brown 4642552f7358SJed Brown PetscFunctionBegin; 46439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm,&comm)); 4644dadcf809SJacob Faibussowitsch PetscValidIntPointer(numFaceVertices,4); 4645552f7358SJed Brown switch (cellDim) { 4646552f7358SJed Brown case 0: 4647552f7358SJed Brown *numFaceVertices = 0; 4648552f7358SJed Brown break; 4649552f7358SJed Brown case 1: 4650552f7358SJed Brown *numFaceVertices = 1; 4651552f7358SJed Brown break; 4652552f7358SJed Brown case 2: 4653552f7358SJed Brown switch (numCorners) { 465419436ca2SJed Brown case 3: /* triangle */ 465519436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4656552f7358SJed Brown break; 465719436ca2SJed Brown case 4: /* quadrilateral */ 465819436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4659552f7358SJed Brown break; 466019436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 466119436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4662552f7358SJed Brown break; 466319436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 466419436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4665552f7358SJed Brown break; 4666552f7358SJed Brown default: 466763a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4668552f7358SJed Brown } 4669552f7358SJed Brown break; 4670552f7358SJed Brown case 3: 4671552f7358SJed Brown switch (numCorners) { 467219436ca2SJed Brown case 4: /* tetradehdron */ 467319436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 4674552f7358SJed Brown break; 467519436ca2SJed Brown case 6: /* tet cohesive cells */ 467619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4677552f7358SJed Brown break; 467819436ca2SJed Brown case 8: /* hexahedron */ 467919436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4680552f7358SJed Brown break; 468119436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 468219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4683552f7358SJed Brown break; 468419436ca2SJed Brown case 10: /* quadratic tetrahedron */ 468519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4686552f7358SJed Brown break; 468719436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 468819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4689552f7358SJed Brown break; 469019436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 469119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4692552f7358SJed Brown break; 469319436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 469419436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 4695552f7358SJed Brown break; 4696552f7358SJed Brown default: 469763a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4698552f7358SJed Brown } 4699552f7358SJed Brown break; 4700552f7358SJed Brown default: 470163a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 4702552f7358SJed Brown } 4703552f7358SJed Brown PetscFunctionReturn(0); 4704552f7358SJed Brown } 4705552f7358SJed Brown 4706552f7358SJed Brown /*@ 4707aa50250dSMatthew G. Knepley DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4708552f7358SJed Brown 4709552f7358SJed Brown Not Collective 4710552f7358SJed Brown 4711aa50250dSMatthew G. Knepley Input Parameter: 4712552f7358SJed Brown . dm - The DMPlex object 4713552f7358SJed Brown 4714aa50250dSMatthew G. Knepley Output Parameter: 4715aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth 4716552f7358SJed Brown 4717552f7358SJed Brown Level: developer 4718552f7358SJed Brown 4719db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 4720aa50250dSMatthew G. Knepley @*/ 4721aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4722aa50250dSMatthew G. Knepley { 4723aa50250dSMatthew G. Knepley PetscFunctionBegin; 4724aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4725aa50250dSMatthew G. Knepley PetscValidPointer(depthLabel, 2); 4726c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 4727aa50250dSMatthew G. Knepley PetscFunctionReturn(0); 4728aa50250dSMatthew G. Knepley } 4729aa50250dSMatthew G. Knepley 4730aa50250dSMatthew G. Knepley /*@ 4731aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 4732aa50250dSMatthew G. Knepley 4733aa50250dSMatthew G. Knepley Not Collective 4734aa50250dSMatthew G. Knepley 4735aa50250dSMatthew G. Knepley Input Parameter: 4736aa50250dSMatthew G. Knepley . dm - The DMPlex object 4737aa50250dSMatthew G. Knepley 4738aa50250dSMatthew G. Knepley Output Parameter: 4739aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 4740aa50250dSMatthew G. Knepley 4741aa50250dSMatthew G. Knepley Level: developer 4742552f7358SJed Brown 4743b1bb481bSMatthew Knepley Notes: 4744b1bb481bSMatthew Knepley This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4745dc287ab2SVaclav Hapla The point depth is described more in detail in DMPlexGetDepthStratum(). 4746dc287ab2SVaclav Hapla An empty mesh gives -1. 4747b1bb481bSMatthew Knepley 4748db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 4749552f7358SJed Brown @*/ 4750552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4751552f7358SJed Brown { 4752aa50250dSMatthew G. Knepley DMLabel label; 4753aa50250dSMatthew G. Knepley PetscInt d = 0; 4754552f7358SJed Brown 4755552f7358SJed Brown PetscFunctionBegin; 4756552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4757dadcf809SJacob Faibussowitsch PetscValidIntPointer(depth, 2); 47589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 47599566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 4760552f7358SJed Brown *depth = d-1; 4761552f7358SJed Brown PetscFunctionReturn(0); 4762552f7358SJed Brown } 4763552f7358SJed Brown 4764552f7358SJed Brown /*@ 4765552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4766552f7358SJed Brown 4767552f7358SJed Brown Not Collective 4768552f7358SJed Brown 4769552f7358SJed Brown Input Parameters: 4770552f7358SJed Brown + dm - The DMPlex object 4771570fa34dSVaclav Hapla - depth - The requested depth 4772552f7358SJed Brown 4773552f7358SJed Brown Output Parameters: 4774552f7358SJed Brown + start - The first point at this depth 4775552f7358SJed Brown - end - One beyond the last point at this depth 4776552f7358SJed Brown 4777647867b2SJed Brown Notes: 4778647867b2SJed Brown Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4779647867b2SJed Brown often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4780647867b2SJed Brown higher dimension, e.g., "edges". 4781647867b2SJed Brown 4782552f7358SJed Brown Level: developer 4783552f7358SJed Brown 4784db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 4785552f7358SJed Brown @*/ 4786570fa34dSVaclav Hapla PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 47870adebc6cSBarry Smith { 4788aa50250dSMatthew G. Knepley DMLabel label; 478963d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 4790552f7358SJed Brown 4791552f7358SJed Brown PetscFunctionBegin; 4792552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4793dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4794dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 47959566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 47960d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4797570fa34dSVaclav Hapla if (depth < 0) { 479863d1a920SMatthew G. Knepley if (start) *start = pStart; 479963d1a920SMatthew G. Knepley if (end) *end = pEnd; 480063d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4801552f7358SJed Brown } 48029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 480328b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4804570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 4805552f7358SJed Brown PetscFunctionReturn(0); 4806552f7358SJed Brown } 4807552f7358SJed Brown 4808552f7358SJed Brown /*@ 4809552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4810552f7358SJed Brown 4811552f7358SJed Brown Not Collective 4812552f7358SJed Brown 4813552f7358SJed Brown Input Parameters: 4814552f7358SJed Brown + dm - The DMPlex object 4815570fa34dSVaclav Hapla - height - The requested height 4816552f7358SJed Brown 4817552f7358SJed Brown Output Parameters: 4818552f7358SJed Brown + start - The first point at this height 4819552f7358SJed Brown - end - One beyond the last point at this height 4820552f7358SJed Brown 4821647867b2SJed Brown Notes: 4822647867b2SJed Brown Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4823647867b2SJed Brown points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4824647867b2SJed Brown stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4825647867b2SJed Brown 4826552f7358SJed Brown Level: developer 4827552f7358SJed Brown 4828db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4829552f7358SJed Brown @*/ 4830570fa34dSVaclav Hapla PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 48310adebc6cSBarry Smith { 4832aa50250dSMatthew G. Knepley DMLabel label; 483363d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 4834552f7358SJed Brown 4835552f7358SJed Brown PetscFunctionBegin; 4836552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4837dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4838dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48399566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 48400d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4841570fa34dSVaclav Hapla if (height < 0) { 484263d1a920SMatthew G. Knepley if (start) *start = pStart; 484363d1a920SMatthew G. Knepley if (end) *end = pEnd; 484463d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4845552f7358SJed Brown } 48469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 484728b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 48489566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 4849570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth-1-height, start, end)); 4850552f7358SJed Brown PetscFunctionReturn(0); 4851552f7358SJed Brown } 4852552f7358SJed Brown 4853ba2698f1SMatthew G. Knepley /*@ 4854ba2698f1SMatthew G. Knepley DMPlexGetPointDepth - Get the depth of a given point 4855ba2698f1SMatthew G. Knepley 4856ba2698f1SMatthew G. Knepley Not Collective 4857ba2698f1SMatthew G. Knepley 4858d8d19677SJose E. Roman Input Parameters: 4859ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4860ba2698f1SMatthew G. Knepley - point - The point 4861ba2698f1SMatthew G. Knepley 4862ba2698f1SMatthew G. Knepley Output Parameter: 4863ba2698f1SMatthew G. Knepley . depth - The depth of the point 4864ba2698f1SMatthew G. Knepley 4865ba2698f1SMatthew G. Knepley Level: intermediate 4866ba2698f1SMatthew G. Knepley 4867db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4868ba2698f1SMatthew G. Knepley @*/ 4869ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4870ba2698f1SMatthew G. Knepley { 4871ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4872ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 487340a2aa30SMatthew G. Knepley PetscValidIntPointer(depth, 3); 48749566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 4875ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4876ba2698f1SMatthew G. Knepley } 4877ba2698f1SMatthew G. Knepley 4878ba2698f1SMatthew G. Knepley /*@ 48790c0a32dcSVaclav Hapla DMPlexGetPointHeight - Get the height of a given point 48800c0a32dcSVaclav Hapla 48810c0a32dcSVaclav Hapla Not Collective 48820c0a32dcSVaclav Hapla 4883d8d19677SJose E. Roman Input Parameters: 48840c0a32dcSVaclav Hapla + dm - The DMPlex object 48850c0a32dcSVaclav Hapla - point - The point 48860c0a32dcSVaclav Hapla 48870c0a32dcSVaclav Hapla Output Parameter: 48880c0a32dcSVaclav Hapla . height - The height of the point 48890c0a32dcSVaclav Hapla 48900c0a32dcSVaclav Hapla Level: intermediate 48910c0a32dcSVaclav Hapla 4892db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 48930c0a32dcSVaclav Hapla @*/ 48940c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 48950c0a32dcSVaclav Hapla { 48960c0a32dcSVaclav Hapla PetscInt n, pDepth; 48970c0a32dcSVaclav Hapla 48980c0a32dcSVaclav Hapla PetscFunctionBegin; 48990c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49000c0a32dcSVaclav Hapla PetscValidIntPointer(height, 3); 49019566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 49029566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 49030c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 49040c0a32dcSVaclav Hapla PetscFunctionReturn(0); 49050c0a32dcSVaclav Hapla } 49060c0a32dcSVaclav Hapla 49070c0a32dcSVaclav Hapla /*@ 4908ba2698f1SMatthew G. Knepley DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4909ba2698f1SMatthew G. Knepley 4910ba2698f1SMatthew G. Knepley Not Collective 4911ba2698f1SMatthew G. Knepley 4912ba2698f1SMatthew G. Knepley Input Parameter: 4913ba2698f1SMatthew G. Knepley . dm - The DMPlex object 4914ba2698f1SMatthew G. Knepley 4915ba2698f1SMatthew G. Knepley Output Parameter: 4916ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type 4917ba2698f1SMatthew G. Knepley 4918412e9a14SMatthew G. Knepley Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4919412e9a14SMatthew G. Knepley DMCreateLabel(dm, "celltype") beforehand. 4920412e9a14SMatthew G. Knepley 4921ba2698f1SMatthew G. Knepley Level: developer 4922ba2698f1SMatthew G. Knepley 4923db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 4924ba2698f1SMatthew G. Knepley @*/ 4925ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4926ba2698f1SMatthew G. Knepley { 4927ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4928ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4929ba2698f1SMatthew G. Knepley PetscValidPointer(celltypeLabel, 2); 49309566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 4931ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 4932ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4933ba2698f1SMatthew G. Knepley } 4934ba2698f1SMatthew G. Knepley 4935ba2698f1SMatthew G. Knepley /*@ 4936ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 4937ba2698f1SMatthew G. Knepley 4938ba2698f1SMatthew G. Knepley Not Collective 4939ba2698f1SMatthew G. Knepley 4940d8d19677SJose E. Roman Input Parameters: 4941ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4942ba2698f1SMatthew G. Knepley - cell - The cell 4943ba2698f1SMatthew G. Knepley 4944ba2698f1SMatthew G. Knepley Output Parameter: 4945ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 4946ba2698f1SMatthew G. Knepley 4947ba2698f1SMatthew G. Knepley Level: intermediate 4948ba2698f1SMatthew G. Knepley 4949db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 4950ba2698f1SMatthew G. Knepley @*/ 4951ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4952ba2698f1SMatthew G. Knepley { 4953ba2698f1SMatthew G. Knepley DMLabel label; 4954ba2698f1SMatthew G. Knepley PetscInt ct; 4955ba2698f1SMatthew G. Knepley 4956ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4957ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4958ba2698f1SMatthew G. Knepley PetscValidPointer(celltype, 3); 49599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 49609566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 496163a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 4962ba2698f1SMatthew G. Knepley *celltype = (DMPolytopeType) ct; 4963ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4964ba2698f1SMatthew G. Knepley } 4965ba2698f1SMatthew G. Knepley 4966412e9a14SMatthew G. Knepley /*@ 4967412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 4968412e9a14SMatthew G. Knepley 4969412e9a14SMatthew G. Knepley Not Collective 4970412e9a14SMatthew G. Knepley 4971412e9a14SMatthew G. Knepley Input Parameters: 4972412e9a14SMatthew G. Knepley + dm - The DMPlex object 4973412e9a14SMatthew G. Knepley . cell - The cell 4974412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 4975412e9a14SMatthew G. Knepley 4976412e9a14SMatthew G. Knepley Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4977412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 4978412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 4979412e9a14SMatthew G. Knepley DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4980412e9a14SMatthew G. Knepley 4981412e9a14SMatthew G. Knepley Level: advanced 4982412e9a14SMatthew G. Knepley 4983db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 4984412e9a14SMatthew G. Knepley @*/ 4985412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4986412e9a14SMatthew G. Knepley { 4987412e9a14SMatthew G. Knepley DMLabel label; 4988412e9a14SMatthew G. Knepley 4989412e9a14SMatthew G. Knepley PetscFunctionBegin; 4990412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 49929566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 4993412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4994412e9a14SMatthew G. Knepley } 4995412e9a14SMatthew G. Knepley 49960adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 49970adebc6cSBarry Smith { 4998efe440bfSMatthew G. Knepley PetscSection section, s; 4999efe440bfSMatthew G. Knepley Mat m; 50003e922f36SToby Isaac PetscInt maxHeight; 5001552f7358SJed Brown 5002552f7358SJed Brown PetscFunctionBegin; 50039566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 50049566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 50059566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 50069566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 50079566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 50089566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 50099566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 50109566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 50119566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 50129566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 50139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 50148f4c458bSMatthew G. Knepley 50159566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 50169566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5017552f7358SJed Brown PetscFunctionReturn(0); 5018552f7358SJed Brown } 5019552f7358SJed Brown 5020f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5021f19dbd58SToby Isaac { 5022f19dbd58SToby Isaac Vec coordsLocal; 5023f19dbd58SToby Isaac DM coordsDM; 5024f19dbd58SToby Isaac 5025f19dbd58SToby Isaac PetscFunctionBegin; 5026f19dbd58SToby Isaac *field = NULL; 50279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm,&coordsLocal)); 50289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm,&coordsDM)); 5029f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 50309566063dSJacob Faibussowitsch PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5031f19dbd58SToby Isaac } 5032f19dbd58SToby Isaac PetscFunctionReturn(0); 5033f19dbd58SToby Isaac } 5034f19dbd58SToby Isaac 50357cd05799SMatthew G. Knepley /*@C 50367cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 50377cd05799SMatthew G. Knepley 50387cd05799SMatthew G. Knepley Not Collective 50397cd05799SMatthew G. Knepley 50407cd05799SMatthew G. Knepley Input Parameters: 50417cd05799SMatthew G. Knepley . dm - The DMPlex object 50427cd05799SMatthew G. Knepley 50437cd05799SMatthew G. Knepley Output Parameter: 50447cd05799SMatthew G. Knepley . section - The PetscSection object 50457cd05799SMatthew G. Knepley 50467cd05799SMatthew G. Knepley Level: developer 50477cd05799SMatthew G. Knepley 5048db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()` 50497cd05799SMatthew G. Knepley @*/ 50500adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 50510adebc6cSBarry Smith { 5052552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5053552f7358SJed Brown 5054552f7358SJed Brown PetscFunctionBegin; 5055552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5056552f7358SJed Brown if (section) *section = mesh->coneSection; 5057552f7358SJed Brown PetscFunctionReturn(0); 5058552f7358SJed Brown } 5059552f7358SJed Brown 50607cd05799SMatthew G. Knepley /*@C 50617cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 50627cd05799SMatthew G. Knepley 50637cd05799SMatthew G. Knepley Not Collective 50647cd05799SMatthew G. Knepley 50657cd05799SMatthew G. Knepley Input Parameters: 50667cd05799SMatthew G. Knepley . dm - The DMPlex object 50677cd05799SMatthew G. Knepley 50687cd05799SMatthew G. Knepley Output Parameter: 50697cd05799SMatthew G. Knepley . section - The PetscSection object 50707cd05799SMatthew G. Knepley 50717cd05799SMatthew G. Knepley Level: developer 50727cd05799SMatthew G. Knepley 5073db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 50747cd05799SMatthew G. Knepley @*/ 50758cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 50768cb4d582SMatthew G. Knepley { 50778cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 50788cb4d582SMatthew G. Knepley 50798cb4d582SMatthew G. Knepley PetscFunctionBegin; 50808cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50818cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 50828cb4d582SMatthew G. Knepley PetscFunctionReturn(0); 50838cb4d582SMatthew G. Knepley } 50848cb4d582SMatthew G. Knepley 50857cd05799SMatthew G. Knepley /*@C 50867cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 50877cd05799SMatthew G. Knepley 50887cd05799SMatthew G. Knepley Not Collective 50897cd05799SMatthew G. Knepley 50907cd05799SMatthew G. Knepley Input Parameters: 50917cd05799SMatthew G. Knepley . dm - The DMPlex object 50927cd05799SMatthew G. Knepley 50937cd05799SMatthew G. Knepley Output Parameter: 50947cd05799SMatthew G. Knepley . cones - The cone for each point 50957cd05799SMatthew G. Knepley 50967cd05799SMatthew G. Knepley Level: developer 50977cd05799SMatthew G. Knepley 5098db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 50997cd05799SMatthew G. Knepley @*/ 5100a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5101a6dfd86eSKarl Rupp { 5102552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5103552f7358SJed Brown 5104552f7358SJed Brown PetscFunctionBegin; 5105552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5106552f7358SJed Brown if (cones) *cones = mesh->cones; 5107552f7358SJed Brown PetscFunctionReturn(0); 5108552f7358SJed Brown } 5109552f7358SJed Brown 51107cd05799SMatthew G. Knepley /*@C 51117cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 51127cd05799SMatthew G. Knepley 51137cd05799SMatthew G. Knepley Not Collective 51147cd05799SMatthew G. Knepley 51157cd05799SMatthew G. Knepley Input Parameters: 51167cd05799SMatthew G. Knepley . dm - The DMPlex object 51177cd05799SMatthew G. Knepley 51187cd05799SMatthew G. Knepley Output Parameter: 5119b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 51207cd05799SMatthew G. Knepley 51217cd05799SMatthew G. Knepley Level: developer 51227cd05799SMatthew G. Knepley 5123b5a892a1SMatthew G. Knepley Notes: 5124b5a892a1SMatthew G. Knepley The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5125b5a892a1SMatthew G. Knepley 5126b5a892a1SMatthew G. Knepley The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5127b5a892a1SMatthew G. Knepley 5128db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()` 51297cd05799SMatthew G. Knepley @*/ 5130a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5131a6dfd86eSKarl Rupp { 5132552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5133552f7358SJed Brown 5134552f7358SJed Brown PetscFunctionBegin; 5135552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5136552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5137552f7358SJed Brown PetscFunctionReturn(0); 5138552f7358SJed Brown } 5139552f7358SJed Brown 5140552f7358SJed Brown /******************************** FEM Support **********************************/ 5141552f7358SJed Brown 51429e8305c2SJed Brown /* 51439e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 51449e8305c2SJed Brown representing a line in the section. 51459e8305c2SJed Brown */ 51469e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 51479e8305c2SJed Brown { 51489e8305c2SJed Brown PetscFunctionBeginHot; 51499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5150a433471fSStefano Zampini if (line < 0) { 5151a433471fSStefano Zampini *k = 0; 5152a433471fSStefano Zampini *Nc = 0; 5153a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 51549e8305c2SJed Brown *k = 1; 51559e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 51569e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 51579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 51589e8305c2SJed Brown *k = *k / *Nc + 1; 51599e8305c2SJed Brown } 51609e8305c2SJed Brown PetscFunctionReturn(0); 51619e8305c2SJed Brown } 51629e8305c2SJed Brown 5163a4355906SMatthew Knepley /*@ 5164bc1eb3faSJed Brown 5165bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5166bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 51671bb6d2a8SBarry Smith section provided (or the section of the DM). 5168a4355906SMatthew Knepley 5169a4355906SMatthew Knepley Input Parameters: 5170a4355906SMatthew Knepley + dm - The DM 5171a4355906SMatthew Knepley . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5172a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section 5173a4355906SMatthew Knepley 5174a4355906SMatthew Knepley Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5175a4355906SMatthew Knepley degree of the basis. 5176a4355906SMatthew Knepley 5177bc1eb3faSJed Brown Example: 5178bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5179bc1eb3faSJed Brown .vb 5180bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5181bc1eb3faSJed Brown 5182bc1eb3faSJed Brown v4 -- e6 -- v3 5183bc1eb3faSJed Brown | | 5184bc1eb3faSJed Brown e7 c0 e8 5185bc1eb3faSJed Brown | | 5186bc1eb3faSJed Brown v1 -- e5 -- v2 5187bc1eb3faSJed Brown .ve 5188bc1eb3faSJed Brown 5189bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5190bc1eb3faSJed Brown dofs in the order of points, e.g., 5191bc1eb3faSJed Brown .vb 5192bc1eb3faSJed Brown c0 -> [0,1,2,3] 5193bc1eb3faSJed Brown v1 -> [4] 5194bc1eb3faSJed Brown ... 5195bc1eb3faSJed Brown e5 -> [8, 9] 5196bc1eb3faSJed Brown .ve 5197bc1eb3faSJed Brown 5198bc1eb3faSJed Brown which corresponds to the dofs 5199bc1eb3faSJed Brown .vb 5200bc1eb3faSJed Brown 6 10 11 7 5201bc1eb3faSJed Brown 13 2 3 15 5202bc1eb3faSJed Brown 12 0 1 14 5203bc1eb3faSJed Brown 4 8 9 5 5204bc1eb3faSJed Brown .ve 5205bc1eb3faSJed Brown 5206bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5207bc1eb3faSJed Brown .vb 5208bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5209bc1eb3faSJed Brown .ve 5210bc1eb3faSJed Brown 5211bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5212bc1eb3faSJed Brown .vb 5213bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5214bc1eb3faSJed Brown .ve 5215bc1eb3faSJed Brown 5216a4355906SMatthew Knepley Level: developer 5217a4355906SMatthew Knepley 5218db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5219a4355906SMatthew Knepley @*/ 5220bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 52213194fc30SMatthew G. Knepley { 52227391a63aSMatthew G. Knepley DMLabel label; 5223bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 52249e8305c2SJed Brown PetscBool vertexchart; 52253194fc30SMatthew G. Knepley 52263194fc30SMatthew G. Knepley PetscFunctionBegin; 52279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5228a433471fSStefano Zampini if (dim < 1) PetscFunctionReturn(0); 5229a433471fSStefano Zampini if (point < 0) { 5230a433471fSStefano Zampini PetscInt sStart,sEnd; 5231a433471fSStefano Zampini 52329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5233a433471fSStefano Zampini point = sEnd-sStart ? sStart : point; 5234a433471fSStefano Zampini } 52359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52369566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 52379566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 52387391a63aSMatthew G. Knepley if (depth == 1) {eStart = point;} 52397391a63aSMatthew G. Knepley else if (depth == dim) { 52407391a63aSMatthew G. Knepley const PetscInt *cone; 52417391a63aSMatthew G. Knepley 52429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5243d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5244d4e6627bSStefano Zampini else if (dim == 3) { 5245d4e6627bSStefano Zampini const PetscInt *cone2; 52469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5247d4e6627bSStefano Zampini eStart = cone2[0]; 524863a3b9bcSJacob 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); 524963a3b9bcSJacob 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); 52509e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 52519e8305c2SJed Brown PetscInt pStart,pEnd,cStart,cEnd; 52529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd)); 52539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&cStart,&cEnd)); 5254796d0a68SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5255796d0a68SJed Brown else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5256796d0a68SJed Brown else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 52579e8305c2SJed Brown } 52589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5259bb197d40SJed Brown for (PetscInt d=1; d<=dim; d++) { 5260bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5261bb197d40SJed Brown PetscInt *perm; 5262bb197d40SJed Brown 52633194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 52649566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5265bb197d40SJed Brown size += PetscPowInt(k+1, d)*Nc; 52663194fc30SMatthew G. Knepley } 52679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 52683194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5269bb197d40SJed Brown switch (d) { 5270babf31e0SJed Brown case 1: 52719566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5272babf31e0SJed Brown /* 5273babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5274babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5275babf31e0SJed Brown */ 5276babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5277babf31e0SJed Brown for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5278babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5279babf31e0SJed Brown foffset = offset; 5280babf31e0SJed Brown break; 528189eabcffSMatthew G. Knepley case 2: 52823194fc30SMatthew 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} */ 52839566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 52843194fc30SMatthew G. Knepley /* The SEM order is 52853194fc30SMatthew G. Knepley 52863194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 528789eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 52883194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 52893194fc30SMatthew G. Knepley */ 52903194fc30SMatthew G. Knepley { 52913194fc30SMatthew G. Knepley const PetscInt of = 0; 52923194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k-1); 52933194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k-1); 52943194fc30SMatthew G. Knepley const PetscInt oet = oer + (k-1); 52953194fc30SMatthew G. Knepley const PetscInt oel = oet + (k-1); 52963194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k-1); 52973194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 52983194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 52993194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 53003194fc30SMatthew G. Knepley PetscInt o; 53013194fc30SMatthew G. Knepley 53023194fc30SMatthew G. Knepley /* bottom */ 53033194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 53043194fc30SMatthew G. Knepley for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53053194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 53063194fc30SMatthew G. Knepley /* middle */ 53073194fc30SMatthew G. Knepley for (i = 0; i < k-1; ++i) { 53083194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 53093194fc30SMatthew 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; 53103194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 53113194fc30SMatthew G. Knepley } 53123194fc30SMatthew G. Knepley /* top */ 53133194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 53143194fc30SMatthew G. Knepley for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53153194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 53163194fc30SMatthew G. Knepley foffset = offset; 53173194fc30SMatthew G. Knepley } 531889eabcffSMatthew G. Knepley break; 531989eabcffSMatthew G. Knepley case 3: 532089eabcffSMatthew G. Knepley /* The original hex closure is 532189eabcffSMatthew G. Knepley 532289eabcffSMatthew G. Knepley {c, 532389eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 532489eabcffSMatthew 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, 532589eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 532689eabcffSMatthew G. Knepley */ 53279566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 532889eabcffSMatthew G. Knepley /* The SEM order is 532989eabcffSMatthew G. Knepley Bottom Slice 533089eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 533189eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 533289eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 533389eabcffSMatthew G. Knepley 533489eabcffSMatthew G. Knepley Middle Slice (j) 533589eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 533689eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 533789eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 533889eabcffSMatthew G. Knepley 533989eabcffSMatthew G. Knepley Top Slice 534089eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 534189eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 534289eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 534389eabcffSMatthew G. Knepley */ 534489eabcffSMatthew G. Knepley { 534589eabcffSMatthew G. Knepley const PetscInt oc = 0; 534689eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 534789eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k-1); 534889eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k-1); 534989eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k-1); 535089eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k-1); 535189eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k-1); 535289eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k-1); 535389eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k-1); 535489eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k-1); 535589eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k-1); 535689eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k-1); 535789eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k-1); 535889eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k-1); 535989eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k-1); 536089eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k-1); 536189eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k-1); 536289eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k-1); 536389eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k-1); 536489eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k-1); 536589eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 536689eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 536789eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 536889eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 536989eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 537089eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 537189eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 537289eabcffSMatthew G. Knepley PetscInt o, n; 537389eabcffSMatthew G. Knepley 537489eabcffSMatthew G. Knepley /* Bottom Slice */ 537589eabcffSMatthew G. Knepley /* bottom */ 537689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 537789eabcffSMatthew G. Knepley for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 537889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 537989eabcffSMatthew G. Knepley /* middle */ 538089eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 538189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5382316b7f87SMax 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;} 538389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 53843194fc30SMatthew G. Knepley } 538589eabcffSMatthew G. Knepley /* top */ 538689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 538789eabcffSMatthew G. Knepley for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 538889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 538989eabcffSMatthew G. Knepley 539089eabcffSMatthew G. Knepley /* Middle Slice */ 539189eabcffSMatthew G. Knepley for (j = 0; j < k-1; ++j) { 539289eabcffSMatthew G. Knepley /* bottom */ 539389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 539489eabcffSMatthew 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; 539589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 539689eabcffSMatthew G. Knepley /* middle */ 539789eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 539889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 539989eabcffSMatthew 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; 540089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 540189eabcffSMatthew G. Knepley } 540289eabcffSMatthew G. Knepley /* top */ 540389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 540489eabcffSMatthew 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; 540589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 540689eabcffSMatthew G. Knepley } 540789eabcffSMatthew G. Knepley 540889eabcffSMatthew G. Knepley /* Top Slice */ 540989eabcffSMatthew G. Knepley /* bottom */ 541089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 541189eabcffSMatthew G. Knepley for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 541289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 541389eabcffSMatthew G. Knepley /* middle */ 541489eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 541589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 541689eabcffSMatthew 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; 541789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 541889eabcffSMatthew G. Knepley } 541989eabcffSMatthew G. Knepley /* top */ 542089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 542189eabcffSMatthew G. Knepley for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 542289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 542389eabcffSMatthew G. Knepley 542489eabcffSMatthew G. Knepley foffset = offset; 542589eabcffSMatthew G. Knepley } 542689eabcffSMatthew G. Knepley break; 542763a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 542889eabcffSMatthew G. Knepley } 542989eabcffSMatthew G. Knepley } 543063a3b9bcSJacob Faibussowitsch PetscCheck(offset == size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 54313194fc30SMatthew G. Knepley /* Check permutation */ 54323194fc30SMatthew G. Knepley { 54333194fc30SMatthew G. Knepley PetscInt *check; 54343194fc30SMatthew G. Knepley 54359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 54361dca8a05SBarry Smith for (i = 0; i < size; ++i) { 54371dca8a05SBarry Smith check[i] = -1; 54381dca8a05SBarry 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]); 54391dca8a05SBarry Smith } 54403194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 54411dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 54429566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 54433194fc30SMatthew G. Knepley } 54449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm)); 5445a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5446a05c9aa3SJed Brown PetscInt *loc_perm; 54479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size*2, &loc_perm)); 5448a05c9aa3SJed Brown for (PetscInt i=0; i<size; i++) { 5449a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5450a05c9aa3SJed Brown loc_perm[size+i] = size + perm[i]; 5451a05c9aa3SJed Brown } 54529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm)); 5453a05c9aa3SJed Brown } 5454bb197d40SJed Brown } 54553194fc30SMatthew G. Knepley PetscFunctionReturn(0); 54563194fc30SMatthew G. Knepley } 54573194fc30SMatthew G. Knepley 5458e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5459e071409bSToby Isaac { 5460e071409bSToby Isaac PetscDS prob; 5461e071409bSToby Isaac PetscInt depth, Nf, h; 5462e071409bSToby Isaac DMLabel label; 5463e071409bSToby Isaac 5464e071409bSToby Isaac PetscFunctionBeginHot; 54659566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 5466e071409bSToby Isaac Nf = prob->Nf; 5467e071409bSToby Isaac label = dm->depthLabel; 5468e071409bSToby Isaac *dspace = NULL; 5469e071409bSToby Isaac if (field < Nf) { 5470e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5471e071409bSToby Isaac 5472e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5473e071409bSToby Isaac PetscDualSpace dsp; 5474e071409bSToby Isaac 54759566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp)); 54769566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label,&depth)); 54779566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label,point,&h)); 5478e071409bSToby Isaac h = depth - 1 - h; 5479e071409bSToby Isaac if (h) { 54809566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp,h,dspace)); 5481e071409bSToby Isaac } else { 5482e071409bSToby Isaac *dspace = dsp; 5483e071409bSToby Isaac } 5484e071409bSToby Isaac } 5485e071409bSToby Isaac } 5486e071409bSToby Isaac PetscFunctionReturn(0); 5487e071409bSToby Isaac } 5488e071409bSToby Isaac 54899fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5490a6dfd86eSKarl Rupp { 5491552f7358SJed Brown PetscScalar *array, *vArray; 5492d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 54931a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5494552f7358SJed Brown 54951b406b76SMatthew G. Knepley PetscFunctionBeginHot; 54969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 54979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 54989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 54999566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 55003f7cbbe7SMatthew G. Knepley if (!values || !*values) { 55019df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55029df71ca4SMatthew G. Knepley PetscInt dof; 5503d9917b9dSMatthew G. Knepley 55049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55059df71ca4SMatthew G. Knepley size += dof; 55069df71ca4SMatthew G. Knepley } 55079df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55089df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55092a3aaacfSMatthew G. Knepley PetscInt dof; 55105a1bb5cfSMatthew G. Knepley 55115a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55135a1bb5cfSMatthew G. Knepley size += dof; 55145a1bb5cfSMatthew G. Knepley } 55153f7cbbe7SMatthew G. Knepley if (!values) { 55163f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 55173f7cbbe7SMatthew G. Knepley PetscFunctionReturn(0); 55183f7cbbe7SMatthew G. Knepley } 55199566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 5520982e9ed1SMatthew G. Knepley } else { 5521982e9ed1SMatthew G. Knepley array = *values; 5522982e9ed1SMatthew G. Knepley } 55239df71ca4SMatthew G. Knepley size = 0; 55249566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &vArray)); 55259df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55269df71ca4SMatthew G. Knepley PetscInt dof, off, d; 55279df71ca4SMatthew G. Knepley PetscScalar *varr; 5528d9917b9dSMatthew G. Knepley 55299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 55319df71ca4SMatthew G. Knepley varr = &vArray[off]; 55321a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55331a271a75SMatthew G. Knepley array[offset] = varr[d]; 55349df71ca4SMatthew G. Knepley } 55359df71ca4SMatthew G. Knepley size += dof; 55369df71ca4SMatthew G. Knepley } 55379df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55389df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55399df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 55405a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 55415a1bb5cfSMatthew G. Knepley PetscScalar *varr; 55425a1bb5cfSMatthew G. Knepley 554352ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 55465a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 55475a1bb5cfSMatthew G. Knepley if (o >= 0) { 55481a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55491a271a75SMatthew G. Knepley array[offset] = varr[d]; 55505a1bb5cfSMatthew G. Knepley } 55515a1bb5cfSMatthew G. Knepley } else { 55521a271a75SMatthew G. Knepley for (d = dof-1; d >= 0; --d, ++offset) { 55531a271a75SMatthew G. Knepley array[offset] = varr[d]; 55545a1bb5cfSMatthew G. Knepley } 55555a1bb5cfSMatthew G. Knepley } 55569df71ca4SMatthew G. Knepley size += dof; 55575a1bb5cfSMatthew G. Knepley } 55589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &vArray)); 55599df71ca4SMatthew G. Knepley if (!*values) { 55605a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 55615a1bb5cfSMatthew G. Knepley *values = array; 55629df71ca4SMatthew G. Knepley } else { 556363a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 55648c312ff3SMatthew G. Knepley *csize = size; 55659df71ca4SMatthew G. Knepley } 55665a1bb5cfSMatthew G. Knepley PetscFunctionReturn(0); 55675a1bb5cfSMatthew G. Knepley } 5568d9917b9dSMatthew G. Knepley 556927f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 55709fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 557127f02ce8SMatthew G. Knepley { 557227f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 557327f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 557427f02ce8SMatthew G. Knepley 55759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 557627f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 557727f02ce8SMatthew G. Knepley const PetscInt r = points[p*2]; 557827f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 557927f02ce8SMatthew G. Knepley points[q*2] = r; 558027f02ce8SMatthew G. Knepley points[q*2+1] = points[p*2+1]; 558127f02ce8SMatthew G. Knepley ++q; 558227f02ce8SMatthew G. Knepley } 558327f02ce8SMatthew G. Knepley } 558427f02ce8SMatthew G. Knepley *numPoints = q; 558527f02ce8SMatthew G. Knepley return 0; 558627f02ce8SMatthew G. Knepley } 558727f02ce8SMatthew G. Knepley 558897529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 55891dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5590923c78e0SToby Isaac { 559127f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 5592923c78e0SToby Isaac PetscInt np, *pts = NULL; 5593923c78e0SToby Isaac 5594923c78e0SToby Isaac PetscFunctionBeginHot; 55959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints)); 559627f02ce8SMatthew G. Knepley if (*clPoints) { 5597923c78e0SToby Isaac PetscInt dof, off; 5598923c78e0SToby Isaac 55999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 56009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 56019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 5602923c78e0SToby Isaac np = dof/2; 5603923c78e0SToby Isaac pts = (PetscInt *) &cla[off]; 560427f02ce8SMatthew G. Knepley } else { 56059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts)); 56069566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 5607923c78e0SToby Isaac } 5608923c78e0SToby Isaac *numPoints = np; 5609923c78e0SToby Isaac *points = pts; 5610923c78e0SToby Isaac *clp = cla; 5611923c78e0SToby Isaac PetscFunctionReturn(0); 5612923c78e0SToby Isaac } 5613923c78e0SToby Isaac 56141dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5615923c78e0SToby Isaac { 5616923c78e0SToby Isaac PetscFunctionBeginHot; 5617923c78e0SToby Isaac if (!*clPoints) { 56189566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 5619923c78e0SToby Isaac } else { 56209566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 5621923c78e0SToby Isaac } 5622923c78e0SToby Isaac *numPoints = 0; 5623923c78e0SToby Isaac *points = NULL; 5624923c78e0SToby Isaac *clSec = NULL; 5625923c78e0SToby Isaac *clPoints = NULL; 5626923c78e0SToby Isaac *clp = NULL; 5627923c78e0SToby Isaac PetscFunctionReturn(0); 5628923c78e0SToby Isaac } 5629923c78e0SToby Isaac 56309fbee547SJacob 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[]) 56311a271a75SMatthew G. Knepley { 56321a271a75SMatthew G. Knepley PetscInt offset = 0, p; 563397e99dd9SToby Isaac const PetscInt **perms = NULL; 563497e99dd9SToby Isaac const PetscScalar **flips = NULL; 56351a271a75SMatthew G. Knepley 56361a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5637fe02ba77SJed Brown *size = 0; 56389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 563997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 564097e99dd9SToby Isaac const PetscInt point = points[2*p]; 564197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 564297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 56431a271a75SMatthew G. Knepley PetscInt dof, off, d; 56441a271a75SMatthew G. Knepley const PetscScalar *varr; 56451a271a75SMatthew G. Knepley 56469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 56479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 56481a271a75SMatthew G. Knepley varr = &vArray[off]; 564997e99dd9SToby Isaac if (clperm) { 565097e99dd9SToby Isaac if (perm) { 565197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 56521a271a75SMatthew G. Knepley } else { 565397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 565497e99dd9SToby Isaac } 565597e99dd9SToby Isaac if (flip) { 565697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 565797e99dd9SToby Isaac } 565897e99dd9SToby Isaac } else { 565997e99dd9SToby Isaac if (perm) { 566097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 566197e99dd9SToby Isaac } else { 566297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 566397e99dd9SToby Isaac } 566497e99dd9SToby Isaac if (flip) { 566597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 56661a271a75SMatthew G. Knepley } 56671a271a75SMatthew G. Knepley } 566897e99dd9SToby Isaac offset += dof; 566997e99dd9SToby Isaac } 56709566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 56711a271a75SMatthew G. Knepley *size = offset; 56721a271a75SMatthew G. Knepley PetscFunctionReturn(0); 56731a271a75SMatthew G. Knepley } 56741a271a75SMatthew G. Knepley 56759fbee547SJacob 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[]) 56761a271a75SMatthew G. Knepley { 56771a271a75SMatthew G. Knepley PetscInt offset = 0, f; 56781a271a75SMatthew G. Knepley 56791a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5680fe02ba77SJed Brown *size = 0; 56811a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 568297e99dd9SToby Isaac PetscInt p; 568397e99dd9SToby Isaac const PetscInt **perms = NULL; 568497e99dd9SToby Isaac const PetscScalar **flips = NULL; 56851a271a75SMatthew G. Knepley 56869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 568797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 568897e99dd9SToby Isaac const PetscInt point = points[2*p]; 568997e99dd9SToby Isaac PetscInt fdof, foff, b; 56901a271a75SMatthew G. Knepley const PetscScalar *varr; 569197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 569297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 56931a271a75SMatthew G. Knepley 56949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 56959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 56961a271a75SMatthew G. Knepley varr = &vArray[foff]; 569797e99dd9SToby Isaac if (clperm) { 569897e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 569997e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 570097e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 57011a271a75SMatthew G. Knepley } else { 570297e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 570397e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 570497e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 57051a271a75SMatthew G. Knepley } 570697e99dd9SToby Isaac offset += fdof; 57071a271a75SMatthew G. Knepley } 57089566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 57091a271a75SMatthew G. Knepley } 57101a271a75SMatthew G. Knepley *size = offset; 57111a271a75SMatthew G. Knepley PetscFunctionReturn(0); 57121a271a75SMatthew G. Knepley } 57131a271a75SMatthew G. Knepley 5714552f7358SJed Brown /*@C 5715552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5716552f7358SJed Brown 5717552f7358SJed Brown Not collective 5718552f7358SJed Brown 5719552f7358SJed Brown Input Parameters: 5720552f7358SJed Brown + dm - The DM 5721552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section 5722552f7358SJed Brown . v - The local vector 57236b867d5aSJose E. Roman - point - The point in the DM 5724552f7358SJed Brown 57256b867d5aSJose E. Roman Input/Output Parameters: 57266b867d5aSJose E. Roman + csize - The size of the input values array, or NULL; on output the number of values in the closure 57276b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically; 57286b867d5aSJose E. Roman if the user provided NULL, it is a borrowed array and should not be freed 572922c1ee49SMatthew G. Knepley 573022c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 573122c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 573222c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation. 573322c1ee49SMatthew G. Knepley $ 573422c1ee49SMatthew G. Knepley $ A typical use could be 573522c1ee49SMatthew G. Knepley $ 573622c1ee49SMatthew G. Knepley $ values = NULL; 57379566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 573822c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 573922c1ee49SMatthew G. Knepley $ <Compute on closure> 574022c1ee49SMatthew G. Knepley $ } 57419566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 574222c1ee49SMatthew G. Knepley $ 574322c1ee49SMatthew G. Knepley $ or 574422c1ee49SMatthew G. Knepley $ 574522c1ee49SMatthew G. Knepley $ PetscMalloc1(clMaxSize, &values); 574622c1ee49SMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) { 574722c1ee49SMatthew G. Knepley $ clSize = clMaxSize; 57489566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 574922c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 575022c1ee49SMatthew G. Knepley $ <Compute on closure> 575122c1ee49SMatthew G. Knepley $ } 575222c1ee49SMatthew G. Knepley $ } 575322c1ee49SMatthew G. Knepley $ PetscFree(values); 5754552f7358SJed Brown 5755552f7358SJed Brown Fortran Notes: 5756552f7358SJed Brown Since it returns an array, this routine is only available in Fortran 90, and you must 5757552f7358SJed Brown include petsc.h90 in your code. 5758552f7358SJed Brown 5759552f7358SJed Brown The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5760552f7358SJed Brown 5761552f7358SJed Brown Level: intermediate 5762552f7358SJed Brown 5763db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5764552f7358SJed Brown @*/ 5765552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5766552f7358SJed Brown { 5767552f7358SJed Brown PetscSection clSection; 5768d9917b9dSMatthew G. Knepley IS clPoints; 5769552f7358SJed Brown PetscInt *points = NULL; 5770c459fbc1SJed Brown const PetscInt *clp, *perm; 5771c459fbc1SJed Brown PetscInt depth, numFields, numPoints, asize; 5772552f7358SJed Brown 5773d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 5774552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 57759566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 57761a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 57771a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 57789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 57799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5780552f7358SJed Brown if (depth == 1 && numFields < 2) { 57819566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5782552f7358SJed Brown PetscFunctionReturn(0); 5783552f7358SJed Brown } 57841a271a75SMatthew G. Knepley /* Get points */ 57859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5786c459fbc1SJed Brown /* Get sizes */ 5787c459fbc1SJed Brown asize = 0; 5788c459fbc1SJed Brown for (PetscInt p = 0; p < numPoints*2; p += 2) { 5789c459fbc1SJed Brown PetscInt dof; 57909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 57911a271a75SMatthew G. Knepley asize += dof; 5792552f7358SJed Brown } 5793c459fbc1SJed Brown if (values) { 5794c459fbc1SJed Brown const PetscScalar *vArray; 5795c459fbc1SJed Brown PetscInt size; 5796c459fbc1SJed Brown 5797c459fbc1SJed Brown if (*values) { 579863a3b9bcSJacob 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); 57999566063dSJacob Faibussowitsch } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 58009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm)); 58019566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 58021a271a75SMatthew G. Knepley /* Get values */ 58039566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 58049566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 580563a3b9bcSJacob Faibussowitsch PetscCheck(asize == size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size); 58061a271a75SMatthew G. Knepley /* Cleanup array */ 58079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5808d0f6b257SMatthew G. Knepley } 5809c459fbc1SJed Brown if (csize) *csize = asize; 5810c459fbc1SJed Brown /* Cleanup points */ 58119566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5812552f7358SJed Brown PetscFunctionReturn(0); 5813552f7358SJed Brown } 5814552f7358SJed Brown 5815e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5816e5c487bfSMatthew G. Knepley { 5817e5c487bfSMatthew G. Knepley DMLabel depthLabel; 5818e5c487bfSMatthew G. Knepley PetscSection clSection; 5819e5c487bfSMatthew G. Knepley IS clPoints; 5820e5c487bfSMatthew G. Knepley PetscScalar *array; 5821e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 5822e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 5823c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 5824c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5825e5c487bfSMatthew G. Knepley 5826e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 5827e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58289566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 5829e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5830e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 58319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 58329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 58339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5834e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 58359566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5836e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5837e5c487bfSMatthew G. Knepley } 5838e5c487bfSMatthew G. Knepley /* Get points */ 58399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5840c459fbc1SJed Brown for (clsize=0,p=0; p<Np; p++) { 5841c459fbc1SJed Brown PetscInt dof; 58429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 5843c459fbc1SJed Brown clsize += dof; 5844c459fbc1SJed Brown } 58459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm)); 5846e5c487bfSMatthew G. Knepley /* Filter points */ 5847e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 5848e5c487bfSMatthew G. Knepley PetscInt dep; 5849e5c487bfSMatthew G. Knepley 58509566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 5851e5c487bfSMatthew G. Knepley if (dep != depth) continue; 5852e5c487bfSMatthew G. Knepley points[Np*2+0] = points[p]; 5853e5c487bfSMatthew G. Knepley points[Np*2+1] = points[p+1]; 5854e5c487bfSMatthew G. Knepley ++Np; 5855e5c487bfSMatthew G. Knepley } 5856e5c487bfSMatthew G. Knepley /* Get array */ 5857e5c487bfSMatthew G. Knepley if (!values || !*values) { 5858e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 5859e5c487bfSMatthew G. Knepley 5860e5c487bfSMatthew G. Knepley for (p = 0; p < Np*2; p += 2) { 58619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 5862e5c487bfSMatthew G. Knepley asize += dof; 5863e5c487bfSMatthew G. Knepley } 5864e5c487bfSMatthew G. Knepley if (!values) { 58659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5866e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 5867e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5868e5c487bfSMatthew G. Knepley } 58699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 5870e5c487bfSMatthew G. Knepley } else { 5871e5c487bfSMatthew G. Knepley array = *values; 5872e5c487bfSMatthew G. Knepley } 58739566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 5874e5c487bfSMatthew G. Knepley /* Get values */ 58759566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 58769566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 5877e5c487bfSMatthew G. Knepley /* Cleanup points */ 58789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5879e5c487bfSMatthew G. Knepley /* Cleanup array */ 58809566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5881e5c487bfSMatthew G. Knepley if (!*values) { 5882e5c487bfSMatthew G. Knepley if (csize) *csize = size; 5883e5c487bfSMatthew G. Knepley *values = array; 5884e5c487bfSMatthew G. Knepley } else { 588563a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 5886e5c487bfSMatthew G. Knepley *csize = size; 5887e5c487bfSMatthew G. Knepley } 5888e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5889e5c487bfSMatthew G. Knepley } 5890e5c487bfSMatthew G. Knepley 5891552f7358SJed Brown /*@C 5892552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5893552f7358SJed Brown 5894552f7358SJed Brown Not collective 5895552f7358SJed Brown 5896552f7358SJed Brown Input Parameters: 5897552f7358SJed Brown + dm - The DM 58980298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section 5899552f7358SJed Brown . v - The local vector 5900eaf898f9SPatrick Sanan . point - The point in the DM 59010298fd71SBarry Smith . csize - The number of values in the closure, or NULL 5902552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 5903552f7358SJed Brown 590422c1ee49SMatthew 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() 590522c1ee49SMatthew G. Knepley 59063813dfbdSMatthew G Knepley Fortran Notes: 59073813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 59083813dfbdSMatthew G Knepley include petsc.h90 in your code. 59093813dfbdSMatthew G Knepley 59103813dfbdSMatthew G Knepley The csize argument is not present in the Fortran 90 binding since it is internal to the array. 59113813dfbdSMatthew G Knepley 5912552f7358SJed Brown Level: intermediate 5913552f7358SJed Brown 5914db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5915552f7358SJed Brown @*/ 59167c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5917a6dfd86eSKarl Rupp { 5918552f7358SJed Brown PetscInt size = 0; 5919552f7358SJed Brown 5920552f7358SJed Brown PetscFunctionBegin; 5921552f7358SJed Brown /* Should work without recalculating size */ 59229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values)); 5923c9fdaa05SMatthew G. Knepley *values = NULL; 5924552f7358SJed Brown PetscFunctionReturn(0); 5925552f7358SJed Brown } 5926552f7358SJed Brown 59279fbee547SJacob Faibussowitsch static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 59289fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5929552f7358SJed Brown 59309fbee547SJacob 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[]) 5931552f7358SJed Brown { 5932552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 5933552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5934552f7358SJed Brown PetscScalar *a; 5935552f7358SJed Brown PetscInt off, cind = 0, k; 5936552f7358SJed Brown 5937552f7358SJed Brown PetscFunctionBegin; 59389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 59399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 5940552f7358SJed Brown a = &array[off]; 5941552f7358SJed Brown if (!cdof || setBC) { 594297e99dd9SToby Isaac if (clperm) { 594397e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 594497e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5945552f7358SJed Brown } else { 594697e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 594797e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5948552f7358SJed Brown } 5949552f7358SJed Brown } else { 59509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 595197e99dd9SToby Isaac if (clperm) { 595297e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) { 5953552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 595497e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5955552f7358SJed Brown } 5956552f7358SJed Brown } else { 5957552f7358SJed Brown for (k = 0; k < dof; ++k) { 5958552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 595997e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 596097e99dd9SToby Isaac } 596197e99dd9SToby Isaac } 596297e99dd9SToby Isaac } else { 596397e99dd9SToby Isaac if (perm) { 596497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 596597e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 596697e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 596797e99dd9SToby Isaac } 596897e99dd9SToby Isaac } else { 596997e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 597097e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 597197e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 597297e99dd9SToby Isaac } 5973552f7358SJed Brown } 5974552f7358SJed Brown } 5975552f7358SJed Brown } 5976552f7358SJed Brown PetscFunctionReturn(0); 5977552f7358SJed Brown } 5978552f7358SJed Brown 59799fbee547SJacob 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[]) 5980a5e93ea8SMatthew G. Knepley { 5981a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 5982a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5983a5e93ea8SMatthew G. Knepley PetscScalar *a; 5984a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 5985a5e93ea8SMatthew G. Knepley 5986a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 59879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 59889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 5989a5e93ea8SMatthew G. Knepley a = &array[off]; 5990a5e93ea8SMatthew G. Knepley if (cdof) { 59919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 599297e99dd9SToby Isaac if (clperm) { 599397e99dd9SToby Isaac if (perm) { 5994a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 5995a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 599697e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 599797e99dd9SToby Isaac cind++; 5998a5e93ea8SMatthew G. Knepley } 5999a5e93ea8SMatthew G. Knepley } 6000a5e93ea8SMatthew G. Knepley } else { 6001a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6002a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 600397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 600497e99dd9SToby Isaac cind++; 600597e99dd9SToby Isaac } 600697e99dd9SToby Isaac } 600797e99dd9SToby Isaac } 600897e99dd9SToby Isaac } else { 600997e99dd9SToby Isaac if (perm) { 601097e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 601197e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 601297e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 601397e99dd9SToby Isaac cind++; 601497e99dd9SToby Isaac } 601597e99dd9SToby Isaac } 601697e99dd9SToby Isaac } else { 601797e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 601897e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 601997e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 602097e99dd9SToby Isaac cind++; 602197e99dd9SToby Isaac } 6022a5e93ea8SMatthew G. Knepley } 6023a5e93ea8SMatthew G. Knepley } 6024a5e93ea8SMatthew G. Knepley } 6025a5e93ea8SMatthew G. Knepley } 6026a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6027a5e93ea8SMatthew G. Knepley } 6028a5e93ea8SMatthew G. Knepley 60299fbee547SJacob 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[]) 6030a6dfd86eSKarl Rupp { 6031552f7358SJed Brown PetscScalar *a; 60321a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60331a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 603497e99dd9SToby Isaac PetscInt cind = 0, b; 6035552f7358SJed Brown 6036552f7358SJed Brown PetscFunctionBegin; 60379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 60389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 60399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 60401a271a75SMatthew G. Knepley a = &array[foff]; 6041552f7358SJed Brown if (!fcdof || setBC) { 604297e99dd9SToby Isaac if (clperm) { 604397e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 604497e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6045552f7358SJed Brown } else { 604697e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 604797e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6048552f7358SJed Brown } 6049552f7358SJed Brown } else { 60509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 605197e99dd9SToby Isaac if (clperm) { 605297e99dd9SToby Isaac if (perm) { 605397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 605497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 605597e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6056552f7358SJed Brown } 6057552f7358SJed Brown } else { 605897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 605997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 606097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 606197e99dd9SToby Isaac } 606297e99dd9SToby Isaac } 606397e99dd9SToby Isaac } else { 606497e99dd9SToby Isaac if (perm) { 606597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 606697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 606797e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 606897e99dd9SToby Isaac } 606997e99dd9SToby Isaac } else { 607097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 607197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 607297e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6073552f7358SJed Brown } 6074552f7358SJed Brown } 6075552f7358SJed Brown } 6076552f7358SJed Brown } 60771a271a75SMatthew G. Knepley *offset += fdof; 6078552f7358SJed Brown PetscFunctionReturn(0); 6079552f7358SJed Brown } 6080552f7358SJed Brown 60819fbee547SJacob 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[]) 6082a5e93ea8SMatthew G. Knepley { 6083a5e93ea8SMatthew G. Knepley PetscScalar *a; 60841a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60851a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 60865da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6087ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6088a5e93ea8SMatthew G. Knepley 6089a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 60909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 60919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 60929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 60939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 60941a271a75SMatthew G. Knepley a = &array[foff]; 6095a5e93ea8SMatthew G. Knepley if (fcdof) { 6096ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 60979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 609897e99dd9SToby Isaac if (clperm) { 609997e99dd9SToby Isaac if (perm) { 6100ba322698SMatthew G. Knepley if (comps) { 6101ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6102ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61035da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6104ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6105ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6106ba322698SMatthew G. Knepley } 6107ba322698SMatthew G. Knepley } else { 610897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 610997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 611097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6111a5e93ea8SMatthew G. Knepley ++cind; 6112a5e93ea8SMatthew G. Knepley } 6113a5e93ea8SMatthew G. Knepley } 6114ba322698SMatthew G. Knepley } 6115ba322698SMatthew G. Knepley } else { 6116ba322698SMatthew G. Knepley if (comps) { 6117ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6118ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61195da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6120ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6121ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6122ba322698SMatthew G. Knepley } 6123a5e93ea8SMatthew G. Knepley } else { 612497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 612597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 612697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 612797e99dd9SToby Isaac ++cind; 612897e99dd9SToby Isaac } 612997e99dd9SToby Isaac } 613097e99dd9SToby Isaac } 6131ba322698SMatthew G. Knepley } 613297e99dd9SToby Isaac } else { 613397e99dd9SToby Isaac if (perm) { 6134ba322698SMatthew G. Knepley if (comps) { 6135ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6136ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61375da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6138ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6139ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6140ba322698SMatthew G. Knepley } 6141ba322698SMatthew G. Knepley } else { 614297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 614397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 614497e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 614597e99dd9SToby Isaac ++cind; 614697e99dd9SToby Isaac } 614797e99dd9SToby Isaac } 6148ba322698SMatthew G. Knepley } 6149ba322698SMatthew G. Knepley } else { 6150ba322698SMatthew G. Knepley if (comps) { 6151ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6152ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61535da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6154ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6155ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6156ba322698SMatthew G. Knepley } 615797e99dd9SToby Isaac } else { 615897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 615997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 616097e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6161a5e93ea8SMatthew G. Knepley ++cind; 6162a5e93ea8SMatthew G. Knepley } 6163a5e93ea8SMatthew G. Knepley } 6164a5e93ea8SMatthew G. Knepley } 6165a5e93ea8SMatthew G. Knepley } 6166a5e93ea8SMatthew G. Knepley } 6167ba322698SMatthew G. Knepley } 61681a271a75SMatthew G. Knepley *offset += fdof; 6169a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6170a5e93ea8SMatthew G. Knepley } 6171a5e93ea8SMatthew G. Knepley 61729fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6173a6dfd86eSKarl Rupp { 6174552f7358SJed Brown PetscScalar *array; 61751b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 61761b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6177552f7358SJed Brown 61781b406b76SMatthew G. Knepley PetscFunctionBeginHot; 61799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 61809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 61819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 61829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 61839566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6184b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6185b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p-1]; 6186b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p-1]; 6187b6ebb6e6SMatthew G. Knepley 6188b6ebb6e6SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 61899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6190b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6191b6ebb6e6SMatthew G. Knepley { 6192b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6193b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6194b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6195b6ebb6e6SMatthew G. Knepley 61969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 61979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6198b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6199b6ebb6e6SMatthew G. Knepley if (!cdof) { 6200b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6201b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6202b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6203b6ebb6e6SMatthew G. Knepley } 6204b6ebb6e6SMatthew G. Knepley } else { 6205b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6206b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6207b6ebb6e6SMatthew G. Knepley } 6208b6ebb6e6SMatthew G. Knepley } 6209b6ebb6e6SMatthew G. Knepley } else { 62109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6211b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6212b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6213b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6214b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6215b6ebb6e6SMatthew G. Knepley } 6216b6ebb6e6SMatthew G. Knepley } else { 6217b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6218b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6219b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6220b6ebb6e6SMatthew G. Knepley } 6221b6ebb6e6SMatthew G. Knepley } 6222b6ebb6e6SMatthew G. Knepley } 6223b6ebb6e6SMatthew G. Knepley } 6224b6ebb6e6SMatthew G. Knepley } 62259566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6226b6ebb6e6SMatthew G. Knepley PetscFunctionReturn(0); 6227b6ebb6e6SMatthew G. Knepley } 62281b406b76SMatthew G. Knepley 62291b406b76SMatthew G. Knepley /*@C 62301b406b76SMatthew G. Knepley DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 62311b406b76SMatthew G. Knepley 62321b406b76SMatthew G. Knepley Not collective 62331b406b76SMatthew G. Knepley 62341b406b76SMatthew G. Knepley Input Parameters: 62351b406b76SMatthew G. Knepley + dm - The DM 62361b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 62371b406b76SMatthew G. Knepley . v - The local vector 6238eaf898f9SPatrick Sanan . point - The point in the DM 62391b406b76SMatthew G. Knepley . values - The array of values 624022c1ee49SMatthew 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, 624122c1ee49SMatthew G. Knepley where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 62421b406b76SMatthew G. Knepley 62431b406b76SMatthew G. Knepley Fortran Notes: 62441b406b76SMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 62451b406b76SMatthew G. Knepley 62461b406b76SMatthew G. Knepley Level: intermediate 62471b406b76SMatthew G. Knepley 6248db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 62491b406b76SMatthew G. Knepley @*/ 62501b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 62511b406b76SMatthew G. Knepley { 62521b406b76SMatthew G. Knepley PetscSection clSection; 62531b406b76SMatthew G. Knepley IS clPoints; 62541b406b76SMatthew G. Knepley PetscScalar *array; 62551b406b76SMatthew G. Knepley PetscInt *points = NULL; 625627f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6257c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 62581b406b76SMatthew G. Knepley 62591a271a75SMatthew G. Knepley PetscFunctionBeginHot; 62601b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62619566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 62621a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 62631a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 62649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 62659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 62661b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 62679566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 62681b406b76SMatthew G. Knepley PetscFunctionReturn(0); 62691b406b76SMatthew G. Knepley } 62701a271a75SMatthew G. Knepley /* Get points */ 62719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6272c459fbc1SJed Brown for (clsize=0,p=0; p<numPoints; p++) { 6273c459fbc1SJed Brown PetscInt dof; 62749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 6275c459fbc1SJed Brown clsize += dof; 6276c459fbc1SJed Brown } 62779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 62781a271a75SMatthew G. Knepley /* Get array */ 62799566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 62801a271a75SMatthew G. Knepley /* Get values */ 6281ef90cfe2SMatthew G. Knepley if (numFields > 0) { 628297e99dd9SToby Isaac PetscInt offset = 0, f; 6283552f7358SJed Brown for (f = 0; f < numFields; ++f) { 628497e99dd9SToby Isaac const PetscInt **perms = NULL; 628597e99dd9SToby Isaac const PetscScalar **flips = NULL; 628697e99dd9SToby Isaac 62879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6288552f7358SJed Brown switch (mode) { 6289552f7358SJed Brown case INSERT_VALUES: 629097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 629197e99dd9SToby Isaac const PetscInt point = points[2*p]; 629297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 629397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 629497e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6295552f7358SJed Brown } break; 6296552f7358SJed Brown case INSERT_ALL_VALUES: 629797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 629897e99dd9SToby Isaac const PetscInt point = points[2*p]; 629997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 630097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 630197e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6302552f7358SJed Brown } break; 6303a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 630497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 630597e99dd9SToby Isaac const PetscInt point = points[2*p]; 630697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 630797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6308ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6309a5e93ea8SMatthew G. Knepley } break; 6310552f7358SJed Brown case ADD_VALUES: 631197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 631297e99dd9SToby Isaac const PetscInt point = points[2*p]; 631397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 631497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 631597e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6316552f7358SJed Brown } break; 6317552f7358SJed Brown case ADD_ALL_VALUES: 631897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 631997e99dd9SToby Isaac const PetscInt point = points[2*p]; 632097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 632297e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6323552f7358SJed Brown } break; 6324304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 632597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632697e99dd9SToby Isaac const PetscInt point = points[2*p]; 632797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6329ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6330304ab55fSMatthew G. Knepley } break; 6331552f7358SJed Brown default: 633298921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6333552f7358SJed Brown } 63349566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 63351a271a75SMatthew G. Knepley } 6336552f7358SJed Brown } else { 63371a271a75SMatthew G. Knepley PetscInt dof, off; 633897e99dd9SToby Isaac const PetscInt **perms = NULL; 633997e99dd9SToby Isaac const PetscScalar **flips = NULL; 63401a271a75SMatthew G. Knepley 63419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 6342552f7358SJed Brown switch (mode) { 6343552f7358SJed Brown case INSERT_VALUES: 634497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 634597e99dd9SToby Isaac const PetscInt point = points[2*p]; 634697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 634797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 634997e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6350552f7358SJed Brown } break; 6351552f7358SJed Brown case INSERT_ALL_VALUES: 635297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 635397e99dd9SToby Isaac const PetscInt point = points[2*p]; 635497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 635597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 635797e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6358552f7358SJed Brown } break; 6359a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 636097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 636197e99dd9SToby Isaac const PetscInt point = points[2*p]; 636297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 636397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 636597e99dd9SToby Isaac updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6366a5e93ea8SMatthew G. Knepley } break; 6367552f7358SJed Brown case ADD_VALUES: 636897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 636997e99dd9SToby Isaac const PetscInt point = points[2*p]; 637097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 637197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 637397e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6374552f7358SJed Brown } break; 6375552f7358SJed Brown case ADD_ALL_VALUES: 637697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 637797e99dd9SToby Isaac const PetscInt point = points[2*p]; 637897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 637997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 638197e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6382552f7358SJed Brown } break; 6383304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 638497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 638597e99dd9SToby Isaac const PetscInt point = points[2*p]; 638697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 638797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 638997e99dd9SToby Isaac updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6390304ab55fSMatthew G. Knepley } break; 6391552f7358SJed Brown default: 639298921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6393552f7358SJed Brown } 63949566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 6395552f7358SJed Brown } 63961a271a75SMatthew G. Knepley /* Cleanup points */ 63979566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 63981a271a75SMatthew G. Knepley /* Cleanup array */ 63999566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6400552f7358SJed Brown PetscFunctionReturn(0); 6401552f7358SJed Brown } 6402552f7358SJed Brown 64035f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 64049fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 64055f790a90SMatthew G. Knepley { 64065f790a90SMatthew G. Knepley PetscFunctionBegin; 64075f790a90SMatthew G. Knepley if (label) { 64085f790a90SMatthew G. Knepley PetscInt val, fdof; 64095f790a90SMatthew G. Knepley 64105f790a90SMatthew G. Knepley /* There is a problem with this: 64115f790a90SMatthew 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 64125f790a90SMatthew 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. 64135f790a90SMatthew G. Knepley Thus I am only going to check val != -1, not val != labelId 64145f790a90SMatthew G. Knepley */ 64159566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 64165f790a90SMatthew G. Knepley if (val < 0) { 64179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 64185f790a90SMatthew G. Knepley *offset += fdof; 64195f790a90SMatthew G. Knepley PetscFunctionReturn(1); 64205f790a90SMatthew G. Knepley } 64215f790a90SMatthew G. Knepley } 64225f790a90SMatthew G. Knepley PetscFunctionReturn(0); 64235f790a90SMatthew G. Knepley } 64245f790a90SMatthew G. Knepley 642597529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 64265f790a90SMatthew 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) 6427e07394fbSMatthew G. Knepley { 6428e07394fbSMatthew G. Knepley PetscSection clSection; 6429e07394fbSMatthew G. Knepley IS clPoints; 6430e07394fbSMatthew G. Knepley PetscScalar *array; 6431e07394fbSMatthew G. Knepley PetscInt *points = NULL; 643297529cf3SJed Brown const PetscInt *clp; 6433e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 643497e99dd9SToby Isaac PetscInt offset = 0, f; 6435e07394fbSMatthew G. Knepley 6436e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 6437e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64389566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6439e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6440e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6442e07394fbSMatthew G. Knepley /* Get points */ 64439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6444e07394fbSMatthew G. Knepley /* Get array */ 64459566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6446e07394fbSMatthew G. Knepley /* Get values */ 6447e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 644897e99dd9SToby Isaac const PetscInt **perms = NULL; 644997e99dd9SToby Isaac const PetscScalar **flips = NULL; 645097e99dd9SToby Isaac 6451e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 6452e07394fbSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 6453e07394fbSMatthew G. Knepley PetscInt fdof; 64549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 6455e07394fbSMatthew G. Knepley offset += fdof; 6456e07394fbSMatthew G. Knepley } 6457e07394fbSMatthew G. Knepley continue; 6458e07394fbSMatthew G. Knepley } 64599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6460e07394fbSMatthew G. Knepley switch (mode) { 6461e07394fbSMatthew G. Knepley case INSERT_VALUES: 646297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 646397e99dd9SToby Isaac const PetscInt point = points[2*p]; 646497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 646597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64665f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64679566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 6468e07394fbSMatthew G. Knepley } break; 6469e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 647097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 647197e99dd9SToby Isaac const PetscInt point = points[2*p]; 647297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 647397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64745f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64759566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 6476e07394fbSMatthew G. Knepley } break; 6477e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 647897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 647997e99dd9SToby Isaac const PetscInt point = points[2*p]; 648097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 648197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64825f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64839566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 6484e07394fbSMatthew G. Knepley } break; 6485e07394fbSMatthew G. Knepley case ADD_VALUES: 648697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 648797e99dd9SToby Isaac const PetscInt point = points[2*p]; 648897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 648997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64905f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64919566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 6492e07394fbSMatthew G. Knepley } break; 6493e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 649497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649597e99dd9SToby Isaac const PetscInt point = points[2*p]; 649697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64985f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64999566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 6500e07394fbSMatthew G. Knepley } break; 6501e07394fbSMatthew G. Knepley default: 650298921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6503e07394fbSMatthew G. Knepley } 65049566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6505e07394fbSMatthew G. Knepley } 6506e07394fbSMatthew G. Knepley /* Cleanup points */ 65079566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6508e07394fbSMatthew G. Knepley /* Cleanup array */ 65099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6510e07394fbSMatthew G. Knepley PetscFunctionReturn(0); 6511e07394fbSMatthew G. Knepley } 6512e07394fbSMatthew G. Knepley 65137cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6514552f7358SJed Brown { 6515552f7358SJed Brown PetscMPIInt rank; 6516552f7358SJed Brown PetscInt i, j; 6517552f7358SJed Brown 6518552f7358SJed Brown PetscFunctionBegin; 65199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 652063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 652163a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 652263a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 6523b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 6524557cf195SMatthew G. Knepley if (!values) PetscFunctionReturn(0); 6525b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 65269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 6527b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 6528519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 65299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]))); 6530552f7358SJed Brown #else 65319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j])); 6532552f7358SJed Brown #endif 6533552f7358SJed Brown } 65349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6535552f7358SJed Brown } 6536552f7358SJed Brown PetscFunctionReturn(0); 6537552f7358SJed Brown } 6538552f7358SJed Brown 653905586334SMatthew G. Knepley /* 654005586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 654105586334SMatthew G. Knepley 654205586334SMatthew G. Knepley Input Parameters: 654305586334SMatthew G. Knepley + section - The section for this data layout 654436fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 654505586334SMatthew G. Knepley . point - The point contributing dofs with these indices 654605586334SMatthew G. Knepley . off - The global offset of this point 654705586334SMatthew G. Knepley . loff - The local offset of each field 6548a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 654905586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 655005586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 655105586334SMatthew G. Knepley 655205586334SMatthew G. Knepley Output Parameter: 655305586334SMatthew G. Knepley . indices - Indices for dofs on this point 655405586334SMatthew G. Knepley 655505586334SMatthew G. Knepley Level: developer 655605586334SMatthew G. Knepley 655705586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 655805586334SMatthew G. Knepley */ 655936fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6560a6dfd86eSKarl Rupp { 6561e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 6562552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6563552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6564552f7358SJed Brown PetscInt cind = 0, k; 6565552f7358SJed Brown 6566552f7358SJed Brown PetscFunctionBegin; 656708401ef6SPierre Jolivet PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 65689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 65699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 6570552f7358SJed Brown if (!cdof || setBC) { 657105586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 657205586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 657305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 657405586334SMatthew G. Knepley 657505586334SMatthew G. Knepley indices[ind] = off + k; 6576552f7358SJed Brown } 6577552f7358SJed Brown } else { 65789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 65794acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 658005586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 658105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 658205586334SMatthew G. Knepley 65834acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 65844acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 658505586334SMatthew G. Knepley indices[ind] = -(off+k+1); 65864acb8e1eSToby Isaac ++cind; 65874acb8e1eSToby Isaac } else { 658836fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 6589552f7358SJed Brown } 6590552f7358SJed Brown } 6591552f7358SJed Brown } 6592e6ccafaeSMatthew G Knepley *loff += dof; 6593552f7358SJed Brown PetscFunctionReturn(0); 6594552f7358SJed Brown } 6595552f7358SJed Brown 65967e29afd2SMatthew G. Knepley /* 659736fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 65987e29afd2SMatthew G. Knepley 659936fa2b79SJed Brown Input Parameters: 660036fa2b79SJed Brown + section - a section (global or local) 660136fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 660236fa2b79SJed Brown . point - point within section 660336fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 660436fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 660536fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 660636fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 660736fa2b79SJed Brown . permsoff - offset 660836fa2b79SJed Brown - indperm - index permutation 660936fa2b79SJed Brown 661036fa2b79SJed Brown Output Parameter: 661136fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 661236fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 661336fa2b79SJed Brown 661436fa2b79SJed Brown Notes: 661536fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 661636fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 661736fa2b79SJed Brown in the local vector. 661836fa2b79SJed Brown 661936fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 662036fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 662136fa2b79SJed Brown 662236fa2b79SJed Brown Developer Note: 662336fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 662436fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 662536fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 662636fa2b79SJed Brown 662736fa2b79SJed Brown Example: 662836fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 662936fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 663036fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 663136fa2b79SJed 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. 663236fa2b79SJed Brown 663336fa2b79SJed Brown Level: developer 66347e29afd2SMatthew G. Knepley */ 663536fa2b79SJed 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[]) 6636a6dfd86eSKarl Rupp { 6637552f7358SJed Brown PetscInt numFields, foff, f; 6638552f7358SJed Brown 6639552f7358SJed Brown PetscFunctionBegin; 664008401ef6SPierre Jolivet PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 66419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6642552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 66434acb8e1eSToby Isaac PetscInt fdof, cfdof; 6644552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 66454acb8e1eSToby Isaac PetscInt cind = 0, b; 66464acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6647552f7358SJed Brown 66489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 66499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 6650552f7358SJed Brown if (!cfdof || setBC) { 665105586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 665205586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 665305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 665405586334SMatthew G. Knepley 665505586334SMatthew G. Knepley indices[ind] = off+foff+b; 665605586334SMatthew G. Knepley } 6657552f7358SJed Brown } else { 66589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 665905586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 666005586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 666105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 666205586334SMatthew G. Knepley 66634acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 666405586334SMatthew G. Knepley indices[ind] = -(off+foff+b+1); 6665552f7358SJed Brown ++cind; 6666552f7358SJed Brown } else { 666736fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 6668552f7358SJed Brown } 6669552f7358SJed Brown } 6670552f7358SJed Brown } 667136fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6672552f7358SJed Brown foffs[f] += fdof; 6673552f7358SJed Brown } 6674552f7358SJed Brown PetscFunctionReturn(0); 6675552f7358SJed Brown } 6676552f7358SJed Brown 66777e29afd2SMatthew G. Knepley /* 66787e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 66797e29afd2SMatthew G. Knepley 66807e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 6681645102dcSJed Brown 6682645102dcSJed Brown Notes: 6683645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6684645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 66857e29afd2SMatthew G. Knepley */ 6686645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 66877e29afd2SMatthew G. Knepley { 66887e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 66897e29afd2SMatthew G. Knepley 66907e29afd2SMatthew G. Knepley PetscFunctionBegin; 66919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 66927e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 66937e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 66947e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 66957e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 66967e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 66977e29afd2SMatthew G. Knepley 66989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 66999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 67009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 6701645102dcSJed Brown if (!cfdof) { 670205586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 670305586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 670405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 670505586334SMatthew G. Knepley 670605586334SMatthew G. Knepley indices[ind] = foff+b; 670705586334SMatthew G. Knepley } 67087e29afd2SMatthew G. Knepley } else { 67099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 671005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 671105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 671205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 671305586334SMatthew G. Knepley 67147e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 671505586334SMatthew G. Knepley indices[ind] = -(foff+b+1); 67167e29afd2SMatthew G. Knepley ++cind; 67177e29afd2SMatthew G. Knepley } else { 671805586334SMatthew G. Knepley indices[ind] = foff+b-cind; 67197e29afd2SMatthew G. Knepley } 67207e29afd2SMatthew G. Knepley } 67217e29afd2SMatthew G. Knepley } 67227e29afd2SMatthew G. Knepley foffs[f] += fdof; 67237e29afd2SMatthew G. Knepley } 67247e29afd2SMatthew G. Knepley PetscFunctionReturn(0); 67257e29afd2SMatthew G. Knepley } 67267e29afd2SMatthew G. Knepley 67274acb8e1eSToby 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) 6728d3d1a6afSToby Isaac { 6729d3d1a6afSToby Isaac Mat cMat; 6730d3d1a6afSToby Isaac PetscSection aSec, cSec; 6731d3d1a6afSToby Isaac IS aIS; 6732d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 6733d3d1a6afSToby Isaac const PetscInt *anchors; 6734e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 6735d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 6736d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 6737d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 6738d3d1a6afSToby Isaac PetscInt newOffsets[32]; 6739d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 6740d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 6741d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 67426ecaa68aSToby Isaac PetscScalar *newValues=NULL,*tmpValues; 6743d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 6744d3d1a6afSToby Isaac 6745d3d1a6afSToby Isaac PetscFunctionBegin; 6746d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6747d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 67489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6749d3d1a6afSToby Isaac 67509566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 6751d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 6752d3d1a6afSToby Isaac if (aSec) { 67539566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 67549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 67559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd)); 6756d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 6757d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 6758d3d1a6afSToby Isaac * into the global matrix anyway) */ 6759d3d1a6afSToby Isaac for (p = 0; p < 2*numPoints; p+=2) { 6760d3d1a6afSToby Isaac PetscInt b = points[p]; 67614b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6762d3d1a6afSToby Isaac 67639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 67644b2f2278SToby Isaac if (!bSecDof) { 67654b2f2278SToby Isaac continue; 67664b2f2278SToby Isaac } 6767d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 67689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,b,&bDof)); 6769d3d1a6afSToby Isaac } 6770d3d1a6afSToby Isaac if (bDof) { 6771d3d1a6afSToby Isaac /* this point is constrained */ 6772d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 6773d3d1a6afSToby Isaac PetscInt bOff, q; 6774d3d1a6afSToby Isaac 6775d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 6776d3d1a6afSToby Isaac newNumPoints += bDof; 67779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,b,&bOff)); 6778d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6779d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6780d3d1a6afSToby Isaac PetscInt aDof; 6781d3d1a6afSToby Isaac 67829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 6783d3d1a6afSToby Isaac newNumIndices += aDof; 6784d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6785d3d1a6afSToby Isaac PetscInt fDof; 6786d3d1a6afSToby Isaac 67879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 6788d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6789d3d1a6afSToby Isaac } 6790d3d1a6afSToby Isaac } 6791d3d1a6afSToby Isaac } 6792d3d1a6afSToby Isaac else { 6793d3d1a6afSToby Isaac /* this point is not constrained */ 6794d3d1a6afSToby Isaac newNumPoints++; 67954b2f2278SToby Isaac newNumIndices += bSecDof; 6796d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6797d3d1a6afSToby Isaac PetscInt fDof; 6798d3d1a6afSToby Isaac 67999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6800d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6801d3d1a6afSToby Isaac } 6802d3d1a6afSToby Isaac } 6803d3d1a6afSToby Isaac } 6804d3d1a6afSToby Isaac } 6805d3d1a6afSToby Isaac if (!anyConstrained) { 680672b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 680772b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 680872b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 680972b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 68109566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors)); 6811d3d1a6afSToby Isaac PetscFunctionReturn(0); 6812d3d1a6afSToby Isaac } 6813d3d1a6afSToby Isaac 68146ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 68156ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 68166ecaa68aSToby Isaac 6817f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6818d3d1a6afSToby Isaac 68196ecaa68aSToby Isaac if (!outPoints && !outValues) { 68206ecaa68aSToby Isaac if (offsets) { 68216ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 68226ecaa68aSToby Isaac offsets[f] = newOffsets[f]; 68236ecaa68aSToby Isaac } 68246ecaa68aSToby Isaac } 68259566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors)); 68266ecaa68aSToby Isaac PetscFunctionReturn(0); 68276ecaa68aSToby Isaac } 68286ecaa68aSToby Isaac 68291dca8a05SBarry 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); 6830d3d1a6afSToby Isaac 68319566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 6832d3d1a6afSToby Isaac 6833d3d1a6afSToby Isaac /* workspaces */ 6834d3d1a6afSToby Isaac if (numFields) { 6835d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 68369566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 68379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 6838d3d1a6afSToby Isaac } 6839d3d1a6afSToby Isaac } 6840d3d1a6afSToby Isaac else { 68419566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 68429566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0])); 6843d3d1a6afSToby Isaac } 6844d3d1a6afSToby Isaac 6845d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 6846d3d1a6afSToby Isaac if (numFields) { 68474b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 68484b2f2278SToby Isaac 6849d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6850d3d1a6afSToby Isaac PetscInt b = points[2*p]; 68514b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6852d3d1a6afSToby Isaac 68539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 68544b2f2278SToby Isaac if (!bSecDof) { 68554b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 68564b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 68574b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 68584b2f2278SToby Isaac } 68594b2f2278SToby Isaac continue; 68604b2f2278SToby Isaac } 6861d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 68629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6863d3d1a6afSToby Isaac } 6864d3d1a6afSToby Isaac if (bDof) { 6865d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6866d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 6867d3d1a6afSToby Isaac 68689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 68699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6870d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6871d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6872d3d1a6afSToby Isaac PetscInt aFDof; 6873d3d1a6afSToby Isaac 68749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 6875d3d1a6afSToby Isaac allFDof += aFDof; 6876d3d1a6afSToby Isaac } 6877d3d1a6afSToby Isaac newPointOffsets[f][p+1] = allFDof; 6878d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = fDof * allFDof; 6879d3d1a6afSToby Isaac } 6880d3d1a6afSToby Isaac } 6881d3d1a6afSToby Isaac else { 6882d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6883d3d1a6afSToby Isaac PetscInt fDof; 6884d3d1a6afSToby Isaac 68859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6886d3d1a6afSToby Isaac newPointOffsets[f][p+1] = fDof; 6887d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = 0; 6888d3d1a6afSToby Isaac } 6889d3d1a6afSToby Isaac } 6890d3d1a6afSToby Isaac } 68914b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 68924b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 68934b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 6894d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6895d3d1a6afSToby Isaac newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6896d3d1a6afSToby Isaac pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6897d3d1a6afSToby Isaac } 689819f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 689919f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 69009566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 6901d3d1a6afSToby Isaac } 6902d3d1a6afSToby Isaac } 6903d3d1a6afSToby Isaac else { 6904d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6905d3d1a6afSToby Isaac PetscInt b = points[2*p]; 69064b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6907d3d1a6afSToby Isaac 69089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 69094b2f2278SToby Isaac if (!bSecDof) { 69104b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 69114b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 69124b2f2278SToby Isaac continue; 69134b2f2278SToby Isaac } 6914d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6916d3d1a6afSToby Isaac } 6917d3d1a6afSToby Isaac if (bDof) { 69184b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 6919d3d1a6afSToby Isaac 69209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6921d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6922d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 6923d3d1a6afSToby Isaac 69249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 6925d3d1a6afSToby Isaac allDof += aDof; 6926d3d1a6afSToby Isaac } 6927d3d1a6afSToby Isaac newPointOffsets[0][p+1] = allDof; 69284b2f2278SToby Isaac pointMatOffsets[0][p+1] = bSecDof * allDof; 6929d3d1a6afSToby Isaac } 6930d3d1a6afSToby Isaac else { 69314b2f2278SToby Isaac newPointOffsets[0][p+1] = bSecDof; 6932d3d1a6afSToby Isaac pointMatOffsets[0][p+1] = 0; 6933d3d1a6afSToby Isaac } 6934d3d1a6afSToby Isaac } 6935d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 6936d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 6937d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6938d3d1a6afSToby Isaac newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6939d3d1a6afSToby Isaac pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6940d3d1a6afSToby Isaac } 69419566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 6942d3d1a6afSToby Isaac } 6943d3d1a6afSToby Isaac 69446ecaa68aSToby Isaac /* output arrays */ 69459566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 69466ecaa68aSToby Isaac 6947d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 69489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 69499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 69509566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices)); 69519566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 6952d3d1a6afSToby Isaac if (numFields) { 6953d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 6954d3d1a6afSToby Isaac PetscInt b = points[2*p]; 6955d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 69564b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6957d3d1a6afSToby Isaac 69589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 69594b2f2278SToby Isaac if (!bSecDof) { 69604b2f2278SToby Isaac continue; 69614b2f2278SToby Isaac } 6962d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6964d3d1a6afSToby Isaac } 6965d3d1a6afSToby Isaac if (bDof) { 6966d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6967d3d1a6afSToby Isaac 6968d3d1a6afSToby Isaac fStart[0] = 0; 6969d3d1a6afSToby Isaac fEnd[0] = 0; 6970d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6971d3d1a6afSToby Isaac PetscInt fDof; 6972d3d1a6afSToby Isaac 69739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 6974d3d1a6afSToby Isaac fStart[f+1] = fStart[f] + fDof; 6975d3d1a6afSToby Isaac fEnd[f+1] = fStart[f+1]; 6976d3d1a6afSToby Isaac } 69779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 69789566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 6979d3d1a6afSToby Isaac 6980d3d1a6afSToby Isaac fAnchorStart[0] = 0; 6981d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 6982d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6983d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6984d3d1a6afSToby Isaac 6985d3d1a6afSToby Isaac fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6986d3d1a6afSToby Isaac fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6987d3d1a6afSToby Isaac } 69889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6989d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6990d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 6991d3d1a6afSToby Isaac 6992d3d1a6afSToby 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 */ 6993d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 6994d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 69959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 69969566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 6997d3d1a6afSToby Isaac } 6998d3d1a6afSToby Isaac newP += bDof; 6999d3d1a6afSToby Isaac 70006ecaa68aSToby Isaac if (outValues) { 7001d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 7002d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 70039566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p])); 7004d3d1a6afSToby Isaac } 7005d3d1a6afSToby Isaac } 70066ecaa68aSToby Isaac } 7007d3d1a6afSToby Isaac else { 7008d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7009d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7010d3d1a6afSToby Isaac newP++; 7011d3d1a6afSToby Isaac } 7012d3d1a6afSToby Isaac } 7013d3d1a6afSToby Isaac } else { 7014d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7015d3d1a6afSToby Isaac PetscInt b = points[2*p]; 7016d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 70174b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7018d3d1a6afSToby Isaac 70199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 70204b2f2278SToby Isaac if (!bSecDof) { 70214b2f2278SToby Isaac continue; 70224b2f2278SToby Isaac } 7023d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 70249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7025d3d1a6afSToby Isaac } 7026d3d1a6afSToby Isaac if (bDof) { 7027d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7028d3d1a6afSToby Isaac 70299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 70309566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7031d3d1a6afSToby Isaac 70329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset (aSec, b, &bOff)); 7033d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7034d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7035d3d1a6afSToby Isaac 7036d3d1a6afSToby 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 */ 7037d3d1a6afSToby Isaac 7038d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7039d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70419566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7042d3d1a6afSToby Isaac } 7043d3d1a6afSToby Isaac newP += bDof; 7044d3d1a6afSToby Isaac 7045d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 70466ecaa68aSToby Isaac if (outValues) { 70479566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p])); 7048d3d1a6afSToby Isaac } 70496ecaa68aSToby Isaac } 7050d3d1a6afSToby Isaac else { 7051d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7052d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7053d3d1a6afSToby Isaac newP++; 7054d3d1a6afSToby Isaac } 7055d3d1a6afSToby Isaac } 7056d3d1a6afSToby Isaac } 7057d3d1a6afSToby Isaac 70586ecaa68aSToby Isaac if (outValues) { 70599566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 70609566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues,newNumIndices*numIndices)); 7061d3d1a6afSToby Isaac /* multiply constraints on the right */ 7062d3d1a6afSToby Isaac if (numFields) { 7063d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7064d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7065d3d1a6afSToby Isaac 7066d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7067d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7068d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7069d3d1a6afSToby Isaac PetscInt c, r, k; 7070d3d1a6afSToby Isaac PetscInt dof; 7071d3d1a6afSToby Isaac 70729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,b,f,&dof)); 70734b2f2278SToby Isaac if (!dof) { 70744b2f2278SToby Isaac continue; 70754b2f2278SToby Isaac } 7076d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7077d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7078d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7079d3d1a6afSToby Isaac 7080d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7081d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7082d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 70834acb8e1eSToby Isaac tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7084d3d1a6afSToby Isaac } 7085d3d1a6afSToby Isaac } 7086d3d1a6afSToby Isaac } 7087d3d1a6afSToby Isaac } 7088d3d1a6afSToby Isaac else { 7089d3d1a6afSToby Isaac /* copy this column as is */ 7090d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7091d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7092d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7093d3d1a6afSToby Isaac } 7094d3d1a6afSToby Isaac } 7095d3d1a6afSToby Isaac } 7096d3d1a6afSToby Isaac oldOff += dof; 7097d3d1a6afSToby Isaac } 7098d3d1a6afSToby Isaac } 7099d3d1a6afSToby Isaac } 7100d3d1a6afSToby Isaac else { 7101d3d1a6afSToby Isaac PetscInt oldOff = 0; 7102d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7103d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7104d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7105d3d1a6afSToby Isaac PetscInt c, r, k; 7106d3d1a6afSToby Isaac PetscInt dof; 7107d3d1a6afSToby Isaac 71089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&dof)); 71094b2f2278SToby Isaac if (!dof) { 71104b2f2278SToby Isaac continue; 71114b2f2278SToby Isaac } 7112d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7113d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7114d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7115d3d1a6afSToby Isaac 7116d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7117d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7118d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7119d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7120d3d1a6afSToby Isaac } 7121d3d1a6afSToby Isaac } 7122d3d1a6afSToby Isaac } 7123d3d1a6afSToby Isaac } 7124d3d1a6afSToby Isaac else { 7125d3d1a6afSToby Isaac /* copy this column as is */ 7126d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7127d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7128d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7129d3d1a6afSToby Isaac } 7130d3d1a6afSToby Isaac } 7131d3d1a6afSToby Isaac } 7132d3d1a6afSToby Isaac oldOff += dof; 7133d3d1a6afSToby Isaac } 7134d3d1a6afSToby Isaac } 7135d3d1a6afSToby Isaac 71366ecaa68aSToby Isaac if (multiplyLeft) { 71379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues)); 71389566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues,newNumIndices*newNumIndices)); 7139d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7140d3d1a6afSToby Isaac if (numFields) { 7141d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7142d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7143d3d1a6afSToby Isaac 7144d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7145d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7146d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7147d3d1a6afSToby Isaac PetscInt c, r, k; 7148d3d1a6afSToby Isaac PetscInt dof; 7149d3d1a6afSToby Isaac 71509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,b,f,&dof)); 7151d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7152d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7153d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7154d3d1a6afSToby Isaac 7155d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7156d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7157d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7158d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7159d3d1a6afSToby Isaac } 7160d3d1a6afSToby Isaac } 7161d3d1a6afSToby Isaac } 7162d3d1a6afSToby Isaac } 7163d3d1a6afSToby Isaac else { 7164d3d1a6afSToby Isaac /* copy this row as is */ 7165d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7166d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7167d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7168d3d1a6afSToby Isaac } 7169d3d1a6afSToby Isaac } 7170d3d1a6afSToby Isaac } 7171d3d1a6afSToby Isaac oldOff += dof; 7172d3d1a6afSToby Isaac } 7173d3d1a6afSToby Isaac } 7174d3d1a6afSToby Isaac } 7175d3d1a6afSToby Isaac else { 7176d3d1a6afSToby Isaac PetscInt oldOff = 0; 7177d3d1a6afSToby Isaac 7178d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7179d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7180d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7181d3d1a6afSToby Isaac PetscInt c, r, k; 7182d3d1a6afSToby Isaac PetscInt dof; 7183d3d1a6afSToby Isaac 71849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&dof)); 7185d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7186d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7187d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7188d3d1a6afSToby Isaac 7189d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7190d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7191d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7192d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7193d3d1a6afSToby Isaac } 7194d3d1a6afSToby Isaac } 7195d3d1a6afSToby Isaac } 7196d3d1a6afSToby Isaac } 7197d3d1a6afSToby Isaac else { 7198d3d1a6afSToby Isaac /* copy this row as is */ 71999fc93327SToby Isaac for (r = 0; r < dof; r++) { 7200d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7201d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7202d3d1a6afSToby Isaac } 7203d3d1a6afSToby Isaac } 7204d3d1a6afSToby Isaac } 7205d3d1a6afSToby Isaac oldOff += dof; 7206d3d1a6afSToby Isaac } 7207d3d1a6afSToby Isaac } 7208d3d1a6afSToby Isaac 72099566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 72106ecaa68aSToby Isaac } 72116ecaa68aSToby Isaac else { 72126ecaa68aSToby Isaac newValues = tmpValues; 72136ecaa68aSToby Isaac } 72146ecaa68aSToby Isaac } 72156ecaa68aSToby Isaac 7216d3d1a6afSToby Isaac /* clean up */ 72179566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices)); 72189566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 72196ecaa68aSToby Isaac 7220d3d1a6afSToby Isaac if (numFields) { 7221d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 72229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 72239566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 72249566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 7225d3d1a6afSToby Isaac } 7226d3d1a6afSToby Isaac } 7227d3d1a6afSToby Isaac else { 72289566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 72299566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 72309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0])); 7231d3d1a6afSToby Isaac } 72329566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 7233d3d1a6afSToby Isaac 7234d3d1a6afSToby Isaac /* output */ 72356ecaa68aSToby Isaac if (outPoints) { 7236d3d1a6afSToby Isaac *outPoints = newPoints; 72376ecaa68aSToby Isaac } 72386ecaa68aSToby Isaac else { 72399566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 72406ecaa68aSToby Isaac } 724131620726SToby Isaac if (outValues) { 7242d3d1a6afSToby Isaac *outValues = newValues; 72436ecaa68aSToby Isaac } 72446ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 7245d3d1a6afSToby Isaac offsets[f] = newOffsets[f]; 7246d3d1a6afSToby Isaac } 7247d3d1a6afSToby Isaac PetscFunctionReturn(0); 7248d3d1a6afSToby Isaac } 7249d3d1a6afSToby Isaac 72504a1e0b3eSMatthew G. Knepley /*@C 725171f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 72527cd05799SMatthew G. Knepley 72537cd05799SMatthew G. Knepley Not collective 72547cd05799SMatthew G. Knepley 72557cd05799SMatthew G. Knepley Input Parameters: 72567cd05799SMatthew G. Knepley + dm - The DM 725771f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 725871f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 725971f0bbf9SMatthew G. Knepley . point - The point defining the closure 726071f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 72617cd05799SMatthew G. Knepley 726271f0bbf9SMatthew G. Knepley Output Parameters: 726371f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 726471f0bbf9SMatthew G. Knepley . indices - The dof indices 726571f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 726671f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 72677cd05799SMatthew G. Knepley 726836fa2b79SJed Brown Notes: 726936fa2b79SJed Brown Must call DMPlexRestoreClosureIndices() to free allocated memory 727036fa2b79SJed Brown 727136fa2b79SJed Brown If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 727236fa2b79SJed Brown of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 727336fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 727436fa2b79SJed Brown indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 727536fa2b79SJed Brown indices (with the above semantics) are implied. 72767cd05799SMatthew G. Knepley 72777cd05799SMatthew G. Knepley Level: advanced 72787cd05799SMatthew G. Knepley 7279db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 72804a1e0b3eSMatthew G. Knepley @*/ 728171f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 728271f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 72837773e69fSMatthew G. Knepley { 728471f0bbf9SMatthew G. Knepley /* Closure ordering */ 72857773e69fSMatthew G. Knepley PetscSection clSection; 72867773e69fSMatthew G. Knepley IS clPoints; 728771f0bbf9SMatthew G. Knepley const PetscInt *clp; 728871f0bbf9SMatthew G. Knepley PetscInt *points; 728971f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 729071f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 72914acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 729271f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 729371f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 729471f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 729571f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 729671f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 729771f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 729871f0bbf9SMatthew G. Knepley 729971f0bbf9SMatthew G. Knepley PetscInt *idx; 730071f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 730171f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 73027773e69fSMatthew G. Knepley 730371f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 73047773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 73057773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 730636fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7307dadcf809SJacob Faibussowitsch if (numIndices) PetscValidIntPointer(numIndices, 6); 730871f0bbf9SMatthew G. Knepley if (indices) PetscValidPointer(indices, 7); 7309dadcf809SJacob Faibussowitsch if (outOffsets) PetscValidIntPointer(outOffsets, 8); 731071f0bbf9SMatthew G. Knepley if (values) PetscValidPointer(values, 9); 73119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 731263a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 73139566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 731471f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 73159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7316c459fbc1SJed Brown if (useClPerm) { 7317c459fbc1SJed Brown PetscInt depth, clsize; 73189566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7319c459fbc1SJed Brown for (clsize=0,p=0; p<Ncl; p++) { 7320c459fbc1SJed Brown PetscInt dof; 73219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 7322c459fbc1SJed Brown clsize += dof; 7323c459fbc1SJed Brown } 73249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 7325c459fbc1SJed Brown } 732671f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 732771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl*2; p += 2) { 73287773e69fSMatthew G. Knepley PetscInt dof, fdof; 73297773e69fSMatthew G. Knepley 73309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 73317773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 73329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 73337773e69fSMatthew G. Knepley offsets[f+1] += fdof; 73347773e69fSMatthew G. Knepley } 733571f0bbf9SMatthew G. Knepley Ni += dof; 73367773e69fSMatthew G. Knepley } 73377773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 73381dca8a05SBarry 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); 733971f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 734071f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73419566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73429566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 734371f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 734471f0bbf9SMatthew G. Knepley if (values && flips[f]) { 734571f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 73466ecaa68aSToby Isaac 734771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 734871f0bbf9SMatthew G. Knepley PetscInt pnt = points[2*p], fdof; 734971f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 735071f0bbf9SMatthew G. Knepley 73519566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 73529566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 735371f0bbf9SMatthew G. Knepley if (flip) { 735471f0bbf9SMatthew G. Knepley PetscInt i, j, k; 735571f0bbf9SMatthew G. Knepley 735671f0bbf9SMatthew G. Knepley if (!valCopy) { 73579566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 735871f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 735971f0bbf9SMatthew G. Knepley *values = valCopy; 736071f0bbf9SMatthew G. Knepley } 736171f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 736271f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 736371f0bbf9SMatthew G. Knepley 736471f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 736571f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 736671f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 73676ecaa68aSToby Isaac } 73686ecaa68aSToby Isaac } 736971f0bbf9SMatthew G. Knepley } 737071f0bbf9SMatthew G. Knepley foffset += fdof; 737171f0bbf9SMatthew G. Knepley } 737271f0bbf9SMatthew G. Knepley } 737371f0bbf9SMatthew G. Knepley } 737471f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 73759566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 737671f0bbf9SMatthew G. Knepley if (NclC) { 73779566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 737871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73799566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73809566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 738171f0bbf9SMatthew G. Knepley } 738271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73839566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 73849566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 738571f0bbf9SMatthew G. Knepley } 73869566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 738771f0bbf9SMatthew G. Knepley Ncl = NclC; 738871f0bbf9SMatthew G. Knepley Ni = NiC; 738971f0bbf9SMatthew G. Knepley points = pointsC; 739071f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 739171f0bbf9SMatthew G. Knepley } 739271f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 73939566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 739471f0bbf9SMatthew G. Knepley if (Nf) { 739571f0bbf9SMatthew G. Knepley PetscInt idxOff; 739671f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 739771f0bbf9SMatthew G. Knepley 739871f0bbf9SMatthew G. Knepley if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 73999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 740071f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 740171f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 740271f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 740371f0bbf9SMatthew G. Knepley 74049566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 74057773e69fSMatthew G. Knepley } 74067773e69fSMatthew G. Knepley } else { 740771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 740871f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 740971f0bbf9SMatthew G. Knepley 74109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 741171f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 741271f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 741371f0bbf9SMatthew G. Knepley * global section. */ 74149566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 741571f0bbf9SMatthew G. Knepley } 741671f0bbf9SMatthew G. Knepley } 741771f0bbf9SMatthew G. Knepley } else { 741871f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 741971f0bbf9SMatthew G. Knepley 742071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 742171f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 74224acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 74234acb8e1eSToby Isaac 74249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 742571f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 742671f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 74279566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 74287773e69fSMatthew G. Knepley } 74297773e69fSMatthew G. Knepley } 743071f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 743171f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74329566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 74339566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 74344acb8e1eSToby Isaac } 743571f0bbf9SMatthew G. Knepley if (NclC) { 74369566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC)); 74377773e69fSMatthew G. Knepley } else { 74389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 74397773e69fSMatthew G. Knepley } 744071f0bbf9SMatthew G. Knepley 744171f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 744271f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 74437773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74447773e69fSMatthew G. Knepley } 74457773e69fSMatthew G. Knepley 74467cd05799SMatthew G. Knepley /*@C 744771f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 74487cd05799SMatthew G. Knepley 74497cd05799SMatthew G. Knepley Not collective 74507cd05799SMatthew G. Knepley 74517cd05799SMatthew G. Knepley Input Parameters: 74527cd05799SMatthew G. Knepley + dm - The DM 745371f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 745471f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 745571f0bbf9SMatthew G. Knepley . point - The point defining the closure 745671f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 745771f0bbf9SMatthew G. Knepley 745871f0bbf9SMatthew G. Knepley Output Parameters: 745971f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 746071f0bbf9SMatthew G. Knepley . indices - The dof indices 746171f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 746271f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 746371f0bbf9SMatthew G. Knepley 746471f0bbf9SMatthew G. Knepley Notes: 746571f0bbf9SMatthew G. Knepley If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 746671f0bbf9SMatthew G. Knepley 746771f0bbf9SMatthew G. Knepley If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 746871f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 746971f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 747071f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 747171f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 74727cd05799SMatthew G. Knepley 74737cd05799SMatthew G. Knepley Level: advanced 74747cd05799SMatthew G. Knepley 7475db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 74767cd05799SMatthew G. Knepley @*/ 747771f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 747871f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 74797773e69fSMatthew G. Knepley { 74807773e69fSMatthew G. Knepley PetscFunctionBegin; 74817773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7482064a246eSJacob Faibussowitsch PetscValidPointer(indices, 7); 74839566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 74847773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74857773e69fSMatthew G. Knepley } 74867773e69fSMatthew G. Knepley 74877f5d1fdeSMatthew G. Knepley /*@C 74887f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 74897f5d1fdeSMatthew G. Knepley 74907f5d1fdeSMatthew G. Knepley Not collective 74917f5d1fdeSMatthew G. Knepley 74927f5d1fdeSMatthew G. Knepley Input Parameters: 74937f5d1fdeSMatthew G. Knepley + dm - The DM 7494ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section 7495ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section 74967f5d1fdeSMatthew G. Knepley . A - The matrix 7497eaf898f9SPatrick Sanan . point - The point in the DM 74987f5d1fdeSMatthew G. Knepley . values - The array of values 74997f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75007f5d1fdeSMatthew G. Knepley 75017f5d1fdeSMatthew G. Knepley Fortran Notes: 75027f5d1fdeSMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 75037f5d1fdeSMatthew G. Knepley 75047f5d1fdeSMatthew G. Knepley Level: intermediate 75057f5d1fdeSMatthew G. Knepley 7506db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 75077f5d1fdeSMatthew G. Knepley @*/ 75087c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7509552f7358SJed Brown { 7510552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7511552f7358SJed Brown PetscInt *indices; 751271f0bbf9SMatthew G. Knepley PetscInt numIndices; 751371f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 7514552f7358SJed Brown PetscErrorCode ierr; 7515552f7358SJed Brown 7516552f7358SJed Brown PetscFunctionBegin; 7517552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 75189566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 75193dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 75209566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 75213dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 75223dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7523552f7358SJed Brown 75249566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75250d644c17SKarl Rupp 75269566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 7527d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 75284a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7529552f7358SJed Brown if (ierr) { 7530552f7358SJed Brown PetscMPIInt rank; 7531552f7358SJed Brown 75329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 75339566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 75349566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 75359566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75369566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 7537c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7538552f7358SJed Brown } 75394a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 75404a1e0b3eSMatthew G. Knepley PetscInt i; 75419566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 754263a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 75439566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 75444a1e0b3eSMatthew G. Knepley } 754571f0bbf9SMatthew G. Knepley 75469566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75479566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 754871f0bbf9SMatthew G. Knepley PetscFunctionReturn(0); 75494acb8e1eSToby Isaac } 755071f0bbf9SMatthew G. Knepley 75514a1e0b3eSMatthew G. Knepley /*@C 75524a1e0b3eSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 75534a1e0b3eSMatthew G. Knepley 75544a1e0b3eSMatthew G. Knepley Not collective 75554a1e0b3eSMatthew G. Knepley 75564a1e0b3eSMatthew G. Knepley Input Parameters: 75574a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields 75584a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 75594a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 75604a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields 75614a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 75624a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 75634a1e0b3eSMatthew G. Knepley . A - The matrix 75644a1e0b3eSMatthew G. Knepley . point - The point in the DMs 75654a1e0b3eSMatthew G. Knepley . values - The array of values 75664a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75674a1e0b3eSMatthew G. Knepley 75684a1e0b3eSMatthew G. Knepley Level: intermediate 75694a1e0b3eSMatthew G. Knepley 7570db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 75714a1e0b3eSMatthew G. Knepley @*/ 757271f0bbf9SMatthew 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) 757371f0bbf9SMatthew G. Knepley { 757471f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmRow->data; 757571f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 757671f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 757771f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 757871f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 757971f0bbf9SMatthew G. Knepley 758071f0bbf9SMatthew G. Knepley PetscFunctionBegin; 758171f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 75829566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 758371f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 75849566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 758571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 758671f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 75879566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 758871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 75899566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 759071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 759171f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 759271f0bbf9SMatthew G. Knepley 75939566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 75949566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 759571f0bbf9SMatthew G. Knepley 75969566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 7597d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 75984a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 759971f0bbf9SMatthew G. Knepley if (ierr) { 760071f0bbf9SMatthew G. Knepley PetscMPIInt rank; 760171f0bbf9SMatthew G. Knepley 76029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 76039566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 76049566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 76059566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values)); 76079566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7608d3d1a6afSToby Isaac } 760971f0bbf9SMatthew G. Knepley 76109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76119566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 76129566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7613552f7358SJed Brown PetscFunctionReturn(0); 7614552f7358SJed Brown } 7615552f7358SJed Brown 7616de41b84cSMatthew 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) 7617de41b84cSMatthew G. Knepley { 7618de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmf->data; 7619de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 7620de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 7621de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 762217c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7623de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 7624412e9a14SMatthew G. Knepley DMPolytopeType ct; 76254ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7626de41b84cSMatthew G. Knepley PetscErrorCode ierr; 7627de41b84cSMatthew G. Knepley 7628de41b84cSMatthew G. Knepley PetscFunctionBegin; 7629de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7630de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 76319566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 7632de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 76339566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 7634de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 76359566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 7636de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 76379566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 7638de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7639de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 76409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 764163a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 76429566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 76439566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 7644de41b84cSMatthew G. Knepley /* Column indices */ 76459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 76464ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 7647de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 7648de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 76499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 7650de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7651de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7652de41b84cSMatthew G. Knepley cpoints[q*2] = cpoints[p]; 7653de41b84cSMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 7654de41b84cSMatthew G. Knepley ++q; 7655de41b84cSMatthew G. Knepley } 7656de41b84cSMatthew G. Knepley } 7657de41b84cSMatthew G. Knepley numCPoints = q; 7658de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7659de41b84cSMatthew G. Knepley PetscInt fdof; 7660de41b84cSMatthew G. Knepley 76619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 76624ca5e9f5SMatthew G. Knepley if (!dof) continue; 7663de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 76649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 7665de41b84cSMatthew G. Knepley coffsets[f+1] += fdof; 7666de41b84cSMatthew G. Knepley } 7667de41b84cSMatthew G. Knepley numCIndices += dof; 7668de41b84cSMatthew G. Knepley } 7669de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7670de41b84cSMatthew G. Knepley /* Row indices */ 76719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7672412e9a14SMatthew G. Knepley { 7673012bc364SMatthew G. Knepley DMPlexTransform tr; 7674012bc364SMatthew G. Knepley DMPolytopeType *rct; 7675012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7676012bc364SMatthew G. Knepley 76779566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 76789566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 76799566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7680012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 76819566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7682412e9a14SMatthew G. Knepley } 76839566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 7684de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 7685de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 76869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 7687de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 76889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 7689de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 7690de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 76919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 76924ca5e9f5SMatthew G. Knepley if (!dof) continue; 76934ca5e9f5SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 76944ca5e9f5SMatthew G. Knepley if (s < q) continue; 7695de41b84cSMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 7696de41b84cSMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 7697de41b84cSMatthew G. Knepley ++q; 7698de41b84cSMatthew G. Knepley } 7699de41b84cSMatthew G. Knepley } 77009566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 7701de41b84cSMatthew G. Knepley } 7702de41b84cSMatthew G. Knepley numFPoints = q; 7703de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7704de41b84cSMatthew G. Knepley PetscInt fdof; 7705de41b84cSMatthew G. Knepley 77069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 77074ca5e9f5SMatthew G. Knepley if (!dof) continue; 7708de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 77099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 7710de41b84cSMatthew G. Knepley foffsets[f+1] += fdof; 7711de41b84cSMatthew G. Knepley } 7712de41b84cSMatthew G. Knepley numFIndices += dof; 7713de41b84cSMatthew G. Knepley } 7714de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7715de41b84cSMatthew G. Knepley 77161dca8a05SBarry 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); 77171dca8a05SBarry 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); 77189566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77199566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7720de41b84cSMatthew G. Knepley if (numFields) { 77214acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 77224acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 77234acb8e1eSToby Isaac 77244acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7727de41b84cSMatthew G. Knepley } 77284acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 77299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77309566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 77314acb8e1eSToby Isaac } 77324acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 77339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77349566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 77354acb8e1eSToby Isaac } 77364acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77379566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77389566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7739de41b84cSMatthew G. Knepley } 7740de41b84cSMatthew G. Knepley } else { 77414acb8e1eSToby Isaac const PetscInt **permsF = NULL; 77424acb8e1eSToby Isaac const PetscInt **permsC = NULL; 77434acb8e1eSToby Isaac 77449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 77464acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 77474acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 77484acb8e1eSToby Isaac 77499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77509566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 7751de41b84cSMatthew G. Knepley } 77524acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 77534acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 77544acb8e1eSToby Isaac 77559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77569566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 7757de41b84cSMatthew G. Knepley } 77589566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77599566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 7760de41b84cSMatthew G. Knepley } 77619566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77624acb8e1eSToby Isaac /* TODO: flips */ 7763d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 7764de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7765de41b84cSMatthew G. Knepley if (ierr) { 7766de41b84cSMatthew G. Knepley PetscMPIInt rank; 7767de41b84cSMatthew G. Knepley 77689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 77699566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 77709566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77719566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77729566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7773de41b84cSMatthew G. Knepley } 77749566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 77759566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 77769566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77779566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7778de41b84cSMatthew G. Knepley PetscFunctionReturn(0); 7779de41b84cSMatthew G. Knepley } 7780de41b84cSMatthew G. Knepley 77817c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 77827c927364SMatthew G. Knepley { 77837c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 77847c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 77857c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 778617c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7787412e9a14SMatthew G. Knepley DMPolytopeType ct; 77887c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 77897c927364SMatthew G. Knepley 77907c927364SMatthew G. Knepley PetscFunctionBegin; 77917c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 77927c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 77939566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 77947c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 77959566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 77967c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 77979566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 77987c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 77999566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 78007c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 78019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 780263a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 78039566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 78049566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 78057c927364SMatthew G. Knepley /* Column indices */ 78069566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78077c927364SMatthew G. Knepley maxFPoints = numCPoints; 78087c927364SMatthew G. Knepley /* Compress out points not in the section */ 78097c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 78109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 78117c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 78127c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 78137c927364SMatthew G. Knepley cpoints[q*2] = cpoints[p]; 78147c927364SMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 78157c927364SMatthew G. Knepley ++q; 78167c927364SMatthew G. Knepley } 78177c927364SMatthew G. Knepley } 78187c927364SMatthew G. Knepley numCPoints = q; 78197c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 78207c927364SMatthew G. Knepley PetscInt fdof; 78217c927364SMatthew G. Knepley 78229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 78237c927364SMatthew G. Knepley if (!dof) continue; 78247c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 78267c927364SMatthew G. Knepley coffsets[f+1] += fdof; 78277c927364SMatthew G. Knepley } 78287c927364SMatthew G. Knepley numCIndices += dof; 78297c927364SMatthew G. Knepley } 78307c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 78317c927364SMatthew G. Knepley /* Row indices */ 78329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7833412e9a14SMatthew G. Knepley { 7834012bc364SMatthew G. Knepley DMPlexTransform tr; 7835012bc364SMatthew G. Knepley DMPolytopeType *rct; 7836012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7837012bc364SMatthew G. Knepley 78389566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 78399566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 78409566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7841012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 78429566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7843412e9a14SMatthew G. Knepley } 78449566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 78457c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 78467c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 78479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 78487c927364SMatthew G. Knepley /* Compress out points not in the section */ 78499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 78507c927364SMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 78517c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 78529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 78537c927364SMatthew G. Knepley if (!dof) continue; 78547c927364SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 78557c927364SMatthew G. Knepley if (s < q) continue; 78567c927364SMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 78577c927364SMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 78587c927364SMatthew G. Knepley ++q; 78597c927364SMatthew G. Knepley } 78607c927364SMatthew G. Knepley } 78619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 78627c927364SMatthew G. Knepley } 78637c927364SMatthew G. Knepley numFPoints = q; 78647c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 78657c927364SMatthew G. Knepley PetscInt fdof; 78667c927364SMatthew G. Knepley 78679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 78687c927364SMatthew G. Knepley if (!dof) continue; 78697c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 78717c927364SMatthew G. Knepley foffsets[f+1] += fdof; 78727c927364SMatthew G. Knepley } 78737c927364SMatthew G. Knepley numFIndices += dof; 78747c927364SMatthew G. Knepley } 78757c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 78767c927364SMatthew G. Knepley 78771dca8a05SBarry 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); 78781dca8a05SBarry 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); 78797c927364SMatthew G. Knepley if (numFields) { 78804acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 78814acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 78824acb8e1eSToby Isaac 78834acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 78849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 78859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 78867c927364SMatthew G. Knepley } 78874acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 78889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 78899566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 78904acb8e1eSToby Isaac } 78914acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 78929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 78939566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 78944acb8e1eSToby Isaac } 78954acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 78969566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 78979566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 78987c927364SMatthew G. Knepley } 78997c927364SMatthew G. Knepley } else { 79004acb8e1eSToby Isaac const PetscInt **permsF = NULL; 79014acb8e1eSToby Isaac const PetscInt **permsC = NULL; 79024acb8e1eSToby Isaac 79039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79054acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 79064acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 79074acb8e1eSToby Isaac 79089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 79099566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 79107c927364SMatthew G. Knepley } 79114acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 79124acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 79134acb8e1eSToby Isaac 79149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79159566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 79167c927364SMatthew G. Knepley } 79179566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79189566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79197c927364SMatthew G. Knepley } 79209566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 79219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 79227c927364SMatthew G. Knepley PetscFunctionReturn(0); 79237c927364SMatthew G. Knepley } 79247c927364SMatthew G. Knepley 79257cd05799SMatthew G. Knepley /*@C 79267cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 79277cd05799SMatthew G. Knepley 79287cd05799SMatthew G. Knepley Input Parameter: 79297cd05799SMatthew G. Knepley . dm - The DMPlex object 79307cd05799SMatthew G. Knepley 79317cd05799SMatthew G. Knepley Output Parameter: 79327cd05799SMatthew G. Knepley . cellHeight - The height of a cell 79337cd05799SMatthew G. Knepley 79347cd05799SMatthew G. Knepley Level: developer 79357cd05799SMatthew G. Knepley 7936db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()` 79377cd05799SMatthew G. Knepley @*/ 7938552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7939552f7358SJed Brown { 7940552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7941552f7358SJed Brown 7942552f7358SJed Brown PetscFunctionBegin; 7943552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7944dadcf809SJacob Faibussowitsch PetscValidIntPointer(cellHeight, 2); 7945552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 7946552f7358SJed Brown PetscFunctionReturn(0); 7947552f7358SJed Brown } 7948552f7358SJed Brown 79497cd05799SMatthew G. Knepley /*@C 79507cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 79517cd05799SMatthew G. Knepley 79527cd05799SMatthew G. Knepley Input Parameters: 79537cd05799SMatthew G. Knepley + dm - The DMPlex object 79547cd05799SMatthew G. Knepley - cellHeight - The height of a cell 79557cd05799SMatthew G. Knepley 79567cd05799SMatthew G. Knepley Level: developer 79577cd05799SMatthew G. Knepley 7958db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()` 79597cd05799SMatthew G. Knepley @*/ 7960552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7961552f7358SJed Brown { 7962552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7963552f7358SJed Brown 7964552f7358SJed Brown PetscFunctionBegin; 7965552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7966552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 7967552f7358SJed Brown PetscFunctionReturn(0); 7968552f7358SJed Brown } 7969552f7358SJed Brown 7970e6139122SMatthew G. Knepley /*@ 7971e6139122SMatthew G. Knepley DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7972e6139122SMatthew G. Knepley 7973e6139122SMatthew G. Knepley Input Parameter: 7974e6139122SMatthew G. Knepley . dm - The DMPlex object 7975e6139122SMatthew G. Knepley 7976e6139122SMatthew G. Knepley Output Parameters: 79772a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL 79782a9f31c0SMatthew G. Knepley - gcEnd - The upper bound on ghost cells, or NULL 7979e6139122SMatthew G. Knepley 79802a9f31c0SMatthew G. Knepley Level: advanced 7981e6139122SMatthew G. Knepley 7982db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 7983e6139122SMatthew G. Knepley @*/ 7984e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7985e6139122SMatthew G. Knepley { 7986412e9a14SMatthew G. Knepley DMLabel ctLabel; 7987e6139122SMatthew G. Knepley 7988e6139122SMatthew G. Knepley PetscFunctionBegin; 7989e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 79909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 79919566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd)); 7992e6139122SMatthew G. Knepley PetscFunctionReturn(0); 7993e6139122SMatthew G. Knepley } 7994e6139122SMatthew G. Knepley 79959886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 7996552f7358SJed Brown { 7997552f7358SJed Brown PetscSection section, globalSection; 7998552f7358SJed Brown PetscInt *numbers, p; 7999552f7358SJed Brown 8000552f7358SJed Brown PetscFunctionBegin; 80019566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 80029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8003552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, 1)); 8005552f7358SJed Brown } 80069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 80079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 80089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8009552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart])); 8011ef48cebcSMatthew G. Knepley if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8012ef48cebcSMatthew G. Knepley else numbers[p-pStart] += shift; 8013552f7358SJed Brown } 80149566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8015ef48cebcSMatthew G. Knepley if (globalSize) { 8016ef48cebcSMatthew G. Knepley PetscLayout layout; 80179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout)); 80189566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 80199566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8020ef48cebcSMatthew G. Knepley } 80219566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 80229566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 8023552f7358SJed Brown PetscFunctionReturn(0); 8024552f7358SJed Brown } 8025552f7358SJed Brown 802681ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8027552f7358SJed Brown { 8028412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8029552f7358SJed Brown 8030552f7358SJed Brown PetscFunctionBegin; 80319566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 80329566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 80339566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 80349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 803581ed3555SMatthew G. Knepley PetscFunctionReturn(0); 8036552f7358SJed Brown } 803781ed3555SMatthew G. Knepley 80388dab3259SMatthew G. Knepley /*@ 80397cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 80407cd05799SMatthew G. Knepley 80417cd05799SMatthew G. Knepley Input Parameter: 80427cd05799SMatthew G. Knepley . dm - The DMPlex object 80437cd05799SMatthew G. Knepley 80447cd05799SMatthew G. Knepley Output Parameter: 80457cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 80467cd05799SMatthew G. Knepley 80477cd05799SMatthew G. Knepley Level: developer 80487cd05799SMatthew G. Knepley 8049db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()` 80507cd05799SMatthew G. Knepley @*/ 805181ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 805281ed3555SMatthew G. Knepley { 805381ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 805481ed3555SMatthew G. Knepley 805581ed3555SMatthew G. Knepley PetscFunctionBegin; 805681ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80579566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8058552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 8059552f7358SJed Brown PetscFunctionReturn(0); 8060552f7358SJed Brown } 8061552f7358SJed Brown 806281ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 806381ed3555SMatthew G. Knepley { 8064412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 806581ed3555SMatthew G. Knepley 806681ed3555SMatthew G. Knepley PetscFunctionBegin; 806781ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 80699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 807081ed3555SMatthew G. Knepley PetscFunctionReturn(0); 807181ed3555SMatthew G. Knepley } 807281ed3555SMatthew G. Knepley 80738dab3259SMatthew G. Knepley /*@ 80746aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 80757cd05799SMatthew G. Knepley 80767cd05799SMatthew G. Knepley Input Parameter: 80777cd05799SMatthew G. Knepley . dm - The DMPlex object 80787cd05799SMatthew G. Knepley 80797cd05799SMatthew G. Knepley Output Parameter: 80807cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 80817cd05799SMatthew G. Knepley 80827cd05799SMatthew G. Knepley Level: developer 80837cd05799SMatthew G. Knepley 8084db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 80857cd05799SMatthew G. Knepley @*/ 8086552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8087552f7358SJed Brown { 8088552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 8089552f7358SJed Brown 8090552f7358SJed Brown PetscFunctionBegin; 8091552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80929566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8093552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 8094552f7358SJed Brown PetscFunctionReturn(0); 8095552f7358SJed Brown } 8096552f7358SJed Brown 80978dab3259SMatthew G. Knepley /*@ 80987cd05799SMatthew G. Knepley DMPlexCreatePointNumbering - Create a global numbering for all points on this process 80997cd05799SMatthew G. Knepley 81007cd05799SMatthew G. Knepley Input Parameter: 81017cd05799SMatthew G. Knepley . dm - The DMPlex object 81027cd05799SMatthew G. Knepley 81037cd05799SMatthew G. Knepley Output Parameter: 81047cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 81057cd05799SMatthew G. Knepley 81067cd05799SMatthew G. Knepley Level: developer 81077cd05799SMatthew G. Knepley 8108db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 81097cd05799SMatthew G. Knepley @*/ 8110ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8111ef48cebcSMatthew G. Knepley { 8112ef48cebcSMatthew G. Knepley IS nums[4]; 8113862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8114ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 8115ef48cebcSMatthew G. Knepley 8116ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8117ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 81198abc87a0SMichael Lange /* For unstratified meshes use dim instead of depth */ 81209566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 8121862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8122862913ffSStefano Zampini PetscInt end; 8123862913ffSStefano Zampini 8124862913ffSStefano Zampini depths[d] = depth-d; 81259566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 8126862913ffSStefano Zampini if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8127862913ffSStefano Zampini } 81289566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(depth+1, starts, depths)); 81291c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm))); 8130862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 81311dca8a05SBarry 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]); 8132862913ffSStefano Zampini } 8133ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8134ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8135ef48cebcSMatthew G. Knepley 81369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 81379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8138ef48cebcSMatthew G. Knepley shift += gsize; 8139ef48cebcSMatthew G. Knepley } 81409566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers)); 81419566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 8142ef48cebcSMatthew G. Knepley PetscFunctionReturn(0); 8143ef48cebcSMatthew G. Knepley } 8144ef48cebcSMatthew G. Knepley 814508a22f4bSMatthew G. Knepley /*@ 814608a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 814708a22f4bSMatthew G. Knepley 814808a22f4bSMatthew G. Knepley Input Parameter: 814908a22f4bSMatthew G. Knepley . dm - The DMPlex object 815008a22f4bSMatthew G. Knepley 815108a22f4bSMatthew G. Knepley Output Parameter: 815208a22f4bSMatthew G. Knepley . ranks - The rank field 815308a22f4bSMatthew G. Knepley 815408a22f4bSMatthew G. Knepley Options Database Keys: 815508a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 815608a22f4bSMatthew G. Knepley 815708a22f4bSMatthew G. Knepley Level: intermediate 815808a22f4bSMatthew G. Knepley 8159db781477SPatrick Sanan .seealso: `DMView()` 816008a22f4bSMatthew G. Knepley @*/ 816108a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 816208a22f4bSMatthew G. Knepley { 816308a22f4bSMatthew G. Knepley DM rdm; 816408a22f4bSMatthew G. Knepley PetscFE fe; 816508a22f4bSMatthew G. Knepley PetscScalar *r; 816608a22f4bSMatthew G. Knepley PetscMPIInt rank; 8167a55f9a55SMatthew G. Knepley DMPolytopeType ct; 816808a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8169a55f9a55SMatthew G. Knepley PetscBool simplex; 817008a22f4bSMatthew G. Knepley 817108a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8172f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8173f95ace6aSMatthew G. Knepley PetscValidPointer(ranks, 2); 81749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 81759566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 81769566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 81779566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 81789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8179a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 81809566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 81819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) fe, "rank")); 81829566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 81839566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 81849566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 81859566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 81869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *ranks, "partition")); 81879566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 818808a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 818908a22f4bSMatthew G. Knepley PetscScalar *lr; 819008a22f4bSMatthew G. Knepley 81919566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 819271f09efeSPierre Jolivet if (lr) *lr = rank; 819308a22f4bSMatthew G. Knepley } 81949566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 81959566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 819608a22f4bSMatthew G. Knepley PetscFunctionReturn(0); 819708a22f4bSMatthew G. Knepley } 819808a22f4bSMatthew G. Knepley 8199ca8062c8SMatthew G. Knepley /*@ 820018e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 820118e14f0cSMatthew G. Knepley 820218e14f0cSMatthew G. Knepley Input Parameters: 820318e14f0cSMatthew G. Knepley + dm - The DMPlex 820418e14f0cSMatthew G. Knepley - label - The DMLabel 820518e14f0cSMatthew G. Knepley 820618e14f0cSMatthew G. Knepley Output Parameter: 820718e14f0cSMatthew G. Knepley . val - The label value field 820818e14f0cSMatthew G. Knepley 820918e14f0cSMatthew G. Knepley Options Database Keys: 821018e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 821118e14f0cSMatthew G. Knepley 821218e14f0cSMatthew G. Knepley Level: intermediate 821318e14f0cSMatthew G. Knepley 8214db781477SPatrick Sanan .seealso: `DMView()` 821518e14f0cSMatthew G. Knepley @*/ 821618e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 821718e14f0cSMatthew G. Knepley { 821818e14f0cSMatthew G. Knepley DM rdm; 821918e14f0cSMatthew G. Knepley PetscFE fe; 822018e14f0cSMatthew G. Knepley PetscScalar *v; 822118e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 822218e14f0cSMatthew G. Knepley 822318e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 822418e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 822518e14f0cSMatthew G. Knepley PetscValidPointer(label, 2); 822618e14f0cSMatthew G. Knepley PetscValidPointer(val, 3); 82279566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 82289566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 82299566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 82309566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) fe, "label_value")); 82319566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 82329566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 82339566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 82349566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82359566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 82369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *val, "label_value")); 82379566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 823818e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 823918e14f0cSMatthew G. Knepley PetscScalar *lv; 824018e14f0cSMatthew G. Knepley PetscInt cval; 824118e14f0cSMatthew G. Knepley 82429566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 82439566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 824418e14f0cSMatthew G. Knepley *lv = cval; 824518e14f0cSMatthew G. Knepley } 82469566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 82479566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 824818e14f0cSMatthew G. Knepley PetscFunctionReturn(0); 824918e14f0cSMatthew G. Knepley } 825018e14f0cSMatthew G. Knepley 825118e14f0cSMatthew G. Knepley /*@ 8252ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8253ca8062c8SMatthew G. Knepley 825469916449SMatthew G. Knepley Input Parameter: 825569916449SMatthew G. Knepley . dm - The DMPlex object 8256ca8062c8SMatthew G. Knepley 825795eb5ee5SVaclav Hapla Notes: 825895eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 825995eb5ee5SVaclav Hapla 826095eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8261ca8062c8SMatthew G. Knepley 8262ca8062c8SMatthew G. Knepley Level: developer 8263ca8062c8SMatthew G. Knepley 8264db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8265ca8062c8SMatthew G. Knepley @*/ 8266ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm) 8267ca8062c8SMatthew G. Knepley { 8268ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8269ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8270ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 827157beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 827257beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8273ca8062c8SMatthew G. Knepley 8274ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8275ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 82769566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 82779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 82789566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8279ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 82809566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8281ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 82829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 82839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8284ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 828542e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 828642e66dfaSMatthew G. Knepley PetscInt d; 828742e66dfaSMatthew G. Knepley for (d = c-1; d >= 0; --d) { 828842e66dfaSMatthew G. Knepley if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 828942e66dfaSMatthew G. Knepley } 82909566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 82919566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8292ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8293ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8294ca8062c8SMatthew G. Knepley } 829542e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s+1] != p))) { 829663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 8297ca8062c8SMatthew G. Knepley for (s = 0; s < coneSize; ++s) { 829863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 8299ca8062c8SMatthew G. Knepley } 83009566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 830163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 8302ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 830363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 8304ca8062c8SMatthew G. Knepley } 83059566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 830663a3b9bcSJacob 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]); 830763a3b9bcSJacob Faibussowitsch else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8308ca8062c8SMatthew G. Knepley } 830942e66dfaSMatthew G. Knepley } 83109566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 831157beb4faSStefano Zampini if (p != pp) { storagecheck = PETSC_FALSE; continue; } 83129566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 83139566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8314ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 83159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 83169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8317ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 83189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 831957beb4faSStefano Zampini if (cone[c] != pp) { c = 0; break; } 8320ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8321ca8062c8SMatthew G. Knepley } 8322ca8062c8SMatthew G. Knepley if (c >= coneSize) { 832363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 8324ca8062c8SMatthew G. Knepley for (c = 0; c < supportSize; ++c) { 832563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 8326ca8062c8SMatthew G. Knepley } 83279566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 832863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 8329ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 833063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 8331ca8062c8SMatthew G. Knepley } 83329566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 833363a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8334ca8062c8SMatthew G. Knepley } 8335ca8062c8SMatthew G. Knepley } 8336ca8062c8SMatthew G. Knepley } 833757beb4faSStefano Zampini if (storagecheck) { 83389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 83399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 834063a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 834157beb4faSStefano Zampini } 8342ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8343ca8062c8SMatthew G. Knepley } 8344ca8062c8SMatthew G. Knepley 8345412e9a14SMatthew G. Knepley /* 8346412e9a14SMatthew 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. 8347412e9a14SMatthew G. Knepley */ 8348412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8349412e9a14SMatthew G. Knepley { 8350412e9a14SMatthew G. Knepley DMPolytopeType cct; 8351412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8352412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8353412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8354412e9a14SMatthew G. Knepley 8355412e9a14SMatthew G. Knepley PetscFunctionBegin; 8356412e9a14SMatthew G. Knepley *unsplit = 0; 8357412e9a14SMatthew G. Knepley switch (ct) { 8358b5a892a1SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 8359b5a892a1SMatthew G. Knepley ptpoints[npt++] = c; 8360b5a892a1SMatthew G. Knepley break; 8361412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 83629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 83639566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8364412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 8366412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8367412e9a14SMatthew G. Knepley } 8368412e9a14SMatthew G. Knepley break; 8369412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8370412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 83719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 83729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8373412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83749566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 83759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8376412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 83779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8378412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8379412e9a14SMatthew G. Knepley PetscInt p; 8380412e9a14SMatthew G. Knepley for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8381412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8382412e9a14SMatthew G. Knepley } 8383412e9a14SMatthew G. Knepley } 8384412e9a14SMatthew G. Knepley } 8385412e9a14SMatthew G. Knepley break; 8386412e9a14SMatthew G. Knepley default: break; 8387412e9a14SMatthew G. Knepley } 8388412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 83899566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8390412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8391412e9a14SMatthew G. Knepley } 8392412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 8393412e9a14SMatthew G. Knepley } 8394412e9a14SMatthew G. Knepley 8395ca8062c8SMatthew G. Knepley /*@ 8396ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8397ca8062c8SMatthew G. Knepley 8398ca8062c8SMatthew G. Knepley Input Parameters: 8399ca8062c8SMatthew G. Knepley + dm - The DMPlex object 840058723a97SMatthew G. Knepley - cellHeight - Normally 0 8401ca8062c8SMatthew G. Knepley 840295eb5ee5SVaclav Hapla Notes: 840395eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 840425c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 8405ca8062c8SMatthew G. Knepley 840695eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 840795eb5ee5SVaclav Hapla 8408ca8062c8SMatthew G. Knepley Level: developer 8409ca8062c8SMatthew G. Knepley 8410db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8411ca8062c8SMatthew G. Knepley @*/ 841225c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8413ca8062c8SMatthew G. Knepley { 8414412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 8415412e9a14SMatthew G. Knepley DMPolytopeType ct; 8416412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 8417ca8062c8SMatthew G. Knepley 8418ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8419ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84209566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 84219566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 84229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8423412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8424412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 8425412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 842658723a97SMatthew G. Knepley 84279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 842863a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt) ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 8429412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 8430412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 84319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 843263a3b9bcSJacob 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)); 8433412e9a14SMatthew G. Knepley } 84349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 843558723a97SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 843658723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 8437412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 843858723a97SMatthew G. Knepley } 84399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8440412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 8441412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8442412e9a14SMatthew G. Knepley PetscInt unsplit; 844342363296SMatthew G. Knepley 84449566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8445412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 844642363296SMatthew G. Knepley } 844763a3b9bcSJacob 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)); 844842363296SMatthew G. Knepley } 8449ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8450ca8062c8SMatthew G. Knepley } 84519bf0dad6SMatthew G. Knepley 84529bf0dad6SMatthew G. Knepley /*@ 84539bf0dad6SMatthew 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 84549bf0dad6SMatthew G. Knepley 8455899ea2b8SJacob Faibussowitsch Not Collective 8456899ea2b8SJacob Faibussowitsch 84579bf0dad6SMatthew G. Knepley Input Parameters: 84589bf0dad6SMatthew G. Knepley + dm - The DMPlex object 84599bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 84609bf0dad6SMatthew G. Knepley 846145da879fSVaclav Hapla Notes: 846245da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 846345da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 846445da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 846545da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 84669bf0dad6SMatthew G. Knepley 846795eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 846895eb5ee5SVaclav Hapla 84699bf0dad6SMatthew G. Knepley Level: developer 84709bf0dad6SMatthew G. Knepley 8471db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 84729bf0dad6SMatthew G. Knepley @*/ 847325c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 84749bf0dad6SMatthew G. Knepley { 8475ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8476899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 84779bf0dad6SMatthew G. Knepley 84789bf0dad6SMatthew G. Knepley PetscFunctionBegin; 84799bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84809566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpEnum)); 848145da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 848245da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8483899ea2b8SJacob Faibussowitsch PetscMPIInt rank; 8484899ea2b8SJacob Faibussowitsch MPI_Comm comm; 8485899ea2b8SJacob Faibussowitsch 84869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 84879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 848898921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8489899ea2b8SJacob Faibussowitsch } 8490899ea2b8SJacob Faibussowitsch 84919566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 84929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 84939566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8494ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 84959566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 84963554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8497412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 8498412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 8499ba2698f1SMatthew G. Knepley DMPolytopeType ct; 8500412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 8501412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 85029bf0dad6SMatthew G. Knepley 85039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 85049566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8505412e9a14SMatthew G. Knepley if (unsplit) continue; 85069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 85079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 85089566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 85099566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85109bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 85119bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 85129bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 85139bf0dad6SMatthew G. Knepley } 85149566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 851563a3b9bcSJacob 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); 85169bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 8517d4961f80SStefano Zampini DMPolytopeType fct; 85189bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 85199bf0dad6SMatthew G. Knepley 85209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 85219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 85229bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize*2; cl += 2) { 85239bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 85249bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 85259bf0dad6SMatthew G. Knepley } 852663a3b9bcSJacob 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]); 85279bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 8528b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff+v]) { 8529b5a892a1SMatthew G. Knepley PetscInt v1; 8530b5a892a1SMatthew G. Knepley 85319566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 853263a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 85339566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 853463a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff+v1])); 85359566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 853663a3b9bcSJacob 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]); 8537b5a892a1SMatthew G. Knepley } 85389bf0dad6SMatthew G. Knepley } 85399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 8540412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 85419bf0dad6SMatthew G. Knepley } 85429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 85439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85449bf0dad6SMatthew G. Knepley } 85453554e41dSMatthew G. Knepley } 8546552f7358SJed Brown PetscFunctionReturn(0); 8547552f7358SJed Brown } 85483913d7c8SMatthew G. Knepley 8549bb6a34a8SMatthew G. Knepley /*@ 8550bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 8551bb6a34a8SMatthew G. Knepley 8552bb6a34a8SMatthew G. Knepley Input Parameter: 8553bb6a34a8SMatthew G. Knepley . dm - The DMPlex object 8554bb6a34a8SMatthew G. Knepley 855595eb5ee5SVaclav Hapla Notes: 855695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 855795eb5ee5SVaclav Hapla 855895eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8559bb6a34a8SMatthew G. Knepley 8560bb6a34a8SMatthew G. Knepley Level: developer 8561bb6a34a8SMatthew G. Knepley 8562db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8563bb6a34a8SMatthew G. Knepley @*/ 8564bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm) 8565bb6a34a8SMatthew G. Knepley { 8566a2a9e04cSMatthew G. Knepley Vec coordinates; 8567bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 8568bb6a34a8SMatthew G. Knepley PetscReal vol; 8569412e9a14SMatthew G. Knepley PetscBool periodic; 857051a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 8571bb6a34a8SMatthew G. Knepley 8572bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 85739566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 85749566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 857551a74b61SMatthew G. Knepley if (dim != dE) PetscFunctionReturn(0); 85769566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 85779566063dSJacob Faibussowitsch PetscCall(DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL)); 8578bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 85799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8580a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 85819566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8582412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8583412e9a14SMatthew G. Knepley DMPolytopeType ct; 8584412e9a14SMatthew G. Knepley PetscInt unsplit; 8585412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 8586412e9a14SMatthew G. Knepley 85879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 8588412e9a14SMatthew G. Knepley switch (ct) { 8589412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 8590412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8591412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8592412e9a14SMatthew G. Knepley ignoreZeroVol = PETSC_TRUE; break; 8593412e9a14SMatthew G. Knepley default: break; 8594412e9a14SMatthew G. Knepley } 8595412e9a14SMatthew G. Knepley switch (ct) { 8596412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 8597412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8598412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8599a2a9e04cSMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 8600412e9a14SMatthew G. Knepley continue; 8601412e9a14SMatthew G. Knepley default: break; 8602412e9a14SMatthew G. Knepley } 86039566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8604412e9a14SMatthew G. Knepley if (unsplit) continue; 86059566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 86061dca8a05SBarry 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); 860763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ*refVol))); 8608412e9a14SMatthew G. Knepley if (depth > 1 && !periodic) { 86099566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 86101dca8a05SBarry 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); 861163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double) vol)); 8612bb6a34a8SMatthew G. Knepley } 8613bb6a34a8SMatthew G. Knepley } 8614bb6a34a8SMatthew G. Knepley PetscFunctionReturn(0); 8615bb6a34a8SMatthew G. Knepley } 8616bb6a34a8SMatthew G. Knepley 861703da9461SVaclav Hapla /*@ 8618e83a0d2dSVaclav Hapla DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 861903da9461SVaclav Hapla 862003da9461SVaclav Hapla Input Parameters: 862103da9461SVaclav Hapla . dm - The DMPlex object 862203da9461SVaclav Hapla 8623e83a0d2dSVaclav Hapla Notes: 8624e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 86258918e3e2SVaclav Hapla It currently checks only meshes with no partition overlapping. 862603da9461SVaclav Hapla 862795eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 862895eb5ee5SVaclav Hapla 862903da9461SVaclav Hapla Level: developer 863003da9461SVaclav Hapla 8631db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()` 863203da9461SVaclav Hapla @*/ 863303da9461SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm) 863403da9461SVaclav Hapla { 8635f0cfc026SVaclav Hapla PetscSF pointSF; 8636f5869d18SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8637f5869d18SMatthew G. Knepley const PetscInt *locals, *rootdegree; 8638f0cfc026SVaclav Hapla PetscBool distributed; 863903da9461SVaclav Hapla 864003da9461SVaclav Hapla PetscFunctionBegin; 864103da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86429566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF)); 86439566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 8644f0cfc026SVaclav Hapla if (!distributed) PetscFunctionReturn(0); 86459566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap)); 8646f0cfc026SVaclav Hapla if (overlap) { 86479566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping")); 86488918e3e2SVaclav Hapla PetscFunctionReturn(0); 86498918e3e2SVaclav Hapla } 865028b400f6SJacob Faibussowitsch PetscCheck(pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 86519566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL)); 865208401ef6SPierre Jolivet PetscCheck(nroots >= 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 86539566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 86549566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 865503da9461SVaclav Hapla 8656ece87651SVaclav Hapla /* 1) check there are no faces in 2D, cells in 3D, in interface */ 86579566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 86589566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 8659f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 8660f5869d18SMatthew G. Knepley const PetscInt point = locals[l]; 8661f5869d18SMatthew G. Knepley 86621dca8a05SBarry Smith PetscCheck(point <= cStart || point >= cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 866303da9461SVaclav Hapla } 8664ece87651SVaclav Hapla 8665f5869d18SMatthew G. Knepley /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8666f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 8667f5869d18SMatthew G. Knepley const PetscInt point = locals[l]; 8668f5869d18SMatthew G. Knepley const PetscInt *cone; 8669f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 8670f5869d18SMatthew G. Knepley 86719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 86729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 8673f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8674f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 86759566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 867663a3b9bcSJacob 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]); 8677f5869d18SMatthew G. Knepley } 8678f5869d18SMatthew G. Knepley } 8679ece87651SVaclav Hapla } 868003da9461SVaclav Hapla PetscFunctionReturn(0); 868103da9461SVaclav Hapla } 868203da9461SVaclav Hapla 8683b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8684b5a892a1SMatthew G. Knepley { 8685b5a892a1SMatthew G. Knepley PetscFunctionBegin; 86869566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 86879566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 86889566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 86899566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 86909566063dSJacob Faibussowitsch PetscCall(DMPlexCheckPointSF(dm)); 86919566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 8692b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 8693b5a892a1SMatthew G. Knepley } 8694b5a892a1SMatthew G. Knepley 8695068a5610SStefano Zampini typedef struct cell_stats 8696068a5610SStefano Zampini { 8697068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 8698068a5610SStefano Zampini PetscInt count; 8699068a5610SStefano Zampini } cell_stats_t; 8700068a5610SStefano Zampini 870125befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8702068a5610SStefano Zampini { 8703068a5610SStefano Zampini PetscInt i, N = *len; 8704068a5610SStefano Zampini 8705068a5610SStefano Zampini for (i = 0; i < N; i++) { 8706068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *) a; 8707068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *) b; 8708068a5610SStefano Zampini 8709068a5610SStefano Zampini B->min = PetscMin(A->min,B->min); 8710068a5610SStefano Zampini B->max = PetscMax(A->max,B->max); 8711068a5610SStefano Zampini B->sum += A->sum; 8712068a5610SStefano Zampini B->squaresum += A->squaresum; 8713068a5610SStefano Zampini B->count += A->count; 8714068a5610SStefano Zampini } 8715068a5610SStefano Zampini } 8716068a5610SStefano Zampini 8717068a5610SStefano Zampini /*@ 871843fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8719068a5610SStefano Zampini 87208261a58bSMatthew G. Knepley Collective on dm 87218261a58bSMatthew G. Knepley 8722068a5610SStefano Zampini Input Parameters: 8723068a5610SStefano Zampini + dm - The DMPlex object 872443fa8764SMatthew G. Knepley . output - If true, statistics will be displayed on stdout 872543fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8726068a5610SStefano Zampini 872795eb5ee5SVaclav Hapla Notes: 872895eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 872995eb5ee5SVaclav Hapla 873095eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8731068a5610SStefano Zampini 8732068a5610SStefano Zampini Level: developer 8733068a5610SStefano Zampini 8734db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 8735068a5610SStefano Zampini @*/ 873643fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8737068a5610SStefano Zampini { 8738068a5610SStefano Zampini DM dmCoarse; 873943fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 874043fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 874143fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 874243fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8743412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 874443fa8764SMatthew G. Knepley PetscMPIInt rank,size; 8745068a5610SStefano Zampini 8746068a5610SStefano Zampini PetscFunctionBegin; 8747068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8748068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 8749068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 8750068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 8751068a5610SStefano Zampini stats.count = 0; 8752068a5610SStefano Zampini 87539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 87549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 87559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm,&cdim)); 87569566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 87579566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd)); 87589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd)); 8759412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 8760068a5610SStefano Zampini PetscInt i; 8761068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8762068a5610SStefano Zampini 87639566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ)); 876463a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 876543fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 8766068a5610SStefano Zampini frobJ += J[i] * J[i]; 8767068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 8768068a5610SStefano Zampini } 8769068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 8770068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 8771068a5610SStefano Zampini 8772068a5610SStefano Zampini stats.min = PetscMin(stats.min,cond); 8773068a5610SStefano Zampini stats.max = PetscMax(stats.max,cond); 8774068a5610SStefano Zampini stats.sum += cond; 8775068a5610SStefano Zampini stats.squaresum += cond2; 8776068a5610SStefano Zampini stats.count++; 87778261a58bSMatthew G. Knepley if (output && cond > limit) { 877843fa8764SMatthew G. Knepley PetscSection coordSection; 877943fa8764SMatthew G. Knepley Vec coordsLocal; 878043fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 878143fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 878243fa8764SMatthew G. Knepley 87839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 87849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 87859566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 878663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double) cond)); 878743fa8764SMatthew G. Knepley for (i = 0; i < Nv/cdim; ++i) { 878863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 878943fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 87909566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 87919566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]))); 879243fa8764SMatthew G. Knepley } 87939566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 879443fa8764SMatthew G. Knepley } 87959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 879643fa8764SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) { 879743fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 879843fa8764SMatthew G. Knepley 879943fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 880043fa8764SMatthew G. Knepley PetscReal len; 880143fa8764SMatthew G. Knepley 88029566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 880363a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double) len)); 880443fa8764SMatthew G. Knepley } 880543fa8764SMatthew G. Knepley } 88069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 88079566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 880843fa8764SMatthew G. Knepley } 8809068a5610SStefano Zampini } 88109566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 8811068a5610SStefano Zampini 8812068a5610SStefano Zampini if (size > 1) { 8813068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4,1}; 8814068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8815068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8816068a5610SStefano Zampini MPI_Op statReduce; 8817068a5610SStefano Zampini 88189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType)); 88199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 88209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 88219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm)); 88229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 88239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 8824068a5610SStefano Zampini } else { 88259566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats,&stats,1)); 8826068a5610SStefano Zampini } 8827dd400576SPatrick Sanan if (rank == 0) { 8828068a5610SStefano Zampini count = globalStats.count; 8829068a5610SStefano Zampini min = globalStats.min; 8830068a5610SStefano Zampini max = globalStats.max; 8831068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 8832068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8833068a5610SStefano Zampini } 8834068a5610SStefano Zampini 8835068a5610SStefano Zampini if (output) { 883663a3b9bcSJacob 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)); 8837068a5610SStefano Zampini } 88389566063dSJacob Faibussowitsch PetscCall(PetscFree2(J,invJ)); 8839068a5610SStefano Zampini 88409566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm,&dmCoarse)); 8841068a5610SStefano Zampini if (dmCoarse) { 8842068a5610SStefano Zampini PetscBool isplex; 8843068a5610SStefano Zampini 88449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex)); 8845068a5610SStefano Zampini if (isplex) { 88469566063dSJacob Faibussowitsch PetscCall(DMPlexCheckCellShape(dmCoarse,output,condLimit)); 8847068a5610SStefano Zampini } 8848068a5610SStefano Zampini } 8849068a5610SStefano Zampini PetscFunctionReturn(0); 8850068a5610SStefano Zampini } 8851068a5610SStefano Zampini 8852f108dbd7SJacob Faibussowitsch /*@ 8853f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8854f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 8855f108dbd7SJacob Faibussowitsch 88566ed19f2fSJacob Faibussowitsch Collective on dm 8857f108dbd7SJacob Faibussowitsch 8858f108dbd7SJacob Faibussowitsch Input Parameters: 8859f108dbd7SJacob Faibussowitsch + dm - The DMPlex object 8860f108dbd7SJacob Faibussowitsch . fv - Optional PetscFV object for pre-computed cell/face centroid information 8861f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 8862f108dbd7SJacob Faibussowitsch 8863f108dbd7SJacob Faibussowitsch Output Parameters: 8864f108dbd7SJacob Faibussowitsch + OrthQual - Vec containing orthogonal quality per cell 8865f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8866f108dbd7SJacob Faibussowitsch 8867f108dbd7SJacob Faibussowitsch Options Database Keys: 8868f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8869f108dbd7SJacob Faibussowitsch supported. 8870f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8871f108dbd7SJacob Faibussowitsch 8872f108dbd7SJacob Faibussowitsch Notes: 8873f108dbd7SJacob Faibussowitsch Orthogonal quality is given by the following formula: 8874f108dbd7SJacob Faibussowitsch 8875f108dbd7SJacob Faibussowitsch \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8876f108dbd7SJacob Faibussowitsch 8877f108dbd7SJacob 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 8878f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8879f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8880f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 8881f108dbd7SJacob Faibussowitsch 8882f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 8883f108dbd7SJacob Faibussowitsch 8884f108dbd7SJacob Faibussowitsch This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8885f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8886f108dbd7SJacob Faibussowitsch 8887f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8888f108dbd7SJacob Faibussowitsch 8889f108dbd7SJacob Faibussowitsch Level: intermediate 8890f108dbd7SJacob Faibussowitsch 8891db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()` 8892f108dbd7SJacob Faibussowitsch @*/ 8893f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8894f108dbd7SJacob Faibussowitsch { 88956ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 88966ed19f2fSJacob Faibussowitsch PetscInt *idx; 88976ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 8898f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 88996ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 8900f108dbd7SJacob Faibussowitsch MPI_Comm comm; 8901f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 8902f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 8903f108dbd7SJacob Faibussowitsch IS glob; 8904f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 8905f108dbd7SJacob Faibussowitsch PetscViewer vwr; 8906f108dbd7SJacob Faibussowitsch 8907f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 8908f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89096ed19f2fSJacob Faibussowitsch if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8910f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQual, 4); 89116bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 89129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 89139566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 891463a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 89156ed19f2fSJacob Faibussowitsch { 89166ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 89176ed19f2fSJacob Faibussowitsch 89189566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 8919f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8920f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 8921f108dbd7SJacob Faibussowitsch 89229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 892398921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8924f108dbd7SJacob Faibussowitsch } 89256ed19f2fSJacob Faibussowitsch } 8926f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 8927f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQualLabel, 5); 89289566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 89299566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 89306ed19f2fSJacob Faibussowitsch } else {*OrthQualLabel = NULL;} 89319566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 89329566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 89339566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 89349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 89359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 89369566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 89379566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 89389566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE)); 89399566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 89409566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 89419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 89429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 89439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 89449566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 89459566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 89469566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 89479566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 89489566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 89496ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++,cell++) { 89506ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8951f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 8952f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 8953898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 8954f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 8955f108dbd7SJacob Faibussowitsch 89566ed19f2fSJacob Faibussowitsch idx[cellIter] = cell-cStart; 8957f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 8958f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 89599566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 89609566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 8961f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 89629566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 89636ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 89646ed19f2fSJacob Faibussowitsch PetscInt i; 89656ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 8966f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 8967f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 8968f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 8969f108dbd7SJacob Faibussowitsch 8970f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 8971f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 89729566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 8973f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 89746ed19f2fSJacob Faibussowitsch { 89756ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 89766ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 89776ed19f2fSJacob Faibussowitsch 89789566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 89799566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 89809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 89816ed19f2fSJacob Faibussowitsch } 8982f108dbd7SJacob Faibussowitsch 8983f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 8984f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 8985f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8986f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 8987f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 8988addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 8989addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 8990addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 8991f108dbd7SJacob Faibussowitsch } 8992addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 8993addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 8994addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 8995f108dbd7SJacob Faibussowitsch 8996f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 8997f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 8998f108dbd7SJacob Faibussowitsch ci[i] = ci[i]/normci; 8999f108dbd7SJacob Faibussowitsch fi[i] = fi[i]/normfi; 9000f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i]/normai; 9001f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9002f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9003f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9004f108dbd7SJacob Faibussowitsch } 9005f108dbd7SJacob Faibussowitsch if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9006f108dbd7SJacob Faibussowitsch minvalc = PetscRealPart(cArr[cellneighiter]); 9007f108dbd7SJacob Faibussowitsch } 9008f108dbd7SJacob Faibussowitsch if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9009f108dbd7SJacob Faibussowitsch minvalf = PetscRealPart(fArr[cellneighiter]); 9010f108dbd7SJacob Faibussowitsch } 9011f108dbd7SJacob Faibussowitsch } 90129566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 90139566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9014f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 90156ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9016f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 90179566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9018f108dbd7SJacob Faibussowitsch } 9019f108dbd7SJacob Faibussowitsch } 90209566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES)); 90219566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 90229566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 90239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 90249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 90259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9026f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 90279566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9028f108dbd7SJacob Faibussowitsch } 90299566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 90309566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vwr)); 90319566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 9032f108dbd7SJacob Faibussowitsch PetscFunctionReturn(0); 9033f108dbd7SJacob Faibussowitsch } 9034f108dbd7SJacob Faibussowitsch 90351eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 90361eb70e55SToby Isaac * interpolator construction */ 90371eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 90381eb70e55SToby Isaac { 90391eb70e55SToby Isaac PetscSection section, newSection, gsection; 90401eb70e55SToby Isaac PetscSF sf; 90411eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 90421eb70e55SToby Isaac 90431eb70e55SToby Isaac PetscFunctionBegin; 90441eb70e55SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 90451eb70e55SToby Isaac PetscValidPointer(odm,2); 90469566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 90479566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 90489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm))); 90491eb70e55SToby Isaac if (!ghasConstraints) { 90509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 90511eb70e55SToby Isaac *odm = dm; 90521eb70e55SToby Isaac PetscFunctionReturn(0); 90531eb70e55SToby Isaac } 90549566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 90559566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 90569566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 90579566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 90589566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 90599566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 90609566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 90611eb70e55SToby Isaac PetscFunctionReturn(0); 90621eb70e55SToby Isaac } 90631eb70e55SToby Isaac 90641eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 90651eb70e55SToby Isaac { 90661eb70e55SToby Isaac DM dmco, dmfo; 90671eb70e55SToby Isaac Mat interpo; 90681eb70e55SToby Isaac Vec rscale; 90691eb70e55SToby Isaac Vec cglobalo, clocal; 90701eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 90711eb70e55SToby Isaac PetscBool regular; 90721eb70e55SToby Isaac 90731eb70e55SToby Isaac PetscFunctionBegin; 90749566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 90759566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 90769566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 90779566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 90789566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 90799566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 90809566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 90819566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 90829566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 90839566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 90849566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 90859566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 90869566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 90879566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 90889566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 90899566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 90909566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 90919566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 90929566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 90939566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 90949566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 90959566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 90969566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 90979566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 90981eb70e55SToby Isaac *shift = fglobal; 90999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 91009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 91019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 91029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 91039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 91049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 91059566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 91069566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 91071eb70e55SToby Isaac PetscFunctionReturn(0); 91081eb70e55SToby Isaac } 91091eb70e55SToby Isaac 91101eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 91111eb70e55SToby Isaac { 91121eb70e55SToby Isaac PetscObject shifto; 91131eb70e55SToby Isaac Vec shift; 91141eb70e55SToby Isaac 91151eb70e55SToby Isaac PetscFunctionBegin; 91161eb70e55SToby Isaac if (!interp) { 91171eb70e55SToby Isaac Vec rscale; 91181eb70e55SToby Isaac 91199566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 91209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 91211eb70e55SToby Isaac } else { 91229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 91231eb70e55SToby Isaac } 91249566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 91251eb70e55SToby Isaac if (!shifto) { 91269566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 91279566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift)); 91281eb70e55SToby Isaac shifto = (PetscObject) shift; 91299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 91301eb70e55SToby Isaac } 91311eb70e55SToby Isaac shift = (Vec) shifto; 91329566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 91339566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 91349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 91351eb70e55SToby Isaac PetscFunctionReturn(0); 91361eb70e55SToby Isaac } 91371eb70e55SToby Isaac 9138bceba477SMatthew G. Knepley /* Pointwise interpolation 9139bceba477SMatthew G. Knepley Just code FEM for now 9140bceba477SMatthew G. Knepley u^f = I u^c 91414ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 91424ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 91434ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9144bceba477SMatthew G. Knepley */ 9145bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9146bceba477SMatthew G. Knepley { 9147bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9148bceba477SMatthew G. Knepley PetscInt m, n; 9149a063dac3SMatthew G. Knepley void *ctx; 915068132eb9SMatthew G. Knepley DM cdm; 9151cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9152bceba477SMatthew G. Knepley 9153bceba477SMatthew G. Knepley PetscFunctionBegin; 91549566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 91559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 91569566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 91579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 915868132eb9SMatthew G. Knepley 91599566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 91609566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation)); 91619566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 91629566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 91639566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 916468132eb9SMatthew G. Knepley 91659566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 91669566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 91679566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 91689566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 91699566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 91704db47ee9SStefano Zampini if (scaling) { 91715d1c2e58SMatthew G. Knepley /* Use naive scaling */ 91729566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 91734db47ee9SStefano Zampini } 9174a063dac3SMatthew G. Knepley PetscFunctionReturn(0); 9175a063dac3SMatthew G. Knepley } 9176bceba477SMatthew G. Knepley 91776dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9178a063dac3SMatthew G. Knepley { 91796dbf9973SLawrence Mitchell VecScatter ctx; 918090748bafSMatthew G. Knepley 9181a063dac3SMatthew G. Knepley PetscFunctionBegin; 91829566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 91839566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 91849566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 9185bceba477SMatthew G. Knepley PetscFunctionReturn(0); 9186bceba477SMatthew G. Knepley } 9187bceba477SMatthew G. Knepley 91883e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 91893e9753d6SMatthew G. Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 91903e9753d6SMatthew G. Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 91913e9753d6SMatthew G. Knepley PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 91923e9753d6SMatthew G. Knepley { 919300635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 919400635df3SMatthew G. Knepley PetscInt c; 919500635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 91963e9753d6SMatthew G. Knepley } 91973e9753d6SMatthew G. Knepley 9198b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9199b4937a87SMatthew G. Knepley { 9200b4937a87SMatthew G. Knepley DM dmc; 9201b4937a87SMatthew G. Knepley PetscDS ds; 9202b4937a87SMatthew G. Knepley Vec ones, locmass; 9203b4937a87SMatthew G. Knepley IS cellIS; 9204b4937a87SMatthew G. Knepley PetscFormKey key; 9205b4937a87SMatthew G. Knepley PetscInt depth; 9206b4937a87SMatthew G. Knepley 9207b4937a87SMatthew G. Knepley PetscFunctionBegin; 92089566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 92099566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 92109566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 92119566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92129566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 92139566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 92149566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 92159566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 92169566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 92179566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 92189566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9219b4937a87SMatthew G. Knepley key.label = NULL; 9220b4937a87SMatthew G. Knepley key.value = 0; 9221b4937a87SMatthew G. Knepley key.field = 0; 9222b4937a87SMatthew G. Knepley key.part = 0; 92239566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 92249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 92259566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 92269566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 92279566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 92289566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 92299566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 92309566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 9231b4937a87SMatthew G. Knepley PetscFunctionReturn(0); 9232b4937a87SMatthew G. Knepley } 9233b4937a87SMatthew G. Knepley 9234bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9235bd041c0cSMatthew G. Knepley { 9236bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9237bd041c0cSMatthew G. Knepley PetscInt m, n; 9238bd041c0cSMatthew G. Knepley void *ctx; 9239bd041c0cSMatthew G. Knepley DM cdm; 9240bd041c0cSMatthew G. Knepley PetscBool regular; 9241bd041c0cSMatthew G. Knepley 9242bd041c0cSMatthew G. Knepley PetscFunctionBegin; 92433e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 92443e9753d6SMatthew G. Knepley DM dmc; 92453e9753d6SMatthew G. Knepley PetscDS ds; 9246b4937a87SMatthew G. Knepley PetscWeakForm wf; 92473e9753d6SMatthew G. Knepley Vec u; 92483e9753d6SMatthew G. Knepley IS cellIS; 924906ad1575SMatthew G. Knepley PetscFormKey key; 92503e9753d6SMatthew G. Knepley PetscInt depth; 92513e9753d6SMatthew G. Knepley 92529566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 92539566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 92549566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 92559566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 92569566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 92579566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92589566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 92599566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmc, &u)); 92609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 92619566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 92629566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 92636528b96dSMatthew G. Knepley key.label = NULL; 92646528b96dSMatthew G. Knepley key.value = 0; 92656528b96dSMatthew G. Knepley key.field = 0; 926606ad1575SMatthew G. Knepley key.part = 0; 92679566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 92689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 92699566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmc, &u)); 92709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 92713e9753d6SMatthew G. Knepley } else { 92729566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 92739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 92749566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 92759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9276bd041c0cSMatthew G. Knepley 92779566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass)); 92789566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 92799566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 92809566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9281bd041c0cSMatthew G. Knepley 92829566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 92839566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 92849566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 92859566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 92863e9753d6SMatthew G. Knepley } 92879566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 9288bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 9289bd041c0cSMatthew G. Knepley } 9290bd041c0cSMatthew G. Knepley 92910aef6b92SMatthew G. Knepley /*@ 92920aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 92930aef6b92SMatthew G. Knepley 92940aef6b92SMatthew G. Knepley Input Parameter: 92950aef6b92SMatthew G. Knepley . dm - The DMPlex object 92960aef6b92SMatthew G. Knepley 92970aef6b92SMatthew G. Knepley Output Parameter: 92980aef6b92SMatthew G. Knepley . regular - The flag 92990aef6b92SMatthew G. Knepley 93000aef6b92SMatthew G. Knepley Level: intermediate 93010aef6b92SMatthew G. Knepley 9302db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()` 93030aef6b92SMatthew G. Knepley @*/ 93040aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 93050aef6b92SMatthew G. Knepley { 93060aef6b92SMatthew G. Knepley PetscFunctionBegin; 93070aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9308dadcf809SJacob Faibussowitsch PetscValidBoolPointer(regular, 2); 93090aef6b92SMatthew G. Knepley *regular = ((DM_Plex *) dm->data)->regularRefinement; 93100aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93110aef6b92SMatthew G. Knepley } 93120aef6b92SMatthew G. Knepley 93130aef6b92SMatthew G. Knepley /*@ 93140aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93150aef6b92SMatthew G. Knepley 93160aef6b92SMatthew G. Knepley Input Parameters: 93170aef6b92SMatthew G. Knepley + dm - The DMPlex object 93180aef6b92SMatthew G. Knepley - regular - The flag 93190aef6b92SMatthew G. Knepley 93200aef6b92SMatthew G. Knepley Level: intermediate 93210aef6b92SMatthew G. Knepley 9322db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()` 93230aef6b92SMatthew G. Knepley @*/ 93240aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 93250aef6b92SMatthew G. Knepley { 93260aef6b92SMatthew G. Knepley PetscFunctionBegin; 93270aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93280aef6b92SMatthew G. Knepley ((DM_Plex *) dm->data)->regularRefinement = regular; 93290aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93300aef6b92SMatthew G. Knepley } 93310aef6b92SMatthew G. Knepley 9332f7c74593SToby Isaac /* anchors */ 9333a68b90caSToby Isaac /*@ 9334f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9335ebdb1bfaSJed Brown call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9336a68b90caSToby Isaac 9337e228b242SToby Isaac not collective 9338a68b90caSToby Isaac 9339f899ff85SJose E. Roman Input Parameter: 9340a68b90caSToby Isaac . dm - The DMPlex object 9341a68b90caSToby Isaac 9342a68b90caSToby Isaac Output Parameters: 9343a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9344a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9345a68b90caSToby Isaac 9346a68b90caSToby Isaac Level: intermediate 9347a68b90caSToby Isaac 9348db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9349a68b90caSToby Isaac @*/ 9350a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9351a68b90caSToby Isaac { 9352a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9353a68b90caSToby Isaac 9354a68b90caSToby Isaac PetscFunctionBegin; 9355a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93569566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 9357a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 9358a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 9359a68b90caSToby Isaac PetscFunctionReturn(0); 9360a68b90caSToby Isaac } 9361a68b90caSToby Isaac 9362a68b90caSToby Isaac /*@ 9363f7c74593SToby Isaac DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9364f7c74593SToby Isaac when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9365a68b90caSToby Isaac point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9366a68b90caSToby Isaac 9367a17985deSToby Isaac After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9368ebdb1bfaSJed Brown DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9369a68b90caSToby Isaac 9370e228b242SToby Isaac collective on dm 9371a68b90caSToby Isaac 9372a68b90caSToby Isaac Input Parameters: 9373a68b90caSToby Isaac + dm - The DMPlex object 9374e228b242SToby 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). 9375e228b242SToby Isaac - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9376a68b90caSToby Isaac 9377a68b90caSToby Isaac The reference counts of anchorSection and anchorIS are incremented. 9378a68b90caSToby Isaac 9379a68b90caSToby Isaac Level: intermediate 9380a68b90caSToby Isaac 9381db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9382a68b90caSToby Isaac @*/ 9383a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9384a68b90caSToby Isaac { 9385a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9386e228b242SToby Isaac PetscMPIInt result; 9387a68b90caSToby Isaac 9388a68b90caSToby Isaac PetscFunctionBegin; 9389a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9390e228b242SToby Isaac if (anchorSection) { 9391e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 93929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result)); 93931dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9394e228b242SToby Isaac } 9395e228b242SToby Isaac if (anchorIS) { 9396e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 93979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result)); 93981dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9399e228b242SToby Isaac } 9400a68b90caSToby Isaac 94019566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 94029566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 9403a68b90caSToby Isaac plex->anchorSection = anchorSection; 9404a68b90caSToby Isaac 94059566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 94069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 9407a68b90caSToby Isaac plex->anchorIS = anchorIS; 9408a68b90caSToby Isaac 9409cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9410a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 9411a68b90caSToby Isaac const PetscInt *anchors; 9412a68b90caSToby Isaac 94139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 94149566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS,&size)); 94159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS,&anchors)); 9416a68b90caSToby Isaac for (a = 0; a < size; a++) { 9417a68b90caSToby Isaac PetscInt p; 9418a68b90caSToby Isaac 9419a68b90caSToby Isaac p = anchors[a]; 9420a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 9421a68b90caSToby Isaac PetscInt dof; 9422a68b90caSToby Isaac 94239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection,p,&dof)); 9424a68b90caSToby Isaac if (dof) { 9425a68b90caSToby Isaac 94269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS,&anchors)); 942763a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %" PetscInt_FMT " cannot be constrained and an anchor",p); 9428a68b90caSToby Isaac } 9429a68b90caSToby Isaac } 9430a68b90caSToby Isaac } 94319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS,&anchors)); 9432a68b90caSToby Isaac } 9433f7c74593SToby Isaac /* reset the generic constraints */ 94349566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,NULL,NULL,NULL)); 9435a68b90caSToby Isaac PetscFunctionReturn(0); 9436a68b90caSToby Isaac } 9437a68b90caSToby Isaac 9438f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9439a68b90caSToby Isaac { 9440f7c74593SToby Isaac PetscSection anchorSection; 94416995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9442a68b90caSToby Isaac 9443a68b90caSToby Isaac PetscFunctionBegin; 9444a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94459566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL)); 94469566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,cSec)); 94479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numFields)); 94486995de1eSToby Isaac if (numFields) { 9449719ab38cSToby Isaac PetscInt f; 94509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec,numFields)); 9451719ab38cSToby Isaac 9452719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 9453719ab38cSToby Isaac PetscInt numComp; 9454719ab38cSToby Isaac 94559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section,f,&numComp)); 94569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec,f,numComp)); 9457719ab38cSToby Isaac } 94586995de1eSToby Isaac } 94599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 94609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&sStart,&sEnd)); 94616995de1eSToby Isaac pStart = PetscMax(pStart,sStart); 94626995de1eSToby Isaac pEnd = PetscMin(pEnd,sEnd); 94636995de1eSToby Isaac pEnd = PetscMax(pStart,pEnd); 94649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec,pStart,pEnd)); 9465a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 94669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection,p,&dof)); 9467a68b90caSToby Isaac if (dof) { 94689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,p,&dof)); 94699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec,p,dof)); 9470a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 94719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,p,f,&dof)); 94729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec,p,f,dof)); 9473a68b90caSToby Isaac } 9474a68b90caSToby Isaac } 9475a68b90caSToby Isaac } 94769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 94779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *cSec, "Constraint Section")); 9478a68b90caSToby Isaac PetscFunctionReturn(0); 9479a68b90caSToby Isaac } 9480a68b90caSToby Isaac 9481f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9482a68b90caSToby Isaac { 9483f7c74593SToby Isaac PetscSection aSec; 9484ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 94850ac89760SToby Isaac const PetscInt *anchors; 94860ac89760SToby Isaac PetscInt numFields, f; 948766ad2231SToby Isaac IS aIS; 9488e19f7ee6SMark Adams MatType mtype; 9489e19f7ee6SMark Adams PetscBool iscuda,iskokkos; 94900ac89760SToby Isaac 94910ac89760SToby Isaac PetscFunctionBegin; 94920ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 94949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 94959566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,cMat)); 94969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat,m,n,m,n)); 94979566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda)); 94989566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda)); 94999566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos)); 95009566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos)); 9501e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 9502e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9503e19f7ee6SMark Adams else mtype = MATSEQAIJ; 95049566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat,mtype)); 95059566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 95069566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 95076995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 95089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec,&pStart,&pEnd)); 95099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&sStart,&sEnd)); 95109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&i)); 95110ac89760SToby Isaac i[0] = 0; 95129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numFields)); 95130ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 9514f19733c5SToby Isaac PetscInt rDof, rOff, r; 9515f19733c5SToby Isaac 95169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 9517f19733c5SToby Isaac if (!rDof) continue; 95189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 95190ac89760SToby Isaac if (numFields) { 95200ac89760SToby Isaac for (f = 0; f < numFields; f++) { 95210ac89760SToby Isaac annz = 0; 9522f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 9523f19733c5SToby Isaac a = anchors[rOff + r]; 9524ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof)); 95260ac89760SToby Isaac annz += aDof; 95270ac89760SToby Isaac } 95289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof)); 95299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&off)); 95300ac89760SToby Isaac for (q = 0; q < dof; q++) { 95310ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 95320ac89760SToby Isaac } 95330ac89760SToby Isaac } 95342f7452b8SBarry Smith } else { 95350ac89760SToby Isaac annz = 0; 95369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 95370ac89760SToby Isaac for (q = 0; q < dof; q++) { 9538ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 9539ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 95410ac89760SToby Isaac annz += aDof; 95420ac89760SToby Isaac } 95439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 95449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec,p,&off)); 95450ac89760SToby Isaac for (q = 0; q < dof; q++) { 95460ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 95470ac89760SToby Isaac } 95480ac89760SToby Isaac } 95490ac89760SToby Isaac } 95500ac89760SToby Isaac nnz = i[m]; 95519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&j)); 95520ac89760SToby Isaac offset = 0; 95530ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 95540ac89760SToby Isaac if (numFields) { 95550ac89760SToby Isaac for (f = 0; f < numFields; f++) { 95569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof)); 95570ac89760SToby Isaac for (q = 0; q < dof; q++) { 95580ac89760SToby Isaac PetscInt rDof, rOff, r; 95599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 95609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 95610ac89760SToby Isaac for (r = 0; r < rDof; r++) { 95620ac89760SToby Isaac PetscInt s; 95630ac89760SToby Isaac 95640ac89760SToby Isaac a = anchors[rOff + r]; 9565ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof)); 95679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section,a,f,&aOff)); 95680ac89760SToby Isaac for (s = 0; s < aDof; s++) { 95690ac89760SToby Isaac j[offset++] = aOff + s; 95700ac89760SToby Isaac } 95710ac89760SToby Isaac } 95720ac89760SToby Isaac } 95730ac89760SToby Isaac } 95742f7452b8SBarry Smith } else { 95759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 95760ac89760SToby Isaac for (q = 0; q < dof; q++) { 95770ac89760SToby Isaac PetscInt rDof, rOff, r; 95789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 95799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 95800ac89760SToby Isaac for (r = 0; r < rDof; r++) { 95810ac89760SToby Isaac PetscInt s; 95820ac89760SToby Isaac 95830ac89760SToby Isaac a = anchors[rOff + r]; 9584ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 95869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,a,&aOff)); 95870ac89760SToby Isaac for (s = 0; s < aDof; s++) { 95880ac89760SToby Isaac j[offset++] = aOff + s; 95890ac89760SToby Isaac } 95900ac89760SToby Isaac } 95910ac89760SToby Isaac } 95920ac89760SToby Isaac } 95930ac89760SToby Isaac } 95949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL)); 95959566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 95969566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 95979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 95980ac89760SToby Isaac PetscFunctionReturn(0); 95990ac89760SToby Isaac } 96000ac89760SToby Isaac 960166ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 960266ad2231SToby Isaac { 9603f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9604f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 960566ad2231SToby Isaac Mat cMat; 960666ad2231SToby Isaac 960766ad2231SToby Isaac PetscFunctionBegin; 960866ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 96099566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL)); 961066ad2231SToby Isaac if (anchorSection) { 961144a7f3ddSMatthew G. Knepley PetscInt Nf; 9612e228b242SToby Isaac 96139566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm,§ion)); 96149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec)); 96159566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat)); 96169566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm,&Nf)); 96179566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm,section,cSec,cMat)); 96189566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,cSec,cMat,NULL)); 96199566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 96209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 962166ad2231SToby Isaac } 962266ad2231SToby Isaac PetscFunctionReturn(0); 962366ad2231SToby Isaac } 9624a93c429eSMatthew G. Knepley 9625a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9626a93c429eSMatthew G. Knepley { 9627a93c429eSMatthew G. Knepley IS subis; 9628a93c429eSMatthew G. Knepley PetscSection section, subsection; 9629a93c429eSMatthew G. Knepley 9630a93c429eSMatthew G. Knepley PetscFunctionBegin; 96319566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 963228b400f6SJacob Faibussowitsch PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 963328b400f6SJacob Faibussowitsch PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9634a93c429eSMatthew G. Knepley /* Create subdomain */ 96359566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 9636a93c429eSMatthew G. Knepley /* Create submodel */ 96379566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 96389566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 96399566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 96409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 96419566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 9642a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 9643a93c429eSMatthew G. Knepley if (is) { 9644a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 9645a93c429eSMatthew G. Knepley IS spIS; 9646a93c429eSMatthew G. Knepley const PetscInt *spmap; 9647a93c429eSMatthew G. Knepley PetscInt *subIndices; 9648a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9649a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9650a93c429eSMatthew G. Knepley 96519566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 96529566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 96539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 96549566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 96559566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 96569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 9657a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9658a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 9659a93c429eSMatthew G. Knepley 96609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 9661a93c429eSMatthew G. Knepley if (gdof > 0) { 9662a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9663a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 9664a93c429eSMatthew G. Knepley 96659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 96669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 9667a93c429eSMatthew G. Knepley pSubSize += fdof-fcdof; 9668a93c429eSMatthew G. Knepley } 9669a93c429eSMatthew G. Knepley subSize += pSubSize; 9670a93c429eSMatthew G. Knepley if (pSubSize) { 9671a93c429eSMatthew G. Knepley if (bs < 0) { 9672a93c429eSMatthew G. Knepley bs = pSubSize; 9673a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 9674a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 9675a93c429eSMatthew G. Knepley bs = 1; 9676a93c429eSMatthew G. Knepley } 9677a93c429eSMatthew G. Knepley } 9678a93c429eSMatthew G. Knepley } 9679a93c429eSMatthew G. Knepley } 9680a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 9681a93c429eSMatthew G. Knepley bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 96829566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 9683a93c429eSMatthew G. Knepley if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9684a93c429eSMatthew G. Knepley else {bs = bsMinMax[0];} 96859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 9686a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9687a93c429eSMatthew G. Knepley PetscInt gdof, goff; 9688a93c429eSMatthew G. Knepley 96899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 9690a93c429eSMatthew G. Knepley if (gdof > 0) { 9691a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 9692a93c429eSMatthew G. Knepley 96939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 9694a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9695a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 9696a93c429eSMatthew G. Knepley 9697a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 9698a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 96999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 97009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 9701a93c429eSMatthew G. Knepley poff += fdof-fcdof; 9702a93c429eSMatthew G. Knepley } 97039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 97049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 9705a93c429eSMatthew G. Knepley for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9706a93c429eSMatthew G. Knepley subIndices[subOff] = goff+poff+fc; 9707a93c429eSMatthew G. Knepley } 9708a93c429eSMatthew G. Knepley } 9709a93c429eSMatthew G. Knepley } 9710a93c429eSMatthew G. Knepley } 97119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 97129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 9713a93c429eSMatthew G. Knepley if (bs > 1) { 9714a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 9715a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 9716a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 9717a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 9718a93c429eSMatthew G. Knepley if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9719a93c429eSMatthew G. Knepley } 9720a93c429eSMatthew G. Knepley } 97219566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 9722a93c429eSMatthew G. Knepley } 9723a93c429eSMatthew G. Knepley /* Attach nullspace */ 9724a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9725a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9726a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 9727a93c429eSMatthew G. Knepley } 9728a93c429eSMatthew G. Knepley if (f < Nf) { 9729a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 97309566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 97316823f3c5SBlaise Bourdin 97329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace)); 97339566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 9734a93c429eSMatthew G. Knepley } 9735a93c429eSMatthew G. Knepley } 9736a93c429eSMatthew G. Knepley PetscFunctionReturn(0); 9737a93c429eSMatthew G. Knepley } 9738c0f0dcc3SMatthew G. Knepley 9739c0f0dcc3SMatthew G. Knepley /*@ 9740c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 9741c0f0dcc3SMatthew G. Knepley 9742c0f0dcc3SMatthew G. Knepley Input Parameter: 9743c0f0dcc3SMatthew G. Knepley - dm - The DM 9744c0f0dcc3SMatthew G. Knepley 9745c0f0dcc3SMatthew G. Knepley Level: developer 9746c0f0dcc3SMatthew G. Knepley 9747c0f0dcc3SMatthew G. Knepley Options Database Keys: 9748c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor 9749c0f0dcc3SMatthew G. Knepley 9750db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()` 9751c0f0dcc3SMatthew G. Knepley @*/ 9752c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9753c0f0dcc3SMatthew G. Knepley { 9754e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG) 9755c0f0dcc3SMatthew G. Knepley PetscStageLog stageLog; 9756c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 9757c0f0dcc3SMatthew G. Knepley PetscLogStage stage; 9758c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 9759c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 9760c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 9761c0f0dcc3SMatthew G. Knepley const char *name; 9762e5ed2c37SJose E. Roman #endif 9763c0f0dcc3SMatthew G. Knepley 9764c0f0dcc3SMatthew G. Knepley PetscFunctionBegin; 9765c0f0dcc3SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9766c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG) 97679566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 97689566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 97699566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 97709566063dSJacob Faibussowitsch PetscCall(PetscLogGetStageLog(&stageLog)); 97719566063dSJacob Faibussowitsch PetscCall(PetscStageLogGetCurrent(stageLog, &stage)); 97729566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 97739566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 9774c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart)*Nf*eventInfo.count; 9775c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops/eventInfo.time; 9776c0f0dcc3SMatthew G. Knepley cellRate = N/eventInfo.time; 977763a3b9bcSJacob 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))); 9778c0f0dcc3SMatthew G. Knepley #else 9779c0f0dcc3SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9780c0f0dcc3SMatthew G. Knepley #endif 9781c0f0dcc3SMatthew G. Knepley PetscFunctionReturn(0); 9782c0f0dcc3SMatthew G. Knepley } 9783