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 { 760bd83fdcbSStefano 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)); 24472e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C", NULL)); 24482e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C", NULL)); 24492e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C", NULL)); 24502e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C", NULL)); 24512e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",NULL)); 24526bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderGetDefault_C", NULL)); 24536bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderSetDefault_C", NULL)); 2454*c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",NULL)); 2455*c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexSetOverlap_C",NULL)); 24560d644c17SKarl Rupp if (--mesh->refct > 0) PetscFunctionReturn(0); 24579566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 24589566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 24599566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 24609566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 24619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 24629566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 24639566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->facesTmp)); 24649566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 24659566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 24669566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 24679566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 24689566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 24699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 24709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 24719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 24729566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 24739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 24749566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 24759566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 24769566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 24779566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 24789566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 24799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 24809566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 24819566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 24829566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2483552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 24849566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 2485552f7358SJed Brown PetscFunctionReturn(0); 2486552f7358SJed Brown } 2487552f7358SJed Brown 2488b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2489552f7358SJed Brown { 24908d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2491acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 24929fca9976SJed Brown PetscInt localSize, localStart = 0; 2493837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2494b412c318SBarry Smith MatType mtype; 24951428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2496552f7358SJed Brown 2497552f7358SJed Brown PetscFunctionBegin; 24989566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2499b412c318SBarry Smith mtype = dm->mattype; 25009566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 25019566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 25029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 25039fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm))); 25049566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 25059566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 25069566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 25079566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 25089566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2509acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 25109566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 25119566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 25129566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 25139566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 25149566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 25159566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 25169566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 25179566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2518552f7358SJed Brown if (!isShell) { 2519837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 25209fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2521fad22124SMatthew G Knepley PetscInt pStart, pEnd, p, dof, cdof; 2522552f7358SJed Brown 25239566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm,<og)); 25249fca9976SJed Brown 25259fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 25269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2527e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 25289fca9976SJed Brown PetscInt bdof, offset; 2529a9d99c84SMatthew G. Knepley 25309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 25319fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 25329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 25339fca9976SJed Brown for (PetscInt i=0; i < dof - cdof; i++) 25349fca9976SJed Brown pblocks[offset - localStart + i] = dof - cdof; 25351d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof+1) : dof; 25361d17a0a3SMatthew G. Knepley bdof = cdof && (dof-cdof) ? 1 : dof; 25371d17a0a3SMatthew G. Knepley if (dof) { 25381d17a0a3SMatthew G. Knepley if (bs < 0) {bs = bdof;} 25399fca9976SJed Brown else if (bs != bdof) {bs = 1;} 2540552f7358SJed Brown } 25412a28c762SMatthew G Knepley } 25422a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2543e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2544e432b41dSStefano Zampini bsLocal[1] = bs; 25459566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 2546e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2547e432b41dSStefano Zampini else bs = bsMinMax[0]; 25486fd5c86aSStefano Zampini bs = PetscMax(1,bs); 25499566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J,ltog,ltog)); 25500682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 25519566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 25529566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 25530682b8bbSJed Brown } else { 25549566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu)); 25559566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 25569566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2557552f7358SJed Brown } 25589fca9976SJed Brown { // Consolidate blocks 25599fca9976SJed Brown PetscInt nblocks = 0; 25609fca9976SJed Brown for (PetscInt i=0; i<localSize; i += PetscMax(1, pblocks[i])) { 25619fca9976SJed Brown if (pblocks[i] == 0) continue; 25629fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 25639fca9976SJed Brown for (PetscInt j=1; j<pblocks[i]; j++) { 25649fca9976SJed Brown PetscCheck(pblocks[i+j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i+j]); 25659fca9976SJed Brown } 25669fca9976SJed Brown } 25679fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 25689fca9976SJed Brown } 25699fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2570aa0f6e3cSJed Brown } 25719566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 2572552f7358SJed Brown PetscFunctionReturn(0); 2573552f7358SJed Brown } 2574552f7358SJed Brown 25757cd05799SMatthew G. Knepley /*@ 2576a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2577be36d101SStefano Zampini 2578be36d101SStefano Zampini Not collective 2579be36d101SStefano Zampini 2580be36d101SStefano Zampini Input Parameter: 2581be36d101SStefano Zampini . mesh - The DMPlex 2582be36d101SStefano Zampini 2583be36d101SStefano Zampini Output Parameters: 2584be36d101SStefano Zampini . subsection - The subdomain section 2585be36d101SStefano Zampini 2586be36d101SStefano Zampini Level: developer 2587be36d101SStefano Zampini 2588be36d101SStefano Zampini .seealso: 25897cd05799SMatthew G. Knepley @*/ 2590be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2591be36d101SStefano Zampini { 2592be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex*) dm->data; 2593be36d101SStefano Zampini 2594be36d101SStefano Zampini PetscFunctionBegin; 2595be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2596be36d101SStefano Zampini if (!mesh->subdomainSection) { 2597be36d101SStefano Zampini PetscSection section; 2598be36d101SStefano Zampini PetscSF sf; 2599be36d101SStefano Zampini 26009566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sf)); 26019566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm,§ion)); 26029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection)); 26039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2604be36d101SStefano Zampini } 2605be36d101SStefano Zampini *subsection = mesh->subdomainSection; 2606be36d101SStefano Zampini PetscFunctionReturn(0); 2607be36d101SStefano Zampini } 2608be36d101SStefano Zampini 2609552f7358SJed Brown /*@ 2610552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2611552f7358SJed Brown 2612552f7358SJed Brown Not collective 2613552f7358SJed Brown 2614552f7358SJed Brown Input Parameter: 2615552f7358SJed Brown . mesh - The DMPlex 2616552f7358SJed Brown 2617552f7358SJed Brown Output Parameters: 2618552f7358SJed Brown + pStart - The first mesh point 2619552f7358SJed Brown - pEnd - The upper bound for mesh points 2620552f7358SJed Brown 2621552f7358SJed Brown Level: beginner 2622552f7358SJed Brown 2623db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()` 2624552f7358SJed Brown @*/ 2625552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2626552f7358SJed Brown { 2627552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2628552f7358SJed Brown 2629552f7358SJed Brown PetscFunctionBegin; 2630552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 2632552f7358SJed Brown PetscFunctionReturn(0); 2633552f7358SJed Brown } 2634552f7358SJed Brown 2635552f7358SJed Brown /*@ 2636552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2637552f7358SJed Brown 2638552f7358SJed Brown Not collective 2639552f7358SJed Brown 2640552f7358SJed Brown Input Parameters: 2641552f7358SJed Brown + mesh - The DMPlex 2642552f7358SJed Brown . pStart - The first mesh point 2643552f7358SJed Brown - pEnd - The upper bound for mesh points 2644552f7358SJed Brown 2645552f7358SJed Brown Output Parameters: 2646552f7358SJed Brown 2647552f7358SJed Brown Level: beginner 2648552f7358SJed Brown 2649db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()` 2650552f7358SJed Brown @*/ 2651552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2652552f7358SJed Brown { 2653552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2654552f7358SJed Brown 2655552f7358SJed Brown PetscFunctionBegin; 2656552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 26589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 2659552f7358SJed Brown PetscFunctionReturn(0); 2660552f7358SJed Brown } 2661552f7358SJed Brown 2662552f7358SJed Brown /*@ 2663eaf898f9SPatrick Sanan DMPlexGetConeSize - Return 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 2671552f7358SJed Brown Output Parameter: 2672552f7358SJed Brown . size - The cone size for point p 2673552f7358SJed Brown 2674552f7358SJed Brown Level: beginner 2675552f7358SJed Brown 2676db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2677552f7358SJed Brown @*/ 2678552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2679552f7358SJed Brown { 2680552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2681552f7358SJed Brown 2682552f7358SJed Brown PetscFunctionBegin; 2683552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2684dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 26859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 2686552f7358SJed Brown PetscFunctionReturn(0); 2687552f7358SJed Brown } 2688552f7358SJed Brown 2689552f7358SJed Brown /*@ 2690eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2691552f7358SJed Brown 2692552f7358SJed Brown Not collective 2693552f7358SJed Brown 2694552f7358SJed Brown Input Parameters: 2695552f7358SJed Brown + mesh - The DMPlex 2696eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2697552f7358SJed Brown - size - The cone size for point p 2698552f7358SJed Brown 2699552f7358SJed Brown Output Parameter: 2700552f7358SJed Brown 2701552f7358SJed Brown Note: 2702552f7358SJed Brown This should be called after DMPlexSetChart(). 2703552f7358SJed Brown 2704552f7358SJed Brown Level: beginner 2705552f7358SJed Brown 2706db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2707552f7358SJed Brown @*/ 2708552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2709552f7358SJed Brown { 2710552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2711552f7358SJed Brown 2712552f7358SJed Brown PetscFunctionBegin; 2713552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 2715552f7358SJed Brown PetscFunctionReturn(0); 2716552f7358SJed Brown } 2717552f7358SJed Brown 2718f5a469b9SMatthew G. Knepley /*@ 2719eaf898f9SPatrick Sanan DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2720f5a469b9SMatthew G. Knepley 2721f5a469b9SMatthew G. Knepley Not collective 2722f5a469b9SMatthew G. Knepley 2723f5a469b9SMatthew G. Knepley Input Parameters: 2724f5a469b9SMatthew G. Knepley + mesh - The DMPlex 2725eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2726f5a469b9SMatthew G. Knepley - size - The additional cone size for point p 2727f5a469b9SMatthew G. Knepley 2728f5a469b9SMatthew G. Knepley Output Parameter: 2729f5a469b9SMatthew G. Knepley 2730f5a469b9SMatthew G. Knepley Note: 2731f5a469b9SMatthew G. Knepley This should be called after DMPlexSetChart(). 2732f5a469b9SMatthew G. Knepley 2733f5a469b9SMatthew G. Knepley Level: beginner 2734f5a469b9SMatthew G. Knepley 2735db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2736f5a469b9SMatthew G. Knepley @*/ 2737f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2738f5a469b9SMatthew G. Knepley { 2739f5a469b9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 2740f5a469b9SMatthew G. Knepley PetscFunctionBegin; 2741f5a469b9SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27429566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->coneSection, p, size)); 2743f5a469b9SMatthew G. Knepley PetscFunctionReturn(0); 2744f5a469b9SMatthew G. Knepley } 2745f5a469b9SMatthew G. Knepley 2746552f7358SJed Brown /*@C 2747eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2748552f7358SJed Brown 2749552f7358SJed Brown Not collective 2750552f7358SJed Brown 2751552f7358SJed Brown Input Parameters: 2752833c876bSVaclav Hapla + dm - The DMPlex 2753eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2754552f7358SJed Brown 2755552f7358SJed Brown Output Parameter: 2756552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 2757552f7358SJed Brown 2758552f7358SJed Brown Level: beginner 2759552f7358SJed Brown 27603813dfbdSMatthew G Knepley Fortran Notes: 27613813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 27623813dfbdSMatthew G Knepley include petsc.h90 in your code. 2763922102d1SVaclav Hapla You must also call DMPlexRestoreCone() after you finish using the returned array. 2764922102d1SVaclav Hapla DMPlexRestoreCone() is not needed/available in C. 27653813dfbdSMatthew G Knepley 2766db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()` 2767552f7358SJed Brown @*/ 2768552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2769552f7358SJed Brown { 2770552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2771552f7358SJed Brown PetscInt off; 2772552f7358SJed Brown 2773552f7358SJed Brown PetscFunctionBegin; 2774552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2775552f7358SJed Brown PetscValidPointer(cone, 3); 27769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 2777552f7358SJed Brown *cone = &mesh->cones[off]; 2778552f7358SJed Brown PetscFunctionReturn(0); 2779552f7358SJed Brown } 2780552f7358SJed Brown 27810ce7577fSVaclav Hapla /*@C 27820ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 27830ce7577fSVaclav Hapla 27840ce7577fSVaclav Hapla Not collective 27850ce7577fSVaclav Hapla 27860ce7577fSVaclav Hapla Input Parameters: 27870ce7577fSVaclav Hapla + dm - The DMPlex 27880ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 27890ce7577fSVaclav Hapla 2790d8d19677SJose E. Roman Output Parameters: 27910ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones 27920ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p 27930ce7577fSVaclav Hapla 27940ce7577fSVaclav Hapla Level: intermediate 27950ce7577fSVaclav Hapla 2796db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()` 27970ce7577fSVaclav Hapla @*/ 27980ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 27990ce7577fSVaclav Hapla { 28000ce7577fSVaclav Hapla PetscSection cs, newcs; 28010ce7577fSVaclav Hapla PetscInt *cones; 28020ce7577fSVaclav Hapla PetscInt *newarr=NULL; 28030ce7577fSVaclav Hapla PetscInt n; 28040ce7577fSVaclav Hapla 28050ce7577fSVaclav Hapla PetscFunctionBegin; 28069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 28079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 28089566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL)); 28090ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 28100ce7577fSVaclav Hapla if (pCones) { 28119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 28129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 28130ce7577fSVaclav Hapla } 28140ce7577fSVaclav Hapla PetscFunctionReturn(0); 28150ce7577fSVaclav Hapla } 28160ce7577fSVaclav Hapla 2817af9eab45SVaclav Hapla /*@ 2818af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2819d4636a37SVaclav Hapla 2820d4636a37SVaclav Hapla Not collective 2821d4636a37SVaclav Hapla 2822d4636a37SVaclav Hapla Input Parameters: 2823d4636a37SVaclav Hapla + dm - The DMPlex 2824af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2825d4636a37SVaclav Hapla 2826d4636a37SVaclav Hapla Output Parameter: 2827af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 2828d4636a37SVaclav Hapla 2829d4636a37SVaclav Hapla Level: advanced 2830d4636a37SVaclav Hapla 2831af9eab45SVaclav Hapla Notes: 2832af9eab45SVaclav Hapla Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2833af9eab45SVaclav Hapla There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2834af9eab45SVaclav Hapla 2835db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()` 2836d4636a37SVaclav Hapla @*/ 2837af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2838d4636a37SVaclav Hapla { 2839af9eab45SVaclav Hapla IS *expandedPointsAll; 2840af9eab45SVaclav Hapla PetscInt depth; 2841d4636a37SVaclav Hapla 2842d4636a37SVaclav Hapla PetscFunctionBegin; 2843af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2844af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2845af9eab45SVaclav Hapla PetscValidPointer(expandedPoints, 3); 28469566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2847af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 28489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 28499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2850af9eab45SVaclav Hapla PetscFunctionReturn(0); 2851af9eab45SVaclav Hapla } 2852af9eab45SVaclav Hapla 2853af9eab45SVaclav Hapla /*@ 2854af9eab45SVaclav 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). 2855af9eab45SVaclav Hapla 2856af9eab45SVaclav Hapla Not collective 2857af9eab45SVaclav Hapla 2858af9eab45SVaclav Hapla Input Parameters: 2859af9eab45SVaclav Hapla + dm - The DMPlex 2860af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2861af9eab45SVaclav Hapla 2862d8d19677SJose E. Roman Output Parameters: 2863af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2864af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 2865af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2866af9eab45SVaclav Hapla 2867af9eab45SVaclav Hapla Level: advanced 2868af9eab45SVaclav Hapla 2869af9eab45SVaclav Hapla Notes: 2870af9eab45SVaclav Hapla Like DMPlexGetConeTuple() but recursive. 2871af9eab45SVaclav Hapla 2872af9eab45SVaclav 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. 2873af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2874af9eab45SVaclav Hapla 2875af9eab45SVaclav 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: 2876af9eab45SVaclav Hapla (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2877af9eab45SVaclav Hapla (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2878af9eab45SVaclav Hapla 2879db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2880af9eab45SVaclav Hapla @*/ 2881af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2882af9eab45SVaclav Hapla { 2883af9eab45SVaclav Hapla const PetscInt *arr0=NULL, *cone=NULL; 2884af9eab45SVaclav Hapla PetscInt *arr=NULL, *newarr=NULL; 2885af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 2886af9eab45SVaclav Hapla IS *expandedPoints_; 2887af9eab45SVaclav Hapla PetscSection *sections_; 2888af9eab45SVaclav Hapla 2889af9eab45SVaclav Hapla PetscFunctionBegin; 2890af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2891af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2892af9eab45SVaclav Hapla if (depth) PetscValidIntPointer(depth, 3); 2893af9eab45SVaclav Hapla if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2894af9eab45SVaclav Hapla if (sections) PetscValidPointer(sections, 5); 28959566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 28969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 28979566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 28989566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 28999566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 2900af9eab45SVaclav Hapla arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2901af9eab45SVaclav Hapla for (d=depth_-1; d>=0; d--) { 29029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 29039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 2904af9eab45SVaclav Hapla for (i=0; i<n; i++) { 29059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d+1, &start, &end)); 2906af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 29079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 29089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 2909af9eab45SVaclav Hapla } else { 29109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 2911af9eab45SVaclav Hapla } 2912af9eab45SVaclav Hapla } 29139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 29149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 29159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 2916af9eab45SVaclav Hapla for (i=0; i<n; i++) { 29179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 29189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 2919af9eab45SVaclav Hapla if (cn > 1) { 29209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 29219566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt))); 2922af9eab45SVaclav Hapla } else { 2923af9eab45SVaclav Hapla newarr[co] = arr[i]; 2924af9eab45SVaclav Hapla } 2925af9eab45SVaclav Hapla } 29269566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 2927af9eab45SVaclav Hapla arr = newarr; 2928af9eab45SVaclav Hapla n = newn; 2929af9eab45SVaclav Hapla } 29309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 2931af9eab45SVaclav Hapla *depth = depth_; 2932af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 2933af9eab45SVaclav Hapla else { 29349566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 29359566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 2936af9eab45SVaclav Hapla } 2937af9eab45SVaclav Hapla if (sections) *sections = sections_; 2938af9eab45SVaclav Hapla else { 29399566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 29409566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 2941af9eab45SVaclav Hapla } 2942af9eab45SVaclav Hapla PetscFunctionReturn(0); 2943af9eab45SVaclav Hapla } 2944af9eab45SVaclav Hapla 2945af9eab45SVaclav Hapla /*@ 2946af9eab45SVaclav Hapla DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2947af9eab45SVaclav Hapla 2948af9eab45SVaclav Hapla Not collective 2949af9eab45SVaclav Hapla 2950af9eab45SVaclav Hapla Input Parameters: 2951af9eab45SVaclav Hapla + dm - The DMPlex 2952af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2953af9eab45SVaclav Hapla 2954d8d19677SJose E. Roman Output Parameters: 2955af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2956af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 2957af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2958af9eab45SVaclav Hapla 2959af9eab45SVaclav Hapla Level: advanced 2960af9eab45SVaclav Hapla 2961af9eab45SVaclav Hapla Notes: 2962af9eab45SVaclav Hapla See DMPlexGetConeRecursive() for details. 2963af9eab45SVaclav Hapla 2964db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()` 2965af9eab45SVaclav Hapla @*/ 2966af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2967af9eab45SVaclav Hapla { 2968af9eab45SVaclav Hapla PetscInt d, depth_; 2969af9eab45SVaclav Hapla 2970af9eab45SVaclav Hapla PetscFunctionBegin; 29719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 29721dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2973af9eab45SVaclav Hapla if (depth) *depth = 0; 2974af9eab45SVaclav Hapla if (expandedPoints) { 29759566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 29769566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 2977af9eab45SVaclav Hapla } 2978af9eab45SVaclav Hapla if (sections) { 29799566063dSJacob Faibussowitsch for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 29809566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 2981af9eab45SVaclav Hapla } 2982d4636a37SVaclav Hapla PetscFunctionReturn(0); 2983d4636a37SVaclav Hapla } 2984d4636a37SVaclav Hapla 2985552f7358SJed Brown /*@ 298692371b87SBarry 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 2987552f7358SJed Brown 2988552f7358SJed Brown Not collective 2989552f7358SJed Brown 2990552f7358SJed Brown Input Parameters: 2991552f7358SJed Brown + mesh - The DMPlex 2992eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2993552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 2994552f7358SJed Brown 2995552f7358SJed Brown Output Parameter: 2996552f7358SJed Brown 2997552f7358SJed Brown Note: 2998552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2999552f7358SJed Brown 3000552f7358SJed Brown Level: beginner 3001552f7358SJed Brown 3002db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3003552f7358SJed Brown @*/ 3004552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3005552f7358SJed Brown { 3006552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3007552f7358SJed Brown PetscInt pStart, pEnd; 3008552f7358SJed Brown PetscInt dof, off, c; 3009552f7358SJed Brown 3010552f7358SJed Brown PetscFunctionBegin; 3011552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 30139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3014dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(cone, 3); 30159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 301663a3b9bcSJacob 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); 3017552f7358SJed Brown for (c = 0; c < dof; ++c) { 301863a3b9bcSJacob 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); 3019552f7358SJed Brown mesh->cones[off+c] = cone[c]; 3020552f7358SJed Brown } 3021552f7358SJed Brown PetscFunctionReturn(0); 3022552f7358SJed Brown } 3023552f7358SJed Brown 3024552f7358SJed Brown /*@C 3025eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3026552f7358SJed Brown 3027552f7358SJed Brown Not collective 3028552f7358SJed Brown 3029552f7358SJed Brown Input Parameters: 3030552f7358SJed Brown + mesh - The DMPlex 3031eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3032552f7358SJed Brown 3033552f7358SJed Brown Output Parameter: 3034552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 3035b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3036552f7358SJed Brown 3037552f7358SJed Brown Level: beginner 3038552f7358SJed Brown 3039b5a892a1SMatthew G. Knepley Notes: 3040b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3041b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3042b5a892a1SMatthew G. Knepley of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 3043b5a892a1SMatthew G. Knepley with the identity. 3044b5a892a1SMatthew G. Knepley 30453813dfbdSMatthew G Knepley Fortran Notes: 30463813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 30473813dfbdSMatthew G Knepley include petsc.h90 in your code. 30483b12b3d8SVaclav Hapla You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 3049922102d1SVaclav Hapla DMPlexRestoreConeOrientation() is not needed/available in C. 30503813dfbdSMatthew G Knepley 3051db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3052552f7358SJed Brown @*/ 3053552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3054552f7358SJed Brown { 3055552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3056552f7358SJed Brown PetscInt off; 3057552f7358SJed Brown 3058552f7358SJed Brown PetscFunctionBegin; 3059552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 306076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3061552f7358SJed Brown PetscInt dof; 30629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3063552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 3064552f7358SJed Brown } 30659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30660d644c17SKarl Rupp 3067552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 3068552f7358SJed Brown PetscFunctionReturn(0); 3069552f7358SJed Brown } 3070552f7358SJed Brown 3071552f7358SJed Brown /*@ 3072eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3073552f7358SJed Brown 3074552f7358SJed Brown Not collective 3075552f7358SJed Brown 3076552f7358SJed Brown Input Parameters: 3077552f7358SJed Brown + mesh - The DMPlex 3078eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3079b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3080552f7358SJed Brown Output Parameter: 3081552f7358SJed Brown 3082b5a892a1SMatthew G. Knepley Notes: 3083552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3084552f7358SJed Brown 3085b5a892a1SMatthew G. Knepley The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3086b5a892a1SMatthew G. Knepley 3087552f7358SJed Brown Level: beginner 3088552f7358SJed Brown 3089db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3090552f7358SJed Brown @*/ 3091552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3092552f7358SJed Brown { 3093552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3094552f7358SJed Brown PetscInt pStart, pEnd; 3095552f7358SJed Brown PetscInt dof, off, c; 3096552f7358SJed Brown 3097552f7358SJed Brown PetscFunctionBegin; 3098552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 31009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3101dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(coneOrientation, 3); 31029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 310363a3b9bcSJacob 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); 3104552f7358SJed Brown for (c = 0; c < dof; ++c) { 3105552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3106552f7358SJed Brown 31079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof)); 31081dca8a05SBarry 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); 3109552f7358SJed Brown mesh->coneOrientations[off+c] = o; 3110552f7358SJed Brown } 3111552f7358SJed Brown PetscFunctionReturn(0); 3112552f7358SJed Brown } 3113552f7358SJed Brown 31147cd05799SMatthew G. Knepley /*@ 3115eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 31167cd05799SMatthew G. Knepley 31177cd05799SMatthew G. Knepley Not collective 31187cd05799SMatthew G. Knepley 31197cd05799SMatthew G. Knepley Input Parameters: 31207cd05799SMatthew G. Knepley + mesh - The DMPlex 3121eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31227cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31237cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 31247cd05799SMatthew G. Knepley 31257cd05799SMatthew G. Knepley Level: beginner 31267cd05799SMatthew G. Knepley 3127db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31287cd05799SMatthew G. Knepley @*/ 3129552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3130552f7358SJed Brown { 3131552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3132552f7358SJed Brown PetscInt pStart, pEnd; 3133552f7358SJed Brown PetscInt dof, off; 3134552f7358SJed Brown 3135552f7358SJed Brown PetscFunctionBegin; 3136552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 313863a3b9bcSJacob 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); 313963a3b9bcSJacob 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); 31409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 314263a3b9bcSJacob 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); 3143552f7358SJed Brown mesh->cones[off+conePos] = conePoint; 3144552f7358SJed Brown PetscFunctionReturn(0); 3145552f7358SJed Brown } 3146552f7358SJed Brown 31477cd05799SMatthew G. Knepley /*@ 3148eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 31497cd05799SMatthew G. Knepley 31507cd05799SMatthew G. Knepley Not collective 31517cd05799SMatthew G. Knepley 31527cd05799SMatthew G. Knepley Input Parameters: 31537cd05799SMatthew G. Knepley + mesh - The DMPlex 3154eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31557cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31567cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 31577cd05799SMatthew G. Knepley 31587cd05799SMatthew G. Knepley Level: beginner 31597cd05799SMatthew G. Knepley 3160b5a892a1SMatthew G. Knepley Notes: 3161b5a892a1SMatthew G. Knepley The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3162b5a892a1SMatthew G. Knepley 3163db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 31647cd05799SMatthew G. Knepley @*/ 316577c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 316677c88f5bSMatthew G Knepley { 316777c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 316877c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 316977c88f5bSMatthew G Knepley PetscInt dof, off; 317077c88f5bSMatthew G Knepley 317177c88f5bSMatthew G Knepley PetscFunctionBegin; 317277c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 317463a3b9bcSJacob 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); 31759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 317763a3b9bcSJacob 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); 317877c88f5bSMatthew G Knepley mesh->coneOrientations[off+conePos] = coneOrientation; 317977c88f5bSMatthew G Knepley PetscFunctionReturn(0); 318077c88f5bSMatthew G Knepley } 318177c88f5bSMatthew G Knepley 3182552f7358SJed Brown /*@ 3183eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return 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 3191552f7358SJed Brown Output Parameter: 3192552f7358SJed Brown . size - The support size for point p 3193552f7358SJed Brown 3194552f7358SJed Brown Level: beginner 3195552f7358SJed Brown 3196db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3197552f7358SJed Brown @*/ 3198552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3199552f7358SJed Brown { 3200552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3201552f7358SJed Brown 3202552f7358SJed Brown PetscFunctionBegin; 3203552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3204dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 32059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 3206552f7358SJed Brown PetscFunctionReturn(0); 3207552f7358SJed Brown } 3208552f7358SJed Brown 3209552f7358SJed Brown /*@ 3210eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3211552f7358SJed Brown 3212552f7358SJed Brown Not collective 3213552f7358SJed Brown 3214552f7358SJed Brown Input Parameters: 3215552f7358SJed Brown + mesh - The DMPlex 3216eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3217552f7358SJed Brown - size - The support size for point p 3218552f7358SJed Brown 3219552f7358SJed Brown Output Parameter: 3220552f7358SJed Brown 3221552f7358SJed Brown Note: 3222552f7358SJed Brown This should be called after DMPlexSetChart(). 3223552f7358SJed Brown 3224552f7358SJed Brown Level: beginner 3225552f7358SJed Brown 3226db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3227552f7358SJed Brown @*/ 3228552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3229552f7358SJed Brown { 3230552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3231552f7358SJed Brown 3232552f7358SJed Brown PetscFunctionBegin; 3233552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 3235552f7358SJed Brown PetscFunctionReturn(0); 3236552f7358SJed Brown } 3237552f7358SJed Brown 3238552f7358SJed Brown /*@C 3239eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3240552f7358SJed Brown 3241552f7358SJed Brown Not collective 3242552f7358SJed Brown 3243552f7358SJed Brown Input Parameters: 3244552f7358SJed Brown + mesh - The DMPlex 3245eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3246552f7358SJed Brown 3247552f7358SJed Brown Output Parameter: 3248552f7358SJed Brown . support - An array of points which are on the out-edges for point p 3249552f7358SJed Brown 3250552f7358SJed Brown Level: beginner 3251552f7358SJed Brown 32523813dfbdSMatthew G Knepley Fortran Notes: 32533813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 32543813dfbdSMatthew G Knepley include petsc.h90 in your code. 32553b12b3d8SVaclav Hapla You must also call DMPlexRestoreSupport() after you finish using the returned array. 3256922102d1SVaclav Hapla DMPlexRestoreSupport() is not needed/available in C. 32573813dfbdSMatthew G Knepley 3258db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3259552f7358SJed Brown @*/ 3260552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3261552f7358SJed Brown { 3262552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3263552f7358SJed Brown PetscInt off; 3264552f7358SJed Brown 3265552f7358SJed Brown PetscFunctionBegin; 3266552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3267552f7358SJed Brown PetscValidPointer(support, 3); 32689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3269552f7358SJed Brown *support = &mesh->supports[off]; 3270552f7358SJed Brown PetscFunctionReturn(0); 3271552f7358SJed Brown } 3272552f7358SJed Brown 3273552f7358SJed Brown /*@ 327492371b87SBarry 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 3275552f7358SJed Brown 3276552f7358SJed Brown Not collective 3277552f7358SJed Brown 3278552f7358SJed Brown Input Parameters: 3279552f7358SJed Brown + mesh - The DMPlex 3280eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 328192371b87SBarry Smith - support - An array of points which are on the out-edges for point p 3282552f7358SJed Brown 3283552f7358SJed Brown Output Parameter: 3284552f7358SJed Brown 3285552f7358SJed Brown Note: 3286552f7358SJed Brown This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3287552f7358SJed Brown 3288552f7358SJed Brown Level: beginner 3289552f7358SJed Brown 3290db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3291552f7358SJed Brown @*/ 3292552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3293552f7358SJed Brown { 3294552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3295552f7358SJed Brown PetscInt pStart, pEnd; 3296552f7358SJed Brown PetscInt dof, off, c; 3297552f7358SJed Brown 3298552f7358SJed Brown PetscFunctionBegin; 3299552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 3302dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(support, 3); 33039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 330463a3b9bcSJacob 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); 3305552f7358SJed Brown for (c = 0; c < dof; ++c) { 330663a3b9bcSJacob 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); 3307552f7358SJed Brown mesh->supports[off+c] = support[c]; 3308552f7358SJed Brown } 3309552f7358SJed Brown PetscFunctionReturn(0); 3310552f7358SJed Brown } 3311552f7358SJed Brown 33127cd05799SMatthew G. Knepley /*@ 3313eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 33147cd05799SMatthew G. Knepley 33157cd05799SMatthew G. Knepley Not collective 33167cd05799SMatthew G. Knepley 33177cd05799SMatthew G. Knepley Input Parameters: 33187cd05799SMatthew G. Knepley + mesh - The DMPlex 3319eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 33207cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 33217cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 33227cd05799SMatthew G. Knepley 33237cd05799SMatthew G. Knepley Level: beginner 33247cd05799SMatthew G. Knepley 3325db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 33267cd05799SMatthew G. Knepley @*/ 3327552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3328552f7358SJed Brown { 3329552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3330552f7358SJed Brown PetscInt pStart, pEnd; 3331552f7358SJed Brown PetscInt dof, off; 3332552f7358SJed Brown 3333552f7358SJed Brown PetscFunctionBegin; 3334552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 33379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 333863a3b9bcSJacob 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); 333963a3b9bcSJacob 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); 334063a3b9bcSJacob 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); 3341552f7358SJed Brown mesh->supports[off+supportPos] = supportPoint; 3342552f7358SJed Brown PetscFunctionReturn(0); 3343552f7358SJed Brown } 3344552f7358SJed Brown 3345b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3346b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3347b5a892a1SMatthew G. Knepley { 3348b5a892a1SMatthew G. Knepley switch (ct) { 3349b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3350b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3351b5a892a1SMatthew G. Knepley break; 3352b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3353b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3354b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3355b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3356b5a892a1SMatthew G. Knepley break; 3357b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3358b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3359b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3360b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3361b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3362b5a892a1SMatthew G. Knepley break; 3363b5a892a1SMatthew G. Knepley default: return o; 3364b5a892a1SMatthew G. Knepley } 3365b5a892a1SMatthew G. Knepley return o; 3366b5a892a1SMatthew G. Knepley } 3367b5a892a1SMatthew G. Knepley 3368b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3369b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3370b5a892a1SMatthew G. Knepley { 3371b5a892a1SMatthew G. Knepley switch (ct) { 3372b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3373b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3374b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3375b5a892a1SMatthew G. Knepley break; 3376b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3377b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3378b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3379b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3380b5a892a1SMatthew G. Knepley break; 3381b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3382b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3383b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3384b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3385b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3386b5a892a1SMatthew G. Knepley break; 3387b5a892a1SMatthew G. Knepley default: return o; 3388b5a892a1SMatthew G. Knepley } 3389b5a892a1SMatthew G. Knepley return o; 3390b5a892a1SMatthew G. Knepley } 3391b5a892a1SMatthew G. Knepley 3392b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3393b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3394b5a892a1SMatthew G. Knepley { 3395b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3396b5a892a1SMatthew G. Knepley 3397b5a892a1SMatthew G. Knepley PetscFunctionBegin; 33989566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3399b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3400b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3401b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3402b5a892a1SMatthew G. Knepley 34039566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 34049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 34059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3406b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3407b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3408b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3409b5a892a1SMatthew G. Knepley 34109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3411b5a892a1SMatthew G. Knepley switch (ct) { 3412b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 34139566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34149566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3415b5a892a1SMatthew G. Knepley break; 3416b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 34179566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 34189566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34199566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3420b5a892a1SMatthew G. Knepley break; 3421b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 34229566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 34239566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 34249566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 34259566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3426b5a892a1SMatthew G. Knepley break; 3427b5a892a1SMatthew G. Knepley default: break; 3428b5a892a1SMatthew G. Knepley } 3429b5a892a1SMatthew G. Knepley } 3430b5a892a1SMatthew G. Knepley } 3431b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3432b5a892a1SMatthew G. Knepley } 3433b5a892a1SMatthew G. Knepley 3434012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3435b5a892a1SMatthew G. Knepley { 3436b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3437b5a892a1SMatthew G. Knepley PetscInt *closure; 3438b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3439b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3440b5a892a1SMatthew G. Knepley 3441b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3442b5a892a1SMatthew G. Knepley if (ornt) { 34439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3444b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3445b5a892a1SMatthew G. Knepley } 3446b5a892a1SMatthew G. Knepley if (*points) { 3447b5a892a1SMatthew G. Knepley closure = *points; 3448b5a892a1SMatthew G. Knepley } else { 3449b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 34509566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 34519566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure)); 3452b5a892a1SMatthew G. Knepley } 3453b5a892a1SMatthew G. Knepley if (useCone) { 34549566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &tmpSize)); 34559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &tmp)); 34569566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO)); 3457b5a892a1SMatthew G. Knepley } else { 34589566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize)); 34599566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &tmp)); 3460b5a892a1SMatthew G. Knepley } 3461b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3462b5a892a1SMatthew G. Knepley closure[off++] = p; 3463b5a892a1SMatthew G. Knepley closure[off++] = 0; 3464b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3465b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3466b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3467b5a892a1SMatthew G. Knepley } 3468b5a892a1SMatthew G. Knepley } else { 34695f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3470b5a892a1SMatthew G. Knepley 3471b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3472b5a892a1SMatthew G. Knepley closure[off++] = p; 3473b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3474b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3475b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3476b5a892a1SMatthew G. Knepley 34779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3478b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3479b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3480b5a892a1SMatthew G. Knepley } 3481b5a892a1SMatthew G. Knepley } 3482b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize+1; 3483b5a892a1SMatthew G. Knepley if (points) *points = closure; 3484b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3485b5a892a1SMatthew G. Knepley } 3486b5a892a1SMatthew G. Knepley 3487b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3488b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3489b5a892a1SMatthew G. Knepley { 3490b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3491b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3492b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3493b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3494b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3495b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3496b5a892a1SMatthew G. Knepley 3497b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 34989566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 34999566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 35009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 35019566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &ornt)); 35029566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3503b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3504b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3505b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 3506b5a892a1SMatthew G. Knepley if (*points) {pts = *points;} 35079566063dSJacob Faibussowitsch else PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts)); 3508b5a892a1SMatthew G. Knepley c = 0; 3509b5a892a1SMatthew G. Knepley pts[c++] = point; 3510b5a892a1SMatthew G. Knepley pts[c++] = o; 35119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft)); 35129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure)); 3513b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 35149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure)); 3515b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 35169566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3517b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 35189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft)); 3519b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d*2+0]]; 3520b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3521b5a892a1SMatthew G. Knepley } 3522b5a892a1SMatthew G. Knepley if (dim >= 3) { 3523b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3524b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d*2+0]]; 3525b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3526b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3527b5a892a1SMatthew G. Knepley 35289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3529b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 35309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize)); 35319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, fpoint, &fcone)); 35329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt)); 3533b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3534b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc*2+0]]; 3535b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc*2+1]; 3536b5a892a1SMatthew G. Knepley 3537b5a892a1SMatthew G. Knepley for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3538b5a892a1SMatthew G. Knepley if (i == c) { 35399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3540b5a892a1SMatthew G. Knepley pts[c++] = cp; 3541b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3542b5a892a1SMatthew G. Knepley } 3543b5a892a1SMatthew G. Knepley } 3544b5a892a1SMatthew G. Knepley } 3545b5a892a1SMatthew G. Knepley } 3546b5a892a1SMatthew G. Knepley *numPoints = c/2; 3547b5a892a1SMatthew G. Knepley *points = pts; 3548b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3549b5a892a1SMatthew G. Knepley } 3550b5a892a1SMatthew G. Knepley 3551b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3552b5a892a1SMatthew G. Knepley { 3553b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3554b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3555b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3556b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3557b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3558b5a892a1SMatthew G. Knepley 3559b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 35609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3561b5a892a1SMatthew G. Knepley if (depth == 1) { 35629566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 3563b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3564b5a892a1SMatthew G. Knepley } 35659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3566b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3567b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 35689566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 3569b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3570b5a892a1SMatthew G. Knepley } 35719566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3572b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3573b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3574b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 35759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3576b5a892a1SMatthew G. Knepley if (*points) {closure = *points;} 35779566063dSJacob Faibussowitsch else PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure)); 3578b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3579b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3580b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3581b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3582b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3583b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3584b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3585b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3586b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3587b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3588b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3589b5a892a1SMatthew G. Knepley const PetscInt *tmp, *tmpO; 3590b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3591b5a892a1SMatthew G. Knepley 3592b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3593b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 359463a3b9bcSJacob 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); 3595b5a892a1SMatthew G. Knepley } 3596b5a892a1SMatthew G. Knepley if (useCone) { 35979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &tmpSize)); 35989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &tmp)); 35999566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO)); 3600b5a892a1SMatthew G. Knepley } else { 36019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize)); 36029566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &tmp)); 3603b5a892a1SMatthew G. Knepley tmpO = NULL; 3604b5a892a1SMatthew G. Knepley } 3605b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3606b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3607b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3608b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 36099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3610b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3611b5a892a1SMatthew G. Knepley PetscInt c; 3612b5a892a1SMatthew G. Knepley 3613b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3614b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3615b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3616b5a892a1SMatthew G. Knepley } 3617b5a892a1SMatthew G. Knepley if (c == closureSize) { 3618b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3619b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3620b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3621b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3622b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3623b5a892a1SMatthew G. Knepley } 3624b5a892a1SMatthew G. Knepley } 3625b5a892a1SMatthew G. Knepley } 36269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3627b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize/2; 3628b5a892a1SMatthew G. Knepley if (points) *points = closure; 3629b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3630b5a892a1SMatthew G. Knepley } 3631b5a892a1SMatthew G. Knepley 3632552f7358SJed Brown /*@C 3633eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3634552f7358SJed Brown 3635552f7358SJed Brown Not collective 3636552f7358SJed Brown 3637552f7358SJed Brown Input Parameters: 3638b5a892a1SMatthew G. Knepley + dm - The DMPlex 3639b5a892a1SMatthew G. Knepley . p - The mesh point 36406b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star 3641552f7358SJed Brown 36426b867d5aSJose E. Roman Input/Output Parameter: 36436b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 36446b867d5aSJose E. Roman if NULL on input, internal storage will be returned, otherwise the provided array is used 36456b867d5aSJose E. Roman 36466b867d5aSJose E. Roman Output Parameter: 36476b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3648552f7358SJed Brown 3649552f7358SJed Brown Note: 36500298fd71SBarry Smith If using internal storage (points is NULL on input), each call overwrites the last output. 3651552f7358SJed Brown 36523813dfbdSMatthew G Knepley Fortran Notes: 3653b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36543813dfbdSMatthew G Knepley 36553813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36563813dfbdSMatthew G Knepley 3657552f7358SJed Brown Level: beginner 3658552f7358SJed Brown 3659db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3660552f7358SJed Brown @*/ 3661552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3662552f7358SJed Brown { 3663b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3664552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3665b5a892a1SMatthew G. Knepley if (numPoints) PetscValidIntPointer(numPoints, 4); 3666b5a892a1SMatthew G. Knepley if (points) PetscValidPointer(points, 5); 36679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 36689bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 36699bf0dad6SMatthew G. Knepley } 36709bf0dad6SMatthew G. Knepley 3671552f7358SJed Brown /*@C 3672eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3673552f7358SJed Brown 3674552f7358SJed Brown Not collective 3675552f7358SJed Brown 3676552f7358SJed Brown Input Parameters: 3677b5a892a1SMatthew G. Knepley + dm - The DMPlex 3678b5a892a1SMatthew G. Knepley . p - The mesh point 3679b5a892a1SMatthew G. Knepley . useCone - PETSC_TRUE for the closure, otherwise return the star 3680b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3681b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3682552f7358SJed Brown 3683552f7358SJed Brown Note: 36840298fd71SBarry Smith If not using internal storage (points is not NULL on input), this call is unnecessary 3685552f7358SJed Brown 36863813dfbdSMatthew G Knepley Fortran Notes: 3687b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36883813dfbdSMatthew G Knepley 36893813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36903813dfbdSMatthew G Knepley 3691552f7358SJed Brown Level: beginner 3692552f7358SJed Brown 3693db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 3694552f7358SJed Brown @*/ 3695552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3696552f7358SJed Brown { 3697b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3698552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36994ff43b2cSJed Brown if (numPoints) *numPoints = 0; 37009566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 3701552f7358SJed Brown PetscFunctionReturn(0); 3702552f7358SJed Brown } 3703552f7358SJed Brown 3704552f7358SJed Brown /*@ 3705eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3706552f7358SJed Brown 3707552f7358SJed Brown Not collective 3708552f7358SJed Brown 3709552f7358SJed Brown Input Parameter: 3710552f7358SJed Brown . mesh - The DMPlex 3711552f7358SJed Brown 3712552f7358SJed Brown Output Parameters: 3713552f7358SJed Brown + maxConeSize - The maximum number of in-edges 3714552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 3715552f7358SJed Brown 3716552f7358SJed Brown Level: beginner 3717552f7358SJed Brown 3718db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3719552f7358SJed Brown @*/ 3720552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3721552f7358SJed Brown { 3722552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3723552f7358SJed Brown 3724552f7358SJed Brown PetscFunctionBegin; 3725552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37266302a7fbSVaclav Hapla if (maxConeSize) { 37276302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 37286302a7fbSVaclav Hapla } 37296302a7fbSVaclav Hapla if (maxSupportSize) { 37306302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 37316302a7fbSVaclav Hapla } 3732552f7358SJed Brown PetscFunctionReturn(0); 3733552f7358SJed Brown } 3734552f7358SJed Brown 3735552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm) 3736552f7358SJed Brown { 3737552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 37386302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 3739552f7358SJed Brown 3740552f7358SJed Brown PetscFunctionBegin; 3741552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 37439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 37449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 37459566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 37469566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt))); 37476302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 37486302a7fbSVaclav Hapla if (maxSupportSize) { 37499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 37509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 37519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 37529566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt))); 3753552f7358SJed Brown } 3754552f7358SJed Brown PetscFunctionReturn(0); 3755552f7358SJed Brown } 3756552f7358SJed Brown 3757276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3758552f7358SJed Brown { 3759552f7358SJed Brown PetscFunctionBegin; 37609566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 37619566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 3762c2939958SSatish Balay if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3763736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 3764f94b4a02SBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 3765f94b4a02SBlaise Bourdin PetscSection section, sectionSeq; 3766f94b4a02SBlaise Bourdin 37673dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 37689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dm->sfMigration)); 37699566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection((*subdm), §ion)); 37709566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv)); 37719566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq)); 37729566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 3773f94b4a02SBlaise Bourdin 37749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural)); 3775c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 37769566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionSeq)); 37779566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 3778f94b4a02SBlaise Bourdin } 3779552f7358SJed Brown PetscFunctionReturn(0); 3780552f7358SJed Brown } 3781552f7358SJed Brown 37822adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 37832adcc780SMatthew G. Knepley { 37843dcd263cSBlaise Bourdin PetscInt i = 0; 37852adcc780SMatthew G. Knepley 37862adcc780SMatthew G. Knepley PetscFunctionBegin; 37879566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 37889566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 3789c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 37903dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 37913dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 37923dcd263cSBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 37933dcd263cSBlaise Bourdin PetscSection section, sectionSeq; 37943dcd263cSBlaise Bourdin 37953dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 37969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dms[i]->sfMigration)); 3797c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 37989566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection((*superdm), §ion)); 37999566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv)); 38009566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq)); 38019566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 38023dcd263cSBlaise Bourdin 38039566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural)); 3804c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 38059566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionSeq)); 38069566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 38073dcd263cSBlaise Bourdin break; 38083dcd263cSBlaise Bourdin } 38093dcd263cSBlaise Bourdin } 38102adcc780SMatthew G. Knepley PetscFunctionReturn(0); 38112adcc780SMatthew G. Knepley } 38122adcc780SMatthew G. Knepley 3813552f7358SJed Brown /*@ 3814eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3815552f7358SJed Brown 3816552f7358SJed Brown Not collective 3817552f7358SJed Brown 3818552f7358SJed Brown Input Parameter: 3819552f7358SJed Brown . mesh - The DMPlex 3820552f7358SJed Brown 3821552f7358SJed Brown Output Parameter: 3822552f7358SJed Brown 3823552f7358SJed Brown Note: 3824552f7358SJed Brown This should be called after all calls to DMPlexSetCone() 3825552f7358SJed Brown 3826552f7358SJed Brown Level: beginner 3827552f7358SJed Brown 3828db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 3829552f7358SJed Brown @*/ 3830552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm) 3831552f7358SJed Brown { 3832552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3833552f7358SJed Brown PetscInt *offsets; 3834552f7358SJed Brown PetscInt supportSize; 3835552f7358SJed Brown PetscInt pStart, pEnd, p; 3836552f7358SJed Brown 3837552f7358SJed Brown PetscFunctionBegin; 3838552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 383928b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 38409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0)); 3841552f7358SJed Brown /* Calculate support sizes */ 38429566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3843552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3844552f7358SJed Brown PetscInt dof, off, c; 3845552f7358SJed Brown 38469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3848552f7358SJed Brown for (c = off; c < off+dof; ++c) { 38499566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 3850552f7358SJed Brown } 3851552f7358SJed Brown } 38529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 3853552f7358SJed Brown /* Calculate supports */ 38549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 38559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 38569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 3857552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3858552f7358SJed Brown PetscInt dof, off, c; 3859552f7358SJed Brown 38609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3862552f7358SJed Brown for (c = off; c < off+dof; ++c) { 3863552f7358SJed Brown const PetscInt q = mesh->cones[c]; 3864552f7358SJed Brown PetscInt offS; 3865552f7358SJed Brown 38669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 38670d644c17SKarl Rupp 3868552f7358SJed Brown mesh->supports[offS+offsets[q]] = p; 3869552f7358SJed Brown ++offsets[q]; 3870552f7358SJed Brown } 3871552f7358SJed Brown } 38729566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 38739566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0)); 3874552f7358SJed Brown PetscFunctionReturn(0); 3875552f7358SJed Brown } 3876552f7358SJed Brown 3877277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3878277ea44aSLisandro Dalcin { 3879277ea44aSLisandro Dalcin IS stratumIS; 3880277ea44aSLisandro Dalcin 3881277ea44aSLisandro Dalcin PetscFunctionBegin; 3882277ea44aSLisandro Dalcin if (pStart >= pEnd) PetscFunctionReturn(0); 388376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3884277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 3885277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 38869566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 3887277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 38889566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3889277ea44aSLisandro Dalcin if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3890277ea44aSLisandro Dalcin } 389163a3b9bcSJacob 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); 3892277ea44aSLisandro Dalcin } 38939566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS)); 38949566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 38959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 3896277ea44aSLisandro Dalcin PetscFunctionReturn(0); 3897277ea44aSLisandro Dalcin } 3898277ea44aSLisandro Dalcin 3899552f7358SJed Brown /*@ 3900a8d69d7bSBarry Smith DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 39016dd80730SBarry Smith can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3902552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3903552f7358SJed Brown the DAG. 3904552f7358SJed Brown 3905bf4602e4SToby Isaac Collective on dm 3906552f7358SJed Brown 3907552f7358SJed Brown Input Parameter: 3908552f7358SJed Brown . mesh - The DMPlex 3909552f7358SJed Brown 3910552f7358SJed Brown Output Parameter: 3911552f7358SJed Brown 3912552f7358SJed Brown Notes: 3913b1bb481bSMatthew Knepley Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3914b1bb481bSMatthew 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 3915b1bb481bSMatthew Knepley until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3916c58f1c22SToby Isaac manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3917150b719bSJed Brown via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3918552f7358SJed Brown 3919b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3920b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3921b1bb481bSMatthew 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 3922b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 3923b1bb481bSMatthew Knepley $ cone(c0) = {e0, v2} 3924b1bb481bSMatthew Knepley $ cone(e0) = {v0, v1} 3925b1bb481bSMatthew Knepley If DMPlexStratify() is run on this mesh, it will give depths 3926b1bb481bSMatthew Knepley $ depth 0 = {v0, v1, v2} 3927b1bb481bSMatthew Knepley $ depth 1 = {e0, c0} 3928b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3929b1bb481bSMatthew Knepley 3930150b719bSJed Brown DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3931552f7358SJed Brown 3932552f7358SJed Brown Level: beginner 3933552f7358SJed Brown 3934db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 3935552f7358SJed Brown @*/ 3936552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm) 3937552f7358SJed Brown { 3938df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 3939aa50250dSMatthew G. Knepley DMLabel label; 3940552f7358SJed Brown PetscInt pStart, pEnd, p; 3941552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 3942552f7358SJed Brown 3943552f7358SJed Brown PetscFunctionBegin; 3944552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39459566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0)); 3946277ea44aSLisandro Dalcin 3947277ea44aSLisandro Dalcin /* Create depth label */ 39489566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 39499566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 39509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 3951277ea44aSLisandro Dalcin 3952277ea44aSLisandro Dalcin { 3953552f7358SJed Brown /* Initialize roots and count leaves */ 3954277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3955277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3956552f7358SJed Brown PetscInt coneSize, supportSize; 3957552f7358SJed Brown 3958277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39599566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39609566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3961552f7358SJed Brown if (!coneSize && supportSize) { 3962277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3963277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3964552f7358SJed Brown ++numRoots; 3965552f7358SJed Brown } else if (!supportSize && coneSize) { 3966552f7358SJed Brown ++numLeaves; 3967552f7358SJed Brown } else if (!supportSize && !coneSize) { 3968552f7358SJed Brown /* Isolated points */ 3969277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3970277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3971552f7358SJed Brown } 3972552f7358SJed Brown } 39739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1)); 3974277ea44aSLisandro Dalcin } 3975277ea44aSLisandro Dalcin 3976552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 3977277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3978277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3979552f7358SJed Brown PetscInt coneSize, supportSize; 3980552f7358SJed Brown 3981277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39839566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 3984552f7358SJed Brown if (!supportSize && coneSize) { 3985277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3986277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3987552f7358SJed Brown } 3988552f7358SJed Brown } 39899566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1)); 3990552f7358SJed Brown } else { 3991277ea44aSLisandro Dalcin PetscInt level = 0; 3992277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 3993552f7358SJed Brown 39949566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3995277ea44aSLisandro Dalcin while (qEnd > qStart) { 3996277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3997277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 399874ef644bSMatthew G. Knepley 3999277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 400074ef644bSMatthew G. Knepley const PetscInt *support; 400174ef644bSMatthew G. Knepley PetscInt supportSize, s; 400274ef644bSMatthew G. Knepley 40039566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 40049566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &support)); 400574ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 4006277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 4007277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 4008552f7358SJed Brown } 4009552f7358SJed Brown } 40109566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &level)); 40119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1)); 40129566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 401374ef644bSMatthew G. Knepley } 401474ef644bSMatthew G. Knepley } 4015bf4602e4SToby Isaac { /* just in case there is an empty process */ 4016bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4017bf4602e4SToby Isaac 40189566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 40199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 4020bf4602e4SToby Isaac for (v = numValues; v < maxValues; v++) { 40219566063dSJacob Faibussowitsch PetscCall(DMLabelAddStratum(label, v)); 4022bf4602e4SToby Isaac } 4023bf4602e4SToby Isaac } 40249566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject) label, &mesh->depthState)); 40259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0)); 4026552f7358SJed Brown PetscFunctionReturn(0); 4027552f7358SJed Brown } 4028552f7358SJed Brown 4029412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4030ba2698f1SMatthew G. Knepley { 4031412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4032412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4033ba2698f1SMatthew G. Knepley 4034412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 40359566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 40369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 40379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4038ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4039ba2698f1SMatthew G. Knepley if (depth <= 1) { 4040ba2698f1SMatthew G. Knepley switch (pdepth) { 4041ba2698f1SMatthew G. Knepley case 0: ct = DM_POLYTOPE_POINT;break; 4042ba2698f1SMatthew G. Knepley case 1: 4043ba2698f1SMatthew G. Knepley switch (coneSize) { 4044ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4045ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4046ba2698f1SMatthew G. Knepley case 4: 4047ba2698f1SMatthew G. Knepley switch (dim) { 4048ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 4049ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 4050ba2698f1SMatthew G. Knepley default: break; 4051ba2698f1SMatthew G. Knepley } 4052ba2698f1SMatthew G. Knepley break; 4053da9060c4SMatthew G. Knepley case 5: ct = DM_POLYTOPE_PYRAMID;break; 4054ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4055ba2698f1SMatthew G. Knepley case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 4056ba2698f1SMatthew G. Knepley default: break; 4057ba2698f1SMatthew G. Knepley } 4058ba2698f1SMatthew G. Knepley } 4059ba2698f1SMatthew G. Knepley } else { 4060ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4061ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4062ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4063ba2698f1SMatthew G. Knepley switch (dim) { 4064ba2698f1SMatthew G. Knepley case 1: 4065ba2698f1SMatthew G. Knepley switch (coneSize) { 4066ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4067ba2698f1SMatthew G. Knepley default: break; 4068ba2698f1SMatthew G. Knepley } 4069ba2698f1SMatthew G. Knepley break; 4070ba2698f1SMatthew G. Knepley case 2: 4071ba2698f1SMatthew G. Knepley switch (coneSize) { 4072ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4073ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4074ba2698f1SMatthew G. Knepley default: break; 4075ba2698f1SMatthew G. Knepley } 4076ba2698f1SMatthew G. Knepley break; 4077ba2698f1SMatthew G. Knepley case 3: 4078ba2698f1SMatthew G. Knepley switch (coneSize) { 4079ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4080da9060c4SMatthew G. Knepley case 5: 4081da9060c4SMatthew G. Knepley { 4082da9060c4SMatthew G. Knepley const PetscInt *cone; 4083da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4084da9060c4SMatthew G. Knepley 40859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 40869566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4087da9060c4SMatthew G. Knepley switch (faceConeSize) { 4088da9060c4SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4089da9060c4SMatthew G. Knepley case 4: ct = DM_POLYTOPE_PYRAMID;break; 4090da9060c4SMatthew G. Knepley } 4091da9060c4SMatthew G. Knepley } 4092da9060c4SMatthew G. Knepley break; 4093ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4094ba2698f1SMatthew G. Knepley default: break; 4095ba2698f1SMatthew G. Knepley } 4096ba2698f1SMatthew G. Knepley break; 4097ba2698f1SMatthew G. Knepley default: break; 4098ba2698f1SMatthew G. Knepley } 4099ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4100ba2698f1SMatthew G. Knepley switch (coneSize) { 4101ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4102ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4103ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4104ba2698f1SMatthew G. Knepley default: break; 4105ba2698f1SMatthew G. Knepley } 4106ba2698f1SMatthew G. Knepley } 4107ba2698f1SMatthew G. Knepley } 4108412e9a14SMatthew G. Knepley *pt = ct; 4109412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4110ba2698f1SMatthew G. Knepley } 4111412e9a14SMatthew G. Knepley 4112412e9a14SMatthew G. Knepley /*@ 4113412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4114412e9a14SMatthew G. Knepley 4115412e9a14SMatthew G. Knepley Collective on dm 4116412e9a14SMatthew G. Knepley 4117412e9a14SMatthew G. Knepley Input Parameter: 4118412e9a14SMatthew G. Knepley . mesh - The DMPlex 4119412e9a14SMatthew G. Knepley 4120412e9a14SMatthew G. Knepley DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4121412e9a14SMatthew G. Knepley 4122412e9a14SMatthew G. Knepley Level: developer 4123412e9a14SMatthew G. Knepley 4124412e9a14SMatthew G. Knepley Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4125412e9a14SMatthew G. Knepley internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4126412e9a14SMatthew G. Knepley automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4127412e9a14SMatthew G. Knepley 4128db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4129412e9a14SMatthew G. Knepley @*/ 4130412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm) 4131412e9a14SMatthew G. Knepley { 4132412e9a14SMatthew G. Knepley DM_Plex *mesh; 4133412e9a14SMatthew G. Knepley DMLabel ctLabel; 4134412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4135412e9a14SMatthew G. Knepley 4136412e9a14SMatthew G. Knepley PetscFunctionBegin; 4137412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4138412e9a14SMatthew G. Knepley mesh = (DM_Plex *) dm->data; 41399566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 41409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 41419566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4142412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4143327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4144412e9a14SMatthew G. Knepley PetscInt pdepth; 4145412e9a14SMatthew G. Knepley 41469566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 41479566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 414863a3b9bcSJacob Faibussowitsch PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 41499566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 4150412e9a14SMatthew G. Knepley } 41519566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState)); 41529566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view")); 4153ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4154ba2698f1SMatthew G. Knepley } 4155ba2698f1SMatthew G. Knepley 4156552f7358SJed Brown /*@C 4157552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4158552f7358SJed Brown 4159552f7358SJed Brown Not Collective 4160552f7358SJed Brown 4161552f7358SJed Brown Input Parameters: 4162552f7358SJed Brown + dm - The DMPlex object 4163552f7358SJed Brown . numPoints - The number of input points for the join 4164552f7358SJed Brown - points - The input points 4165552f7358SJed Brown 4166552f7358SJed Brown Output Parameters: 4167552f7358SJed Brown + numCoveredPoints - The number of points in the join 4168552f7358SJed Brown - coveredPoints - The points in the join 4169552f7358SJed Brown 4170552f7358SJed Brown Level: intermediate 4171552f7358SJed Brown 4172552f7358SJed Brown Note: Currently, this is restricted to a single level join 4173552f7358SJed Brown 41743813dfbdSMatthew G Knepley Fortran Notes: 41753813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 41763813dfbdSMatthew G Knepley include petsc.h90 in your code. 41773813dfbdSMatthew G Knepley 41783813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 41793813dfbdSMatthew G Knepley 4180db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4181552f7358SJed Brown @*/ 4182552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4183552f7358SJed Brown { 4184552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4185552f7358SJed Brown PetscInt *join[2]; 4186552f7358SJed Brown PetscInt joinSize, i = 0; 4187552f7358SJed Brown PetscInt dof, off, p, c, m; 41886302a7fbSVaclav Hapla PetscInt maxSupportSize; 4189552f7358SJed Brown 4190552f7358SJed Brown PetscFunctionBegin; 4191552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 419248bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 419348bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 419448bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 41956302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41966302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 41976302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4198552f7358SJed Brown /* Copy in support of first point */ 41999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 42009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4201552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4202552f7358SJed Brown join[i][joinSize] = mesh->supports[off+joinSize]; 4203552f7358SJed Brown } 4204552f7358SJed Brown /* Check each successive support */ 4205552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4206552f7358SJed Brown PetscInt newJoinSize = 0; 4207552f7358SJed Brown 42089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 42099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4210552f7358SJed Brown for (c = 0; c < dof; ++c) { 4211552f7358SJed Brown const PetscInt point = mesh->supports[off+c]; 4212552f7358SJed Brown 4213552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4214552f7358SJed Brown if (point == join[i][m]) { 4215552f7358SJed Brown join[1-i][newJoinSize++] = point; 4216552f7358SJed Brown break; 4217552f7358SJed Brown } 4218552f7358SJed Brown } 4219552f7358SJed Brown } 4220552f7358SJed Brown joinSize = newJoinSize; 4221552f7358SJed Brown i = 1-i; 4222552f7358SJed Brown } 4223552f7358SJed Brown *numCoveredPoints = joinSize; 4224552f7358SJed Brown *coveredPoints = join[i]; 42256302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1-i])); 4226552f7358SJed Brown PetscFunctionReturn(0); 4227552f7358SJed Brown } 4228552f7358SJed Brown 4229552f7358SJed Brown /*@C 4230552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4231552f7358SJed Brown 4232552f7358SJed Brown Not Collective 4233552f7358SJed Brown 4234552f7358SJed Brown Input Parameters: 4235552f7358SJed Brown + dm - The DMPlex object 4236552f7358SJed Brown . numPoints - The number of input points for the join 4237552f7358SJed Brown - points - The input points 4238552f7358SJed Brown 4239552f7358SJed Brown Output Parameters: 4240552f7358SJed Brown + numCoveredPoints - The number of points in the join 4241552f7358SJed Brown - coveredPoints - The points in the join 4242552f7358SJed Brown 42433813dfbdSMatthew G Knepley Fortran Notes: 42443813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42453813dfbdSMatthew G Knepley include petsc.h90 in your code. 42463813dfbdSMatthew G Knepley 42473813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42483813dfbdSMatthew G Knepley 4249552f7358SJed Brown Level: intermediate 4250552f7358SJed Brown 4251db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4252552f7358SJed Brown @*/ 4253552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4254552f7358SJed Brown { 4255552f7358SJed Brown PetscFunctionBegin; 4256552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4257d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4258d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4259d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 42609566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4261d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4262552f7358SJed Brown PetscFunctionReturn(0); 4263552f7358SJed Brown } 4264552f7358SJed Brown 4265552f7358SJed Brown /*@C 4266552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4267552f7358SJed Brown 4268552f7358SJed Brown Not Collective 4269552f7358SJed Brown 4270552f7358SJed Brown Input Parameters: 4271552f7358SJed Brown + dm - The DMPlex object 4272552f7358SJed Brown . numPoints - The number of input points for the join 4273552f7358SJed Brown - points - The input points 4274552f7358SJed Brown 4275552f7358SJed Brown Output Parameters: 4276552f7358SJed Brown + numCoveredPoints - The number of points in the join 4277552f7358SJed Brown - coveredPoints - The points in the join 4278552f7358SJed Brown 42793813dfbdSMatthew G Knepley Fortran Notes: 42803813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42813813dfbdSMatthew G Knepley include petsc.h90 in your code. 42823813dfbdSMatthew G Knepley 42833813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42843813dfbdSMatthew G Knepley 4285552f7358SJed Brown Level: intermediate 4286552f7358SJed Brown 4287db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4288552f7358SJed Brown @*/ 4289552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4290552f7358SJed Brown { 4291552f7358SJed Brown PetscInt *offsets, **closures; 4292552f7358SJed Brown PetscInt *join[2]; 4293552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 429424c766afSToby Isaac PetscInt p, d, c, m, ms; 4295552f7358SJed Brown 4296552f7358SJed Brown PetscFunctionBegin; 4297552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 429848bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 429948bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 430048bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 4301552f7358SJed Brown 43029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 43039566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 43049566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 43056302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 430624c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 43079566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 43089566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4309552f7358SJed Brown 4310552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4311552f7358SJed Brown PetscInt closureSize; 4312552f7358SJed Brown 43139566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 43140d644c17SKarl Rupp 4315552f7358SJed Brown offsets[p*(depth+2)+0] = 0; 4316552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4317552f7358SJed Brown PetscInt pStart, pEnd, i; 4318552f7358SJed Brown 43199566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4320552f7358SJed Brown for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4321552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4322552f7358SJed Brown offsets[p*(depth+2)+d+1] = i; 4323552f7358SJed Brown break; 4324552f7358SJed Brown } 4325552f7358SJed Brown } 4326552f7358SJed Brown if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4327552f7358SJed Brown } 432863a3b9bcSJacob 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); 4329552f7358SJed Brown } 4330552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4331552f7358SJed Brown PetscInt dof; 4332552f7358SJed Brown 4333552f7358SJed Brown /* Copy in support of first point */ 4334552f7358SJed Brown dof = offsets[d+1] - offsets[d]; 4335552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4336552f7358SJed Brown join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4337552f7358SJed Brown } 4338552f7358SJed Brown /* Check each successive cone */ 4339552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4340552f7358SJed Brown PetscInt newJoinSize = 0; 4341552f7358SJed Brown 4342552f7358SJed Brown dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4343552f7358SJed Brown for (c = 0; c < dof; ++c) { 4344552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4345552f7358SJed Brown 4346552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4347552f7358SJed Brown if (point == join[i][m]) { 4348552f7358SJed Brown join[1-i][newJoinSize++] = point; 4349552f7358SJed Brown break; 4350552f7358SJed Brown } 4351552f7358SJed Brown } 4352552f7358SJed Brown } 4353552f7358SJed Brown joinSize = newJoinSize; 4354552f7358SJed Brown i = 1-i; 4355552f7358SJed Brown } 4356552f7358SJed Brown if (joinSize) break; 4357552f7358SJed Brown } 4358552f7358SJed Brown *numCoveredPoints = joinSize; 4359552f7358SJed Brown *coveredPoints = join[i]; 4360552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 43619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 4362552f7358SJed Brown } 43639566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 43649566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 43656302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1-i])); 4366552f7358SJed Brown PetscFunctionReturn(0); 4367552f7358SJed Brown } 4368552f7358SJed Brown 4369552f7358SJed Brown /*@C 4370552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4371552f7358SJed Brown 4372552f7358SJed Brown Not Collective 4373552f7358SJed Brown 4374552f7358SJed Brown Input Parameters: 4375552f7358SJed Brown + dm - The DMPlex object 4376552f7358SJed Brown . numPoints - The number of input points for the meet 4377552f7358SJed Brown - points - The input points 4378552f7358SJed Brown 4379552f7358SJed Brown Output Parameters: 4380552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4381552f7358SJed Brown - coveredPoints - The points in the meet 4382552f7358SJed Brown 4383552f7358SJed Brown Level: intermediate 4384552f7358SJed Brown 4385552f7358SJed Brown Note: Currently, this is restricted to a single level meet 4386552f7358SJed Brown 43873813dfbdSMatthew G Knepley Fortran Notes: 43883813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 43893813dfbdSMatthew G Knepley include petsc.h90 in your code. 43903813dfbdSMatthew G Knepley 43913813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 43923813dfbdSMatthew G Knepley 4393db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4394552f7358SJed Brown @*/ 4395552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4396552f7358SJed Brown { 4397552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4398552f7358SJed Brown PetscInt *meet[2]; 4399552f7358SJed Brown PetscInt meetSize, i = 0; 4400552f7358SJed Brown PetscInt dof, off, p, c, m; 44016302a7fbSVaclav Hapla PetscInt maxConeSize; 4402552f7358SJed Brown 4403552f7358SJed Brown PetscFunctionBegin; 4404552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4405dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4406dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveringPoints, 4); 4407064a246eSJacob Faibussowitsch PetscValidPointer(coveringPoints, 5); 44086302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 44096302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 44106302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4411552f7358SJed Brown /* Copy in cone of first point */ 44129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 44139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4414552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4415552f7358SJed Brown meet[i][meetSize] = mesh->cones[off+meetSize]; 4416552f7358SJed Brown } 4417552f7358SJed Brown /* Check each successive cone */ 4418552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4419552f7358SJed Brown PetscInt newMeetSize = 0; 4420552f7358SJed Brown 44219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 44229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4423552f7358SJed Brown for (c = 0; c < dof; ++c) { 4424552f7358SJed Brown const PetscInt point = mesh->cones[off+c]; 4425552f7358SJed Brown 4426552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4427552f7358SJed Brown if (point == meet[i][m]) { 4428552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4429552f7358SJed Brown break; 4430552f7358SJed Brown } 4431552f7358SJed Brown } 4432552f7358SJed Brown } 4433552f7358SJed Brown meetSize = newMeetSize; 4434552f7358SJed Brown i = 1-i; 4435552f7358SJed Brown } 4436552f7358SJed Brown *numCoveringPoints = meetSize; 4437552f7358SJed Brown *coveringPoints = meet[i]; 44386302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1-i])); 4439552f7358SJed Brown PetscFunctionReturn(0); 4440552f7358SJed Brown } 4441552f7358SJed Brown 4442552f7358SJed Brown /*@C 4443552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4444552f7358SJed Brown 4445552f7358SJed Brown Not Collective 4446552f7358SJed Brown 4447552f7358SJed Brown Input Parameters: 4448552f7358SJed Brown + dm - The DMPlex object 4449552f7358SJed Brown . numPoints - The number of input points for the meet 4450552f7358SJed Brown - points - The input points 4451552f7358SJed Brown 4452552f7358SJed Brown Output Parameters: 4453552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4454552f7358SJed Brown - coveredPoints - The points in the meet 4455552f7358SJed Brown 4456552f7358SJed Brown Level: intermediate 4457552f7358SJed Brown 44583813dfbdSMatthew G Knepley Fortran Notes: 44593813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44603813dfbdSMatthew G Knepley include petsc.h90 in your code. 44613813dfbdSMatthew G Knepley 44623813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44633813dfbdSMatthew G Knepley 4464db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4465552f7358SJed Brown @*/ 4466552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4467552f7358SJed Brown { 4468552f7358SJed Brown PetscFunctionBegin; 4469552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4470d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4471d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4472d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints,5); 44739566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4474d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4475552f7358SJed Brown PetscFunctionReturn(0); 4476552f7358SJed Brown } 4477552f7358SJed Brown 4478552f7358SJed Brown /*@C 4479552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4480552f7358SJed Brown 4481552f7358SJed Brown Not Collective 4482552f7358SJed Brown 4483552f7358SJed Brown Input Parameters: 4484552f7358SJed Brown + dm - The DMPlex object 4485552f7358SJed Brown . numPoints - The number of input points for the meet 4486552f7358SJed Brown - points - The input points 4487552f7358SJed Brown 4488552f7358SJed Brown Output Parameters: 4489552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4490552f7358SJed Brown - coveredPoints - The points in the meet 4491552f7358SJed Brown 4492552f7358SJed Brown Level: intermediate 4493552f7358SJed Brown 44943813dfbdSMatthew G Knepley Fortran Notes: 44953813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44963813dfbdSMatthew G Knepley include petsc.h90 in your code. 44973813dfbdSMatthew G Knepley 44983813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44993813dfbdSMatthew G Knepley 4500db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4501552f7358SJed Brown @*/ 4502552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4503552f7358SJed Brown { 4504552f7358SJed Brown PetscInt *offsets, **closures; 4505552f7358SJed Brown PetscInt *meet[2]; 4506552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 450724c766afSToby Isaac PetscInt p, h, c, m, mc; 4508552f7358SJed Brown 4509552f7358SJed Brown PetscFunctionBegin; 4510552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4511dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4512dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveredPoints, 4); 4513064a246eSJacob Faibussowitsch PetscValidPointer(coveredPoints, 5); 4514552f7358SJed Brown 45159566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 45169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 45179566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 45186302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 451924c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 45209566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 45219566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4522552f7358SJed Brown 4523552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4524552f7358SJed Brown PetscInt closureSize; 4525552f7358SJed Brown 45269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 45270d644c17SKarl Rupp 4528552f7358SJed Brown offsets[p*(height+2)+0] = 0; 4529552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4530552f7358SJed Brown PetscInt pStart, pEnd, i; 4531552f7358SJed Brown 45329566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4533552f7358SJed Brown for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4534552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4535552f7358SJed Brown offsets[p*(height+2)+h+1] = i; 4536552f7358SJed Brown break; 4537552f7358SJed Brown } 4538552f7358SJed Brown } 4539552f7358SJed Brown if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4540552f7358SJed Brown } 454163a3b9bcSJacob 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); 4542552f7358SJed Brown } 4543552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4544552f7358SJed Brown PetscInt dof; 4545552f7358SJed Brown 4546552f7358SJed Brown /* Copy in cone of first point */ 4547552f7358SJed Brown dof = offsets[h+1] - offsets[h]; 4548552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4549552f7358SJed Brown meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4550552f7358SJed Brown } 4551552f7358SJed Brown /* Check each successive cone */ 4552552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4553552f7358SJed Brown PetscInt newMeetSize = 0; 4554552f7358SJed Brown 4555552f7358SJed Brown dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4556552f7358SJed Brown for (c = 0; c < dof; ++c) { 4557552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4558552f7358SJed Brown 4559552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4560552f7358SJed Brown if (point == meet[i][m]) { 4561552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4562552f7358SJed Brown break; 4563552f7358SJed Brown } 4564552f7358SJed Brown } 4565552f7358SJed Brown } 4566552f7358SJed Brown meetSize = newMeetSize; 4567552f7358SJed Brown i = 1-i; 4568552f7358SJed Brown } 4569552f7358SJed Brown if (meetSize) break; 4570552f7358SJed Brown } 4571552f7358SJed Brown *numCoveredPoints = meetSize; 4572552f7358SJed Brown *coveredPoints = meet[i]; 4573552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 45749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 4575552f7358SJed Brown } 45769566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 45779566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 45786302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1-i])); 4579552f7358SJed Brown PetscFunctionReturn(0); 4580552f7358SJed Brown } 4581552f7358SJed Brown 45824e3744c5SMatthew G. Knepley /*@C 45834e3744c5SMatthew G. Knepley DMPlexEqual - Determine if two DMs have the same topology 45844e3744c5SMatthew G. Knepley 45854e3744c5SMatthew G. Knepley Not Collective 45864e3744c5SMatthew G. Knepley 45874e3744c5SMatthew G. Knepley Input Parameters: 45884e3744c5SMatthew G. Knepley + dmA - A DMPlex object 45894e3744c5SMatthew G. Knepley - dmB - A DMPlex object 45904e3744c5SMatthew G. Knepley 45914e3744c5SMatthew G. Knepley Output Parameters: 45924e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical 45934e3744c5SMatthew G. Knepley 45944e3744c5SMatthew G. Knepley Level: intermediate 45954e3744c5SMatthew G. Knepley 45964e3744c5SMatthew G. Knepley Notes: 45974e3744c5SMatthew G. Knepley We are not solving graph isomorphism, so we do not permutation. 45984e3744c5SMatthew G. Knepley 4599db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 46004e3744c5SMatthew G. Knepley @*/ 46014e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 46024e3744c5SMatthew G. Knepley { 46034e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 46044e3744c5SMatthew G. Knepley 46054e3744c5SMatthew G. Knepley PetscFunctionBegin; 46064e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 46074e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4608dadcf809SJacob Faibussowitsch PetscValidBoolPointer(equal, 3); 46094e3744c5SMatthew G. Knepley 46104e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 46119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 46129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 46134e3744c5SMatthew G. Knepley if (depth != depthB) PetscFunctionReturn(0); 46149566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 46159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 46164e3744c5SMatthew G. Knepley if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 46174e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 46184e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 46194e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 46204e3744c5SMatthew G. Knepley 46219566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 46229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 46239566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 46249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 46259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 46269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 46274e3744c5SMatthew G. Knepley if (coneSize != coneSizeB) PetscFunctionReturn(0); 46284e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 46294e3744c5SMatthew G. Knepley if (cone[c] != coneB[c]) PetscFunctionReturn(0); 46304e3744c5SMatthew G. Knepley if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 46314e3744c5SMatthew G. Knepley } 46329566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 46339566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 46349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 46359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 46364e3744c5SMatthew G. Knepley if (supportSize != supportSizeB) PetscFunctionReturn(0); 46374e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 46384e3744c5SMatthew G. Knepley if (support[s] != supportB[s]) PetscFunctionReturn(0); 46394e3744c5SMatthew G. Knepley } 46404e3744c5SMatthew G. Knepley } 46414e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 46424e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 46434e3744c5SMatthew G. Knepley } 46444e3744c5SMatthew G. Knepley 46457cd05799SMatthew G. Knepley /*@C 46467cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 46477cd05799SMatthew G. Knepley 46487cd05799SMatthew G. Knepley Not Collective 46497cd05799SMatthew G. Knepley 46507cd05799SMatthew G. Knepley Input Parameters: 46517cd05799SMatthew G. Knepley + dm - The DMPlex 46527cd05799SMatthew G. Knepley . cellDim - The cell dimension 46537cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 46547cd05799SMatthew G. Knepley 46557cd05799SMatthew G. Knepley Output Parameters: 46567cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 46577cd05799SMatthew G. Knepley 46587cd05799SMatthew G. Knepley Level: developer 46597cd05799SMatthew G. Knepley 46607cd05799SMatthew G. Knepley Notes: 46617cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 46627cd05799SMatthew G. Knepley 4663db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 46647cd05799SMatthew G. Knepley @*/ 466518ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4666a6dfd86eSKarl Rupp { 466782f516ccSBarry Smith MPI_Comm comm; 4668552f7358SJed Brown 4669552f7358SJed Brown PetscFunctionBegin; 46709566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm,&comm)); 4671dadcf809SJacob Faibussowitsch PetscValidIntPointer(numFaceVertices,4); 4672552f7358SJed Brown switch (cellDim) { 4673552f7358SJed Brown case 0: 4674552f7358SJed Brown *numFaceVertices = 0; 4675552f7358SJed Brown break; 4676552f7358SJed Brown case 1: 4677552f7358SJed Brown *numFaceVertices = 1; 4678552f7358SJed Brown break; 4679552f7358SJed Brown case 2: 4680552f7358SJed Brown switch (numCorners) { 468119436ca2SJed Brown case 3: /* triangle */ 468219436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4683552f7358SJed Brown break; 468419436ca2SJed Brown case 4: /* quadrilateral */ 468519436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4686552f7358SJed Brown break; 468719436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 468819436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4689552f7358SJed Brown break; 469019436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 469119436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4692552f7358SJed Brown break; 4693552f7358SJed Brown default: 469463a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4695552f7358SJed Brown } 4696552f7358SJed Brown break; 4697552f7358SJed Brown case 3: 4698552f7358SJed Brown switch (numCorners) { 469919436ca2SJed Brown case 4: /* tetradehdron */ 470019436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 4701552f7358SJed Brown break; 470219436ca2SJed Brown case 6: /* tet cohesive cells */ 470319436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4704552f7358SJed Brown break; 470519436ca2SJed Brown case 8: /* hexahedron */ 470619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4707552f7358SJed Brown break; 470819436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 470919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4710552f7358SJed Brown break; 471119436ca2SJed Brown case 10: /* quadratic tetrahedron */ 471219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4713552f7358SJed Brown break; 471419436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 471519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4716552f7358SJed Brown break; 471719436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 471819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4719552f7358SJed Brown break; 472019436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 472119436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 4722552f7358SJed Brown break; 4723552f7358SJed Brown default: 472463a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 4725552f7358SJed Brown } 4726552f7358SJed Brown break; 4727552f7358SJed Brown default: 472863a3b9bcSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 4729552f7358SJed Brown } 4730552f7358SJed Brown PetscFunctionReturn(0); 4731552f7358SJed Brown } 4732552f7358SJed Brown 4733552f7358SJed Brown /*@ 4734aa50250dSMatthew G. Knepley DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4735552f7358SJed Brown 4736552f7358SJed Brown Not Collective 4737552f7358SJed Brown 4738aa50250dSMatthew G. Knepley Input Parameter: 4739552f7358SJed Brown . dm - The DMPlex object 4740552f7358SJed Brown 4741aa50250dSMatthew G. Knepley Output Parameter: 4742aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth 4743552f7358SJed Brown 4744552f7358SJed Brown Level: developer 4745552f7358SJed Brown 4746db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 4747aa50250dSMatthew G. Knepley @*/ 4748aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4749aa50250dSMatthew G. Knepley { 4750aa50250dSMatthew G. Knepley PetscFunctionBegin; 4751aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4752aa50250dSMatthew G. Knepley PetscValidPointer(depthLabel, 2); 4753c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 4754aa50250dSMatthew G. Knepley PetscFunctionReturn(0); 4755aa50250dSMatthew G. Knepley } 4756aa50250dSMatthew G. Knepley 4757aa50250dSMatthew G. Knepley /*@ 4758aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 4759aa50250dSMatthew G. Knepley 4760aa50250dSMatthew G. Knepley Not Collective 4761aa50250dSMatthew G. Knepley 4762aa50250dSMatthew G. Knepley Input Parameter: 4763aa50250dSMatthew G. Knepley . dm - The DMPlex object 4764aa50250dSMatthew G. Knepley 4765aa50250dSMatthew G. Knepley Output Parameter: 4766aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 4767aa50250dSMatthew G. Knepley 4768aa50250dSMatthew G. Knepley Level: developer 4769552f7358SJed Brown 4770b1bb481bSMatthew Knepley Notes: 4771b1bb481bSMatthew Knepley This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4772dc287ab2SVaclav Hapla The point depth is described more in detail in DMPlexGetDepthStratum(). 4773dc287ab2SVaclav Hapla An empty mesh gives -1. 4774b1bb481bSMatthew Knepley 4775db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 4776552f7358SJed Brown @*/ 4777552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4778552f7358SJed Brown { 4779aa50250dSMatthew G. Knepley DMLabel label; 4780aa50250dSMatthew G. Knepley PetscInt d = 0; 4781552f7358SJed Brown 4782552f7358SJed Brown PetscFunctionBegin; 4783552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4784dadcf809SJacob Faibussowitsch PetscValidIntPointer(depth, 2); 47859566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 47869566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 4787552f7358SJed Brown *depth = d-1; 4788552f7358SJed Brown PetscFunctionReturn(0); 4789552f7358SJed Brown } 4790552f7358SJed Brown 4791552f7358SJed Brown /*@ 4792552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4793552f7358SJed Brown 4794552f7358SJed Brown Not Collective 4795552f7358SJed Brown 4796552f7358SJed Brown Input Parameters: 4797552f7358SJed Brown + dm - The DMPlex object 4798570fa34dSVaclav Hapla - depth - The requested depth 4799552f7358SJed Brown 4800552f7358SJed Brown Output Parameters: 4801552f7358SJed Brown + start - The first point at this depth 4802552f7358SJed Brown - end - One beyond the last point at this depth 4803552f7358SJed Brown 4804647867b2SJed Brown Notes: 4805647867b2SJed Brown Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4806647867b2SJed Brown often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4807647867b2SJed Brown higher dimension, e.g., "edges". 4808647867b2SJed Brown 4809552f7358SJed Brown Level: developer 4810552f7358SJed Brown 4811db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 4812552f7358SJed Brown @*/ 4813570fa34dSVaclav Hapla PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 48140adebc6cSBarry Smith { 4815aa50250dSMatthew G. Knepley DMLabel label; 481663d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 4817552f7358SJed Brown 4818552f7358SJed Brown PetscFunctionBegin; 4819552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4820dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4821dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48229566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 48230d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4824570fa34dSVaclav Hapla if (depth < 0) { 482563d1a920SMatthew G. Knepley if (start) *start = pStart; 482663d1a920SMatthew G. Knepley if (end) *end = pEnd; 482763d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4828552f7358SJed Brown } 48299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 483028b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4831570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 4832552f7358SJed Brown PetscFunctionReturn(0); 4833552f7358SJed Brown } 4834552f7358SJed Brown 4835552f7358SJed Brown /*@ 4836552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4837552f7358SJed Brown 4838552f7358SJed Brown Not Collective 4839552f7358SJed Brown 4840552f7358SJed Brown Input Parameters: 4841552f7358SJed Brown + dm - The DMPlex object 4842570fa34dSVaclav Hapla - height - The requested height 4843552f7358SJed Brown 4844552f7358SJed Brown Output Parameters: 4845552f7358SJed Brown + start - The first point at this height 4846552f7358SJed Brown - end - One beyond the last point at this height 4847552f7358SJed Brown 4848647867b2SJed Brown Notes: 4849647867b2SJed Brown Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4850647867b2SJed Brown points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4851647867b2SJed Brown stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4852647867b2SJed Brown 4853552f7358SJed Brown Level: developer 4854552f7358SJed Brown 4855db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4856552f7358SJed Brown @*/ 4857570fa34dSVaclav Hapla PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 48580adebc6cSBarry Smith { 4859aa50250dSMatthew G. Knepley DMLabel label; 486063d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 4861552f7358SJed Brown 4862552f7358SJed Brown PetscFunctionBegin; 4863552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4864dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4865dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48669566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 48670d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 4868570fa34dSVaclav Hapla if (height < 0) { 486963d1a920SMatthew G. Knepley if (start) *start = pStart; 487063d1a920SMatthew G. Knepley if (end) *end = pEnd; 487163d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4872552f7358SJed Brown } 48739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 487428b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 48759566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 4876570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth-1-height, start, end)); 4877552f7358SJed Brown PetscFunctionReturn(0); 4878552f7358SJed Brown } 4879552f7358SJed Brown 4880ba2698f1SMatthew G. Knepley /*@ 4881ba2698f1SMatthew G. Knepley DMPlexGetPointDepth - Get the depth of a given point 4882ba2698f1SMatthew G. Knepley 4883ba2698f1SMatthew G. Knepley Not Collective 4884ba2698f1SMatthew G. Knepley 4885d8d19677SJose E. Roman Input Parameters: 4886ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4887ba2698f1SMatthew G. Knepley - point - The point 4888ba2698f1SMatthew G. Knepley 4889ba2698f1SMatthew G. Knepley Output Parameter: 4890ba2698f1SMatthew G. Knepley . depth - The depth of the point 4891ba2698f1SMatthew G. Knepley 4892ba2698f1SMatthew G. Knepley Level: intermediate 4893ba2698f1SMatthew G. Knepley 4894db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 4895ba2698f1SMatthew G. Knepley @*/ 4896ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4897ba2698f1SMatthew G. Knepley { 4898ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4899ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 490040a2aa30SMatthew G. Knepley PetscValidIntPointer(depth, 3); 49019566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 4902ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4903ba2698f1SMatthew G. Knepley } 4904ba2698f1SMatthew G. Knepley 4905ba2698f1SMatthew G. Knepley /*@ 49060c0a32dcSVaclav Hapla DMPlexGetPointHeight - Get the height of a given point 49070c0a32dcSVaclav Hapla 49080c0a32dcSVaclav Hapla Not Collective 49090c0a32dcSVaclav Hapla 4910d8d19677SJose E. Roman Input Parameters: 49110c0a32dcSVaclav Hapla + dm - The DMPlex object 49120c0a32dcSVaclav Hapla - point - The point 49130c0a32dcSVaclav Hapla 49140c0a32dcSVaclav Hapla Output Parameter: 49150c0a32dcSVaclav Hapla . height - The height of the point 49160c0a32dcSVaclav Hapla 49170c0a32dcSVaclav Hapla Level: intermediate 49180c0a32dcSVaclav Hapla 4919db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 49200c0a32dcSVaclav Hapla @*/ 49210c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 49220c0a32dcSVaclav Hapla { 49230c0a32dcSVaclav Hapla PetscInt n, pDepth; 49240c0a32dcSVaclav Hapla 49250c0a32dcSVaclav Hapla PetscFunctionBegin; 49260c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49270c0a32dcSVaclav Hapla PetscValidIntPointer(height, 3); 49289566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 49299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 49300c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 49310c0a32dcSVaclav Hapla PetscFunctionReturn(0); 49320c0a32dcSVaclav Hapla } 49330c0a32dcSVaclav Hapla 49340c0a32dcSVaclav Hapla /*@ 4935ba2698f1SMatthew G. Knepley DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4936ba2698f1SMatthew G. Knepley 4937ba2698f1SMatthew G. Knepley Not Collective 4938ba2698f1SMatthew G. Knepley 4939ba2698f1SMatthew G. Knepley Input Parameter: 4940ba2698f1SMatthew G. Knepley . dm - The DMPlex object 4941ba2698f1SMatthew G. Knepley 4942ba2698f1SMatthew G. Knepley Output Parameter: 4943ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type 4944ba2698f1SMatthew G. Knepley 4945412e9a14SMatthew G. Knepley Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4946412e9a14SMatthew G. Knepley DMCreateLabel(dm, "celltype") beforehand. 4947412e9a14SMatthew G. Knepley 4948ba2698f1SMatthew G. Knepley Level: developer 4949ba2698f1SMatthew G. Knepley 4950db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 4951ba2698f1SMatthew G. Knepley @*/ 4952ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4953ba2698f1SMatthew G. Knepley { 4954ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4955ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4956ba2698f1SMatthew G. Knepley PetscValidPointer(celltypeLabel, 2); 49579566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 4958ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 4959ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4960ba2698f1SMatthew G. Knepley } 4961ba2698f1SMatthew G. Knepley 4962ba2698f1SMatthew G. Knepley /*@ 4963ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 4964ba2698f1SMatthew G. Knepley 4965ba2698f1SMatthew G. Knepley Not Collective 4966ba2698f1SMatthew G. Knepley 4967d8d19677SJose E. Roman Input Parameters: 4968ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4969ba2698f1SMatthew G. Knepley - cell - The cell 4970ba2698f1SMatthew G. Knepley 4971ba2698f1SMatthew G. Knepley Output Parameter: 4972ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 4973ba2698f1SMatthew G. Knepley 4974ba2698f1SMatthew G. Knepley Level: intermediate 4975ba2698f1SMatthew G. Knepley 4976db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 4977ba2698f1SMatthew G. Knepley @*/ 4978ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4979ba2698f1SMatthew G. Knepley { 4980ba2698f1SMatthew G. Knepley DMLabel label; 4981ba2698f1SMatthew G. Knepley PetscInt ct; 4982ba2698f1SMatthew G. Knepley 4983ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4984ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4985ba2698f1SMatthew G. Knepley PetscValidPointer(celltype, 3); 49869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 49879566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 498863a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 4989ba2698f1SMatthew G. Knepley *celltype = (DMPolytopeType) ct; 4990ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4991ba2698f1SMatthew G. Knepley } 4992ba2698f1SMatthew G. Knepley 4993412e9a14SMatthew G. Knepley /*@ 4994412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 4995412e9a14SMatthew G. Knepley 4996412e9a14SMatthew G. Knepley Not Collective 4997412e9a14SMatthew G. Knepley 4998412e9a14SMatthew G. Knepley Input Parameters: 4999412e9a14SMatthew G. Knepley + dm - The DMPlex object 5000412e9a14SMatthew G. Knepley . cell - The cell 5001412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5002412e9a14SMatthew G. Knepley 5003412e9a14SMatthew G. Knepley Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 5004412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5005412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5006412e9a14SMatthew G. Knepley DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 5007412e9a14SMatthew G. Knepley 5008412e9a14SMatthew G. Knepley Level: advanced 5009412e9a14SMatthew G. Knepley 5010db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5011412e9a14SMatthew G. Knepley @*/ 5012412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5013412e9a14SMatthew G. Knepley { 5014412e9a14SMatthew G. Knepley DMLabel label; 5015412e9a14SMatthew G. Knepley 5016412e9a14SMatthew G. Knepley PetscFunctionBegin; 5017412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 50199566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 5020412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 5021412e9a14SMatthew G. Knepley } 5022412e9a14SMatthew G. Knepley 50230adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 50240adebc6cSBarry Smith { 5025efe440bfSMatthew G. Knepley PetscSection section, s; 5026efe440bfSMatthew G. Knepley Mat m; 50273e922f36SToby Isaac PetscInt maxHeight; 5028552f7358SJed Brown 5029552f7358SJed Brown PetscFunctionBegin; 50309566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 50319566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 50329566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 50339566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 50349566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 50359566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 50369566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 50379566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 50389566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 50399566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 50409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 50418f4c458bSMatthew G. Knepley 50429566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 50439566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5044552f7358SJed Brown PetscFunctionReturn(0); 5045552f7358SJed Brown } 5046552f7358SJed Brown 5047f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5048f19dbd58SToby Isaac { 5049f19dbd58SToby Isaac Vec coordsLocal; 5050f19dbd58SToby Isaac DM coordsDM; 5051f19dbd58SToby Isaac 5052f19dbd58SToby Isaac PetscFunctionBegin; 5053f19dbd58SToby Isaac *field = NULL; 50549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm,&coordsLocal)); 50559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm,&coordsDM)); 5056f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 50579566063dSJacob Faibussowitsch PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5058f19dbd58SToby Isaac } 5059f19dbd58SToby Isaac PetscFunctionReturn(0); 5060f19dbd58SToby Isaac } 5061f19dbd58SToby Isaac 50627cd05799SMatthew G. Knepley /*@C 50637cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 50647cd05799SMatthew G. Knepley 50657cd05799SMatthew G. Knepley Not Collective 50667cd05799SMatthew G. Knepley 50677cd05799SMatthew G. Knepley Input Parameters: 50687cd05799SMatthew G. Knepley . dm - The DMPlex object 50697cd05799SMatthew G. Knepley 50707cd05799SMatthew G. Knepley Output Parameter: 50717cd05799SMatthew G. Knepley . section - The PetscSection object 50727cd05799SMatthew G. Knepley 50737cd05799SMatthew G. Knepley Level: developer 50747cd05799SMatthew G. Knepley 5075db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()` 50767cd05799SMatthew G. Knepley @*/ 50770adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 50780adebc6cSBarry Smith { 5079552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5080552f7358SJed Brown 5081552f7358SJed Brown PetscFunctionBegin; 5082552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5083552f7358SJed Brown if (section) *section = mesh->coneSection; 5084552f7358SJed Brown PetscFunctionReturn(0); 5085552f7358SJed Brown } 5086552f7358SJed Brown 50877cd05799SMatthew G. Knepley /*@C 50887cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 50897cd05799SMatthew G. Knepley 50907cd05799SMatthew G. Knepley Not Collective 50917cd05799SMatthew G. Knepley 50927cd05799SMatthew G. Knepley Input Parameters: 50937cd05799SMatthew G. Knepley . dm - The DMPlex object 50947cd05799SMatthew G. Knepley 50957cd05799SMatthew G. Knepley Output Parameter: 50967cd05799SMatthew G. Knepley . section - The PetscSection object 50977cd05799SMatthew G. Knepley 50987cd05799SMatthew G. Knepley Level: developer 50997cd05799SMatthew G. Knepley 5100db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 51017cd05799SMatthew G. Knepley @*/ 51028cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 51038cb4d582SMatthew G. Knepley { 51048cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 51058cb4d582SMatthew G. Knepley 51068cb4d582SMatthew G. Knepley PetscFunctionBegin; 51078cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51088cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 51098cb4d582SMatthew G. Knepley PetscFunctionReturn(0); 51108cb4d582SMatthew G. Knepley } 51118cb4d582SMatthew G. Knepley 51127cd05799SMatthew G. Knepley /*@C 51137cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 51147cd05799SMatthew G. Knepley 51157cd05799SMatthew G. Knepley Not Collective 51167cd05799SMatthew G. Knepley 51177cd05799SMatthew G. Knepley Input Parameters: 51187cd05799SMatthew G. Knepley . dm - The DMPlex object 51197cd05799SMatthew G. Knepley 51207cd05799SMatthew G. Knepley Output Parameter: 51217cd05799SMatthew G. Knepley . cones - The cone for each point 51227cd05799SMatthew G. Knepley 51237cd05799SMatthew G. Knepley Level: developer 51247cd05799SMatthew G. Knepley 5125db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()` 51267cd05799SMatthew G. Knepley @*/ 5127a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5128a6dfd86eSKarl Rupp { 5129552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5130552f7358SJed Brown 5131552f7358SJed Brown PetscFunctionBegin; 5132552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5133552f7358SJed Brown if (cones) *cones = mesh->cones; 5134552f7358SJed Brown PetscFunctionReturn(0); 5135552f7358SJed Brown } 5136552f7358SJed Brown 51377cd05799SMatthew G. Knepley /*@C 51387cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 51397cd05799SMatthew G. Knepley 51407cd05799SMatthew G. Knepley Not Collective 51417cd05799SMatthew G. Knepley 51427cd05799SMatthew G. Knepley Input Parameters: 51437cd05799SMatthew G. Knepley . dm - The DMPlex object 51447cd05799SMatthew G. Knepley 51457cd05799SMatthew G. Knepley Output Parameter: 5146b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 51477cd05799SMatthew G. Knepley 51487cd05799SMatthew G. Knepley Level: developer 51497cd05799SMatthew G. Knepley 5150b5a892a1SMatthew G. Knepley Notes: 5151b5a892a1SMatthew G. Knepley The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5152b5a892a1SMatthew G. Knepley 5153b5a892a1SMatthew G. Knepley The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5154b5a892a1SMatthew G. Knepley 5155db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()` 51567cd05799SMatthew G. Knepley @*/ 5157a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5158a6dfd86eSKarl Rupp { 5159552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5160552f7358SJed Brown 5161552f7358SJed Brown PetscFunctionBegin; 5162552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5163552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5164552f7358SJed Brown PetscFunctionReturn(0); 5165552f7358SJed Brown } 5166552f7358SJed Brown 5167552f7358SJed Brown /******************************** FEM Support **********************************/ 5168552f7358SJed Brown 51699e8305c2SJed Brown /* 51709e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 51719e8305c2SJed Brown representing a line in the section. 51729e8305c2SJed Brown */ 51739e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 51749e8305c2SJed Brown { 51759e8305c2SJed Brown PetscFunctionBeginHot; 51769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5177a433471fSStefano Zampini if (line < 0) { 5178a433471fSStefano Zampini *k = 0; 5179a433471fSStefano Zampini *Nc = 0; 5180a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 51819e8305c2SJed Brown *k = 1; 51829e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 51839e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 51849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 51859e8305c2SJed Brown *k = *k / *Nc + 1; 51869e8305c2SJed Brown } 51879e8305c2SJed Brown PetscFunctionReturn(0); 51889e8305c2SJed Brown } 51899e8305c2SJed Brown 5190a4355906SMatthew Knepley /*@ 5191bc1eb3faSJed Brown 5192bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5193bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 51941bb6d2a8SBarry Smith section provided (or the section of the DM). 5195a4355906SMatthew Knepley 5196a4355906SMatthew Knepley Input Parameters: 5197a4355906SMatthew Knepley + dm - The DM 5198a4355906SMatthew Knepley . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5199a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section 5200a4355906SMatthew Knepley 5201a4355906SMatthew Knepley Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5202a4355906SMatthew Knepley degree of the basis. 5203a4355906SMatthew Knepley 5204bc1eb3faSJed Brown Example: 5205bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5206bc1eb3faSJed Brown .vb 5207bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5208bc1eb3faSJed Brown 5209bc1eb3faSJed Brown v4 -- e6 -- v3 5210bc1eb3faSJed Brown | | 5211bc1eb3faSJed Brown e7 c0 e8 5212bc1eb3faSJed Brown | | 5213bc1eb3faSJed Brown v1 -- e5 -- v2 5214bc1eb3faSJed Brown .ve 5215bc1eb3faSJed Brown 5216bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5217bc1eb3faSJed Brown dofs in the order of points, e.g., 5218bc1eb3faSJed Brown .vb 5219bc1eb3faSJed Brown c0 -> [0,1,2,3] 5220bc1eb3faSJed Brown v1 -> [4] 5221bc1eb3faSJed Brown ... 5222bc1eb3faSJed Brown e5 -> [8, 9] 5223bc1eb3faSJed Brown .ve 5224bc1eb3faSJed Brown 5225bc1eb3faSJed Brown which corresponds to the dofs 5226bc1eb3faSJed Brown .vb 5227bc1eb3faSJed Brown 6 10 11 7 5228bc1eb3faSJed Brown 13 2 3 15 5229bc1eb3faSJed Brown 12 0 1 14 5230bc1eb3faSJed Brown 4 8 9 5 5231bc1eb3faSJed Brown .ve 5232bc1eb3faSJed Brown 5233bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5234bc1eb3faSJed Brown .vb 5235bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5236bc1eb3faSJed Brown .ve 5237bc1eb3faSJed Brown 5238bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5239bc1eb3faSJed Brown .vb 5240bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5241bc1eb3faSJed Brown .ve 5242bc1eb3faSJed Brown 5243a4355906SMatthew Knepley Level: developer 5244a4355906SMatthew Knepley 5245db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5246a4355906SMatthew Knepley @*/ 5247bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 52483194fc30SMatthew G. Knepley { 52497391a63aSMatthew G. Knepley DMLabel label; 5250bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 52519e8305c2SJed Brown PetscBool vertexchart; 52523194fc30SMatthew G. Knepley 52533194fc30SMatthew G. Knepley PetscFunctionBegin; 52549566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5255a433471fSStefano Zampini if (dim < 1) PetscFunctionReturn(0); 5256a433471fSStefano Zampini if (point < 0) { 5257a433471fSStefano Zampini PetscInt sStart,sEnd; 5258a433471fSStefano Zampini 52599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5260a433471fSStefano Zampini point = sEnd-sStart ? sStart : point; 5261a433471fSStefano Zampini } 52629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52639566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 52649566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 52657391a63aSMatthew G. Knepley if (depth == 1) {eStart = point;} 52667391a63aSMatthew G. Knepley else if (depth == dim) { 52677391a63aSMatthew G. Knepley const PetscInt *cone; 52687391a63aSMatthew G. Knepley 52699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5270d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5271d4e6627bSStefano Zampini else if (dim == 3) { 5272d4e6627bSStefano Zampini const PetscInt *cone2; 52739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5274d4e6627bSStefano Zampini eStart = cone2[0]; 527563a3b9bcSJacob 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); 527663a3b9bcSJacob 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); 52779e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 52789e8305c2SJed Brown PetscInt pStart,pEnd,cStart,cEnd; 52799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd)); 52809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&cStart,&cEnd)); 5281796d0a68SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5282796d0a68SJed Brown else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5283796d0a68SJed Brown else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 52849e8305c2SJed Brown } 52859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5286bb197d40SJed Brown for (PetscInt d=1; d<=dim; d++) { 5287bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5288bb197d40SJed Brown PetscInt *perm; 5289bb197d40SJed Brown 52903194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 52919566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5292bb197d40SJed Brown size += PetscPowInt(k+1, d)*Nc; 52933194fc30SMatthew G. Knepley } 52949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 52953194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5296bb197d40SJed Brown switch (d) { 5297babf31e0SJed Brown case 1: 52989566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5299babf31e0SJed Brown /* 5300babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5301babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5302babf31e0SJed Brown */ 5303babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5304babf31e0SJed Brown for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5305babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5306babf31e0SJed Brown foffset = offset; 5307babf31e0SJed Brown break; 530889eabcffSMatthew G. Knepley case 2: 53093194fc30SMatthew 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} */ 53109566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 53113194fc30SMatthew G. Knepley /* The SEM order is 53123194fc30SMatthew G. Knepley 53133194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 531489eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 53153194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 53163194fc30SMatthew G. Knepley */ 53173194fc30SMatthew G. Knepley { 53183194fc30SMatthew G. Knepley const PetscInt of = 0; 53193194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k-1); 53203194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k-1); 53213194fc30SMatthew G. Knepley const PetscInt oet = oer + (k-1); 53223194fc30SMatthew G. Knepley const PetscInt oel = oet + (k-1); 53233194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k-1); 53243194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 53253194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 53263194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 53273194fc30SMatthew G. Knepley PetscInt o; 53283194fc30SMatthew G. Knepley 53293194fc30SMatthew G. Knepley /* bottom */ 53303194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 53313194fc30SMatthew G. Knepley for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53323194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 53333194fc30SMatthew G. Knepley /* middle */ 53343194fc30SMatthew G. Knepley for (i = 0; i < k-1; ++i) { 53353194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 53363194fc30SMatthew 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; 53373194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 53383194fc30SMatthew G. Knepley } 53393194fc30SMatthew G. Knepley /* top */ 53403194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 53413194fc30SMatthew G. Knepley for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53423194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 53433194fc30SMatthew G. Knepley foffset = offset; 53443194fc30SMatthew G. Knepley } 534589eabcffSMatthew G. Knepley break; 534689eabcffSMatthew G. Knepley case 3: 534789eabcffSMatthew G. Knepley /* The original hex closure is 534889eabcffSMatthew G. Knepley 534989eabcffSMatthew G. Knepley {c, 535089eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 535189eabcffSMatthew 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, 535289eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 535389eabcffSMatthew G. Knepley */ 53549566063dSJacob Faibussowitsch PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 535589eabcffSMatthew G. Knepley /* The SEM order is 535689eabcffSMatthew G. Knepley Bottom Slice 535789eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 535889eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 535989eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 536089eabcffSMatthew G. Knepley 536189eabcffSMatthew G. Knepley Middle Slice (j) 536289eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 536389eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 536489eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 536589eabcffSMatthew G. Knepley 536689eabcffSMatthew G. Knepley Top Slice 536789eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 536889eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 536989eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 537089eabcffSMatthew G. Knepley */ 537189eabcffSMatthew G. Knepley { 537289eabcffSMatthew G. Knepley const PetscInt oc = 0; 537389eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 537489eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k-1); 537589eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k-1); 537689eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k-1); 537789eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k-1); 537889eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k-1); 537989eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k-1); 538089eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k-1); 538189eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k-1); 538289eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k-1); 538389eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k-1); 538489eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k-1); 538589eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k-1); 538689eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k-1); 538789eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k-1); 538889eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k-1); 538989eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k-1); 539089eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k-1); 539189eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k-1); 539289eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 539389eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 539489eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 539589eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 539689eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 539789eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 539889eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 539989eabcffSMatthew G. Knepley PetscInt o, n; 540089eabcffSMatthew G. Knepley 540189eabcffSMatthew G. Knepley /* Bottom Slice */ 540289eabcffSMatthew G. Knepley /* bottom */ 540389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 540489eabcffSMatthew G. Knepley for (o = oetf-1; o >= oebf; --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] = ovbrf*Nc + c + foffset; 540689eabcffSMatthew G. Knepley /* middle */ 540789eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 540889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5409316b7f87SMax 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;} 541089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 54113194fc30SMatthew G. Knepley } 541289eabcffSMatthew G. Knepley /* top */ 541389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 541489eabcffSMatthew G. Knepley for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 541589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 541689eabcffSMatthew G. Knepley 541789eabcffSMatthew G. Knepley /* Middle Slice */ 541889eabcffSMatthew G. Knepley for (j = 0; j < k-1; ++j) { 541989eabcffSMatthew G. Knepley /* bottom */ 542089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 542189eabcffSMatthew 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; 542289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 542389eabcffSMatthew G. Knepley /* middle */ 542489eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 542589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 542689eabcffSMatthew 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; 542789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 542889eabcffSMatthew G. Knepley } 542989eabcffSMatthew G. Knepley /* top */ 543089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 543189eabcffSMatthew 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; 543289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 543389eabcffSMatthew G. Knepley } 543489eabcffSMatthew G. Knepley 543589eabcffSMatthew G. Knepley /* Top Slice */ 543689eabcffSMatthew G. Knepley /* bottom */ 543789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 543889eabcffSMatthew G. Knepley for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 543989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 544089eabcffSMatthew G. Knepley /* middle */ 544189eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 544289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 544389eabcffSMatthew 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; 544489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 544589eabcffSMatthew G. Knepley } 544689eabcffSMatthew G. Knepley /* top */ 544789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 544889eabcffSMatthew G. Knepley for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 544989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 545089eabcffSMatthew G. Knepley 545189eabcffSMatthew G. Knepley foffset = offset; 545289eabcffSMatthew G. Knepley } 545389eabcffSMatthew G. Knepley break; 545463a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 545589eabcffSMatthew G. Knepley } 545689eabcffSMatthew G. Knepley } 545763a3b9bcSJacob Faibussowitsch PetscCheck(offset == size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 54583194fc30SMatthew G. Knepley /* Check permutation */ 54593194fc30SMatthew G. Knepley { 54603194fc30SMatthew G. Knepley PetscInt *check; 54613194fc30SMatthew G. Knepley 54629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 54631dca8a05SBarry Smith for (i = 0; i < size; ++i) { 54641dca8a05SBarry Smith check[i] = -1; 54651dca8a05SBarry 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]); 54661dca8a05SBarry Smith } 54673194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 54681dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 54699566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 54703194fc30SMatthew G. Knepley } 54719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm)); 5472a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5473a05c9aa3SJed Brown PetscInt *loc_perm; 54749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size*2, &loc_perm)); 5475a05c9aa3SJed Brown for (PetscInt i=0; i<size; i++) { 5476a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5477a05c9aa3SJed Brown loc_perm[size+i] = size + perm[i]; 5478a05c9aa3SJed Brown } 54799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm)); 5480a05c9aa3SJed Brown } 5481bb197d40SJed Brown } 54823194fc30SMatthew G. Knepley PetscFunctionReturn(0); 54833194fc30SMatthew G. Knepley } 54843194fc30SMatthew G. Knepley 5485e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5486e071409bSToby Isaac { 5487e071409bSToby Isaac PetscDS prob; 5488e071409bSToby Isaac PetscInt depth, Nf, h; 5489e071409bSToby Isaac DMLabel label; 5490e071409bSToby Isaac 5491e071409bSToby Isaac PetscFunctionBeginHot; 54929566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 5493e071409bSToby Isaac Nf = prob->Nf; 5494e071409bSToby Isaac label = dm->depthLabel; 5495e071409bSToby Isaac *dspace = NULL; 5496e071409bSToby Isaac if (field < Nf) { 5497e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5498e071409bSToby Isaac 5499e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5500e071409bSToby Isaac PetscDualSpace dsp; 5501e071409bSToby Isaac 55029566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp)); 55039566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label,&depth)); 55049566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label,point,&h)); 5505e071409bSToby Isaac h = depth - 1 - h; 5506e071409bSToby Isaac if (h) { 55079566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp,h,dspace)); 5508e071409bSToby Isaac } else { 5509e071409bSToby Isaac *dspace = dsp; 5510e071409bSToby Isaac } 5511e071409bSToby Isaac } 5512e071409bSToby Isaac } 5513e071409bSToby Isaac PetscFunctionReturn(0); 5514e071409bSToby Isaac } 5515e071409bSToby Isaac 55169fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5517a6dfd86eSKarl Rupp { 5518552f7358SJed Brown PetscScalar *array, *vArray; 5519d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 55201a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5521552f7358SJed Brown 55221b406b76SMatthew G. Knepley PetscFunctionBeginHot; 55239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 55249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 55259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 55269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 55273f7cbbe7SMatthew G. Knepley if (!values || !*values) { 55289df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55299df71ca4SMatthew G. Knepley PetscInt dof; 5530d9917b9dSMatthew G. Knepley 55319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55329df71ca4SMatthew G. Knepley size += dof; 55339df71ca4SMatthew G. Knepley } 55349df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55359df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55362a3aaacfSMatthew G. Knepley PetscInt dof; 55375a1bb5cfSMatthew G. Knepley 55385a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55405a1bb5cfSMatthew G. Knepley size += dof; 55415a1bb5cfSMatthew G. Knepley } 55423f7cbbe7SMatthew G. Knepley if (!values) { 55433f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 55443f7cbbe7SMatthew G. Knepley PetscFunctionReturn(0); 55453f7cbbe7SMatthew G. Knepley } 55469566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 5547982e9ed1SMatthew G. Knepley } else { 5548982e9ed1SMatthew G. Knepley array = *values; 5549982e9ed1SMatthew G. Knepley } 55509df71ca4SMatthew G. Knepley size = 0; 55519566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &vArray)); 55529df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55539df71ca4SMatthew G. Knepley PetscInt dof, off, d; 55549df71ca4SMatthew G. Knepley PetscScalar *varr; 5555d9917b9dSMatthew G. Knepley 55569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 55579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 55589df71ca4SMatthew G. Knepley varr = &vArray[off]; 55591a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55601a271a75SMatthew G. Knepley array[offset] = varr[d]; 55619df71ca4SMatthew G. Knepley } 55629df71ca4SMatthew G. Knepley size += dof; 55639df71ca4SMatthew G. Knepley } 55649df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55659df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55669df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 55675a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 55685a1bb5cfSMatthew G. Knepley PetscScalar *varr; 55695a1bb5cfSMatthew G. Knepley 557052ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 55729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 55735a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 55745a1bb5cfSMatthew G. Knepley if (o >= 0) { 55751a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55761a271a75SMatthew G. Knepley array[offset] = varr[d]; 55775a1bb5cfSMatthew G. Knepley } 55785a1bb5cfSMatthew G. Knepley } else { 55791a271a75SMatthew G. Knepley for (d = dof-1; d >= 0; --d, ++offset) { 55801a271a75SMatthew G. Knepley array[offset] = varr[d]; 55815a1bb5cfSMatthew G. Knepley } 55825a1bb5cfSMatthew G. Knepley } 55839df71ca4SMatthew G. Knepley size += dof; 55845a1bb5cfSMatthew G. Knepley } 55859566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &vArray)); 55869df71ca4SMatthew G. Knepley if (!*values) { 55875a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 55885a1bb5cfSMatthew G. Knepley *values = array; 55899df71ca4SMatthew G. Knepley } else { 559063a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 55918c312ff3SMatthew G. Knepley *csize = size; 55929df71ca4SMatthew G. Knepley } 55935a1bb5cfSMatthew G. Knepley PetscFunctionReturn(0); 55945a1bb5cfSMatthew G. Knepley } 5595d9917b9dSMatthew G. Knepley 559627f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 55979fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 559827f02ce8SMatthew G. Knepley { 559927f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 560027f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 560127f02ce8SMatthew G. Knepley 56029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 560327f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 560427f02ce8SMatthew G. Knepley const PetscInt r = points[p*2]; 560527f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 560627f02ce8SMatthew G. Knepley points[q*2] = r; 560727f02ce8SMatthew G. Knepley points[q*2+1] = points[p*2+1]; 560827f02ce8SMatthew G. Knepley ++q; 560927f02ce8SMatthew G. Knepley } 561027f02ce8SMatthew G. Knepley } 561127f02ce8SMatthew G. Knepley *numPoints = q; 561227f02ce8SMatthew G. Knepley return 0; 561327f02ce8SMatthew G. Knepley } 561427f02ce8SMatthew G. Knepley 561597529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 56161dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5617923c78e0SToby Isaac { 561827f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 5619923c78e0SToby Isaac PetscInt np, *pts = NULL; 5620923c78e0SToby Isaac 5621923c78e0SToby Isaac PetscFunctionBeginHot; 56229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints)); 562327f02ce8SMatthew G. Knepley if (*clPoints) { 5624923c78e0SToby Isaac PetscInt dof, off; 5625923c78e0SToby Isaac 56269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 56279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 56289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 5629923c78e0SToby Isaac np = dof/2; 5630923c78e0SToby Isaac pts = (PetscInt *) &cla[off]; 563127f02ce8SMatthew G. Knepley } else { 56329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts)); 56339566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 5634923c78e0SToby Isaac } 5635923c78e0SToby Isaac *numPoints = np; 5636923c78e0SToby Isaac *points = pts; 5637923c78e0SToby Isaac *clp = cla; 5638923c78e0SToby Isaac PetscFunctionReturn(0); 5639923c78e0SToby Isaac } 5640923c78e0SToby Isaac 56411dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5642923c78e0SToby Isaac { 5643923c78e0SToby Isaac PetscFunctionBeginHot; 5644923c78e0SToby Isaac if (!*clPoints) { 56459566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 5646923c78e0SToby Isaac } else { 56479566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 5648923c78e0SToby Isaac } 5649923c78e0SToby Isaac *numPoints = 0; 5650923c78e0SToby Isaac *points = NULL; 5651923c78e0SToby Isaac *clSec = NULL; 5652923c78e0SToby Isaac *clPoints = NULL; 5653923c78e0SToby Isaac *clp = NULL; 5654923c78e0SToby Isaac PetscFunctionReturn(0); 5655923c78e0SToby Isaac } 5656923c78e0SToby Isaac 56579fbee547SJacob 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[]) 56581a271a75SMatthew G. Knepley { 56591a271a75SMatthew G. Knepley PetscInt offset = 0, p; 566097e99dd9SToby Isaac const PetscInt **perms = NULL; 566197e99dd9SToby Isaac const PetscScalar **flips = NULL; 56621a271a75SMatthew G. Knepley 56631a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5664fe02ba77SJed Brown *size = 0; 56659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 566697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 566797e99dd9SToby Isaac const PetscInt point = points[2*p]; 566897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 566997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 56701a271a75SMatthew G. Knepley PetscInt dof, off, d; 56711a271a75SMatthew G. Knepley const PetscScalar *varr; 56721a271a75SMatthew G. Knepley 56739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 56749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 56751a271a75SMatthew G. Knepley varr = &vArray[off]; 567697e99dd9SToby Isaac if (clperm) { 567797e99dd9SToby Isaac if (perm) { 567897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 56791a271a75SMatthew G. Knepley } else { 568097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 568197e99dd9SToby Isaac } 568297e99dd9SToby Isaac if (flip) { 568397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 568497e99dd9SToby Isaac } 568597e99dd9SToby Isaac } else { 568697e99dd9SToby Isaac if (perm) { 568797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 568897e99dd9SToby Isaac } else { 568997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 569097e99dd9SToby Isaac } 569197e99dd9SToby Isaac if (flip) { 569297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 56931a271a75SMatthew G. Knepley } 56941a271a75SMatthew G. Knepley } 569597e99dd9SToby Isaac offset += dof; 569697e99dd9SToby Isaac } 56979566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 56981a271a75SMatthew G. Knepley *size = offset; 56991a271a75SMatthew G. Knepley PetscFunctionReturn(0); 57001a271a75SMatthew G. Knepley } 57011a271a75SMatthew G. Knepley 57029fbee547SJacob 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[]) 57031a271a75SMatthew G. Knepley { 57041a271a75SMatthew G. Knepley PetscInt offset = 0, f; 57051a271a75SMatthew G. Knepley 57061a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5707fe02ba77SJed Brown *size = 0; 57081a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 570997e99dd9SToby Isaac PetscInt p; 571097e99dd9SToby Isaac const PetscInt **perms = NULL; 571197e99dd9SToby Isaac const PetscScalar **flips = NULL; 57121a271a75SMatthew G. Knepley 57139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 571497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 571597e99dd9SToby Isaac const PetscInt point = points[2*p]; 571697e99dd9SToby Isaac PetscInt fdof, foff, b; 57171a271a75SMatthew G. Knepley const PetscScalar *varr; 571897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 571997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 57201a271a75SMatthew G. Knepley 57219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 57229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 57231a271a75SMatthew G. Knepley varr = &vArray[foff]; 572497e99dd9SToby Isaac if (clperm) { 572597e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 572697e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 572797e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 57281a271a75SMatthew G. Knepley } else { 572997e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 573097e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 573197e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 57321a271a75SMatthew G. Knepley } 573397e99dd9SToby Isaac offset += fdof; 57341a271a75SMatthew G. Knepley } 57359566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 57361a271a75SMatthew G. Knepley } 57371a271a75SMatthew G. Knepley *size = offset; 57381a271a75SMatthew G. Knepley PetscFunctionReturn(0); 57391a271a75SMatthew G. Knepley } 57401a271a75SMatthew G. Knepley 5741552f7358SJed Brown /*@C 5742552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5743552f7358SJed Brown 5744552f7358SJed Brown Not collective 5745552f7358SJed Brown 5746552f7358SJed Brown Input Parameters: 5747552f7358SJed Brown + dm - The DM 5748552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section 5749552f7358SJed Brown . v - The local vector 57506b867d5aSJose E. Roman - point - The point in the DM 5751552f7358SJed Brown 57526b867d5aSJose E. Roman Input/Output Parameters: 57536b867d5aSJose E. Roman + csize - The size of the input values array, or NULL; on output the number of values in the closure 57546b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically; 57556b867d5aSJose E. Roman if the user provided NULL, it is a borrowed array and should not be freed 575622c1ee49SMatthew G. Knepley 575722c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 575822c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 575922c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation. 576022c1ee49SMatthew G. Knepley $ 576122c1ee49SMatthew G. Knepley $ A typical use could be 576222c1ee49SMatthew G. Knepley $ 576322c1ee49SMatthew G. Knepley $ values = NULL; 57649566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 576522c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 576622c1ee49SMatthew G. Knepley $ <Compute on closure> 576722c1ee49SMatthew G. Knepley $ } 57689566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 576922c1ee49SMatthew G. Knepley $ 577022c1ee49SMatthew G. Knepley $ or 577122c1ee49SMatthew G. Knepley $ 577222c1ee49SMatthew G. Knepley $ PetscMalloc1(clMaxSize, &values); 577322c1ee49SMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) { 577422c1ee49SMatthew G. Knepley $ clSize = clMaxSize; 57759566063dSJacob Faibussowitsch $ PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 577622c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 577722c1ee49SMatthew G. Knepley $ <Compute on closure> 577822c1ee49SMatthew G. Knepley $ } 577922c1ee49SMatthew G. Knepley $ } 578022c1ee49SMatthew G. Knepley $ PetscFree(values); 5781552f7358SJed Brown 5782552f7358SJed Brown Fortran Notes: 5783552f7358SJed Brown Since it returns an array, this routine is only available in Fortran 90, and you must 5784552f7358SJed Brown include petsc.h90 in your code. 5785552f7358SJed Brown 5786552f7358SJed Brown The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5787552f7358SJed Brown 5788552f7358SJed Brown Level: intermediate 5789552f7358SJed Brown 5790db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5791552f7358SJed Brown @*/ 5792552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5793552f7358SJed Brown { 5794552f7358SJed Brown PetscSection clSection; 5795d9917b9dSMatthew G. Knepley IS clPoints; 5796552f7358SJed Brown PetscInt *points = NULL; 5797c459fbc1SJed Brown const PetscInt *clp, *perm; 5798c459fbc1SJed Brown PetscInt depth, numFields, numPoints, asize; 5799552f7358SJed Brown 5800d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 5801552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58029566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 58031a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 58041a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 58059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 58069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5807552f7358SJed Brown if (depth == 1 && numFields < 2) { 58089566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5809552f7358SJed Brown PetscFunctionReturn(0); 5810552f7358SJed Brown } 58111a271a75SMatthew G. Knepley /* Get points */ 58129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5813c459fbc1SJed Brown /* Get sizes */ 5814c459fbc1SJed Brown asize = 0; 5815c459fbc1SJed Brown for (PetscInt p = 0; p < numPoints*2; p += 2) { 5816c459fbc1SJed Brown PetscInt dof; 58179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 58181a271a75SMatthew G. Knepley asize += dof; 5819552f7358SJed Brown } 5820c459fbc1SJed Brown if (values) { 5821c459fbc1SJed Brown const PetscScalar *vArray; 5822c459fbc1SJed Brown PetscInt size; 5823c459fbc1SJed Brown 5824c459fbc1SJed Brown if (*values) { 582563a3b9bcSJacob 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); 58269566063dSJacob Faibussowitsch } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 58279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm)); 58289566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 58291a271a75SMatthew G. Knepley /* Get values */ 58309566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 58319566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 583263a3b9bcSJacob Faibussowitsch PetscCheck(asize == size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size); 58331a271a75SMatthew G. Knepley /* Cleanup array */ 58349566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5835d0f6b257SMatthew G. Knepley } 5836c459fbc1SJed Brown if (csize) *csize = asize; 5837c459fbc1SJed Brown /* Cleanup points */ 58389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5839552f7358SJed Brown PetscFunctionReturn(0); 5840552f7358SJed Brown } 5841552f7358SJed Brown 5842e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5843e5c487bfSMatthew G. Knepley { 5844e5c487bfSMatthew G. Knepley DMLabel depthLabel; 5845e5c487bfSMatthew G. Knepley PetscSection clSection; 5846e5c487bfSMatthew G. Knepley IS clPoints; 5847e5c487bfSMatthew G. Knepley PetscScalar *array; 5848e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 5849e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 5850c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 5851c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5852e5c487bfSMatthew G. Knepley 5853e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 5854e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58559566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 5856e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5857e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 58589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 58599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 58609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 5861e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 58629566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5863e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5864e5c487bfSMatthew G. Knepley } 5865e5c487bfSMatthew G. Knepley /* Get points */ 58669566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5867c459fbc1SJed Brown for (clsize=0,p=0; p<Np; p++) { 5868c459fbc1SJed Brown PetscInt dof; 58699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 5870c459fbc1SJed Brown clsize += dof; 5871c459fbc1SJed Brown } 58729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm)); 5873e5c487bfSMatthew G. Knepley /* Filter points */ 5874e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 5875e5c487bfSMatthew G. Knepley PetscInt dep; 5876e5c487bfSMatthew G. Knepley 58779566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 5878e5c487bfSMatthew G. Knepley if (dep != depth) continue; 5879e5c487bfSMatthew G. Knepley points[Np*2+0] = points[p]; 5880e5c487bfSMatthew G. Knepley points[Np*2+1] = points[p+1]; 5881e5c487bfSMatthew G. Knepley ++Np; 5882e5c487bfSMatthew G. Knepley } 5883e5c487bfSMatthew G. Knepley /* Get array */ 5884e5c487bfSMatthew G. Knepley if (!values || !*values) { 5885e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 5886e5c487bfSMatthew G. Knepley 5887e5c487bfSMatthew G. Knepley for (p = 0; p < Np*2; p += 2) { 58889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 5889e5c487bfSMatthew G. Knepley asize += dof; 5890e5c487bfSMatthew G. Knepley } 5891e5c487bfSMatthew G. Knepley if (!values) { 58929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5893e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 5894e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5895e5c487bfSMatthew G. Knepley } 58969566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 5897e5c487bfSMatthew G. Knepley } else { 5898e5c487bfSMatthew G. Knepley array = *values; 5899e5c487bfSMatthew G. Knepley } 59009566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 5901e5c487bfSMatthew G. Knepley /* Get values */ 59029566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 59039566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 5904e5c487bfSMatthew G. Knepley /* Cleanup points */ 59059566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5906e5c487bfSMatthew G. Knepley /* Cleanup array */ 59079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 5908e5c487bfSMatthew G. Knepley if (!*values) { 5909e5c487bfSMatthew G. Knepley if (csize) *csize = size; 5910e5c487bfSMatthew G. Knepley *values = array; 5911e5c487bfSMatthew G. Knepley } else { 591263a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 5913e5c487bfSMatthew G. Knepley *csize = size; 5914e5c487bfSMatthew G. Knepley } 5915e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5916e5c487bfSMatthew G. Knepley } 5917e5c487bfSMatthew G. Knepley 5918552f7358SJed Brown /*@C 5919552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5920552f7358SJed Brown 5921552f7358SJed Brown Not collective 5922552f7358SJed Brown 5923552f7358SJed Brown Input Parameters: 5924552f7358SJed Brown + dm - The DM 59250298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section 5926552f7358SJed Brown . v - The local vector 5927eaf898f9SPatrick Sanan . point - The point in the DM 59280298fd71SBarry Smith . csize - The number of values in the closure, or NULL 5929552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 5930552f7358SJed Brown 593122c1ee49SMatthew 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() 593222c1ee49SMatthew G. Knepley 59333813dfbdSMatthew G Knepley Fortran Notes: 59343813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 59353813dfbdSMatthew G Knepley include petsc.h90 in your code. 59363813dfbdSMatthew G Knepley 59373813dfbdSMatthew G Knepley The csize argument is not present in the Fortran 90 binding since it is internal to the array. 59383813dfbdSMatthew G Knepley 5939552f7358SJed Brown Level: intermediate 5940552f7358SJed Brown 5941db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 5942552f7358SJed Brown @*/ 59437c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5944a6dfd86eSKarl Rupp { 5945552f7358SJed Brown PetscInt size = 0; 5946552f7358SJed Brown 5947552f7358SJed Brown PetscFunctionBegin; 5948552f7358SJed Brown /* Should work without recalculating size */ 59499566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values)); 5950c9fdaa05SMatthew G. Knepley *values = NULL; 5951552f7358SJed Brown PetscFunctionReturn(0); 5952552f7358SJed Brown } 5953552f7358SJed Brown 59549fbee547SJacob Faibussowitsch static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 59559fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5956552f7358SJed Brown 59579fbee547SJacob 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[]) 5958552f7358SJed Brown { 5959552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 5960552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5961552f7358SJed Brown PetscScalar *a; 5962552f7358SJed Brown PetscInt off, cind = 0, k; 5963552f7358SJed Brown 5964552f7358SJed Brown PetscFunctionBegin; 59659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 59669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 5967552f7358SJed Brown a = &array[off]; 5968552f7358SJed Brown if (!cdof || setBC) { 596997e99dd9SToby Isaac if (clperm) { 597097e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 597197e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5972552f7358SJed Brown } else { 597397e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 597497e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5975552f7358SJed Brown } 5976552f7358SJed Brown } else { 59779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 597897e99dd9SToby Isaac if (clperm) { 597997e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) { 5980552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 598197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5982552f7358SJed Brown } 5983552f7358SJed Brown } else { 5984552f7358SJed Brown for (k = 0; k < dof; ++k) { 5985552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 598697e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 598797e99dd9SToby Isaac } 598897e99dd9SToby Isaac } 598997e99dd9SToby Isaac } else { 599097e99dd9SToby Isaac if (perm) { 599197e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 599297e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 599397e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 599497e99dd9SToby Isaac } 599597e99dd9SToby Isaac } else { 599697e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 599797e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 599897e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 599997e99dd9SToby Isaac } 6000552f7358SJed Brown } 6001552f7358SJed Brown } 6002552f7358SJed Brown } 6003552f7358SJed Brown PetscFunctionReturn(0); 6004552f7358SJed Brown } 6005552f7358SJed Brown 60069fbee547SJacob 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[]) 6007a5e93ea8SMatthew G. Knepley { 6008a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6009a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6010a5e93ea8SMatthew G. Knepley PetscScalar *a; 6011a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6012a5e93ea8SMatthew G. Knepley 6013a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 60149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 60159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6016a5e93ea8SMatthew G. Knepley a = &array[off]; 6017a5e93ea8SMatthew G. Knepley if (cdof) { 60189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 601997e99dd9SToby Isaac if (clperm) { 602097e99dd9SToby Isaac if (perm) { 6021a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6022a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 602397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 602497e99dd9SToby Isaac cind++; 6025a5e93ea8SMatthew G. Knepley } 6026a5e93ea8SMatthew G. Knepley } 6027a5e93ea8SMatthew G. Knepley } else { 6028a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6029a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 603097e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 603197e99dd9SToby Isaac cind++; 603297e99dd9SToby Isaac } 603397e99dd9SToby Isaac } 603497e99dd9SToby Isaac } 603597e99dd9SToby Isaac } else { 603697e99dd9SToby Isaac if (perm) { 603797e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 603897e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 603997e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 604097e99dd9SToby Isaac cind++; 604197e99dd9SToby Isaac } 604297e99dd9SToby Isaac } 604397e99dd9SToby Isaac } else { 604497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 604597e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 604697e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 604797e99dd9SToby Isaac cind++; 604897e99dd9SToby Isaac } 6049a5e93ea8SMatthew G. Knepley } 6050a5e93ea8SMatthew G. Knepley } 6051a5e93ea8SMatthew G. Knepley } 6052a5e93ea8SMatthew G. Knepley } 6053a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6054a5e93ea8SMatthew G. Knepley } 6055a5e93ea8SMatthew G. Knepley 60569fbee547SJacob 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[]) 6057a6dfd86eSKarl Rupp { 6058552f7358SJed Brown PetscScalar *a; 60591a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60601a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 606197e99dd9SToby Isaac PetscInt cind = 0, b; 6062552f7358SJed Brown 6063552f7358SJed Brown PetscFunctionBegin; 60649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 60659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 60669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 60671a271a75SMatthew G. Knepley a = &array[foff]; 6068552f7358SJed Brown if (!fcdof || setBC) { 606997e99dd9SToby Isaac if (clperm) { 607097e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 607197e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6072552f7358SJed Brown } else { 607397e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 607497e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6075552f7358SJed Brown } 6076552f7358SJed Brown } else { 60779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 607897e99dd9SToby Isaac if (clperm) { 607997e99dd9SToby Isaac if (perm) { 608097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 608197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 608297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6083552f7358SJed Brown } 6084552f7358SJed Brown } else { 608597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 608697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 608797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 608897e99dd9SToby Isaac } 608997e99dd9SToby Isaac } 609097e99dd9SToby Isaac } else { 609197e99dd9SToby Isaac if (perm) { 609297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 609397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 609497e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 609597e99dd9SToby Isaac } 609697e99dd9SToby Isaac } else { 609797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 609897e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 609997e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6100552f7358SJed Brown } 6101552f7358SJed Brown } 6102552f7358SJed Brown } 6103552f7358SJed Brown } 61041a271a75SMatthew G. Knepley *offset += fdof; 6105552f7358SJed Brown PetscFunctionReturn(0); 6106552f7358SJed Brown } 6107552f7358SJed Brown 61089fbee547SJacob 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[]) 6109a5e93ea8SMatthew G. Knepley { 6110a5e93ea8SMatthew G. Knepley PetscScalar *a; 61111a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 61121a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 61135da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6114ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6115a5e93ea8SMatthew G. Knepley 6116a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 61179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 61189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 61199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 61209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 61211a271a75SMatthew G. Knepley a = &array[foff]; 6122a5e93ea8SMatthew G. Knepley if (fcdof) { 6123ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 61249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 612597e99dd9SToby Isaac if (clperm) { 612697e99dd9SToby Isaac if (perm) { 6127ba322698SMatthew G. Knepley if (comps) { 6128ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6129ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61305da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6131ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6132ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6133ba322698SMatthew G. Knepley } 6134ba322698SMatthew G. Knepley } else { 613597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 613697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 613797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6138a5e93ea8SMatthew G. Knepley ++cind; 6139a5e93ea8SMatthew G. Knepley } 6140a5e93ea8SMatthew G. Knepley } 6141ba322698SMatthew G. Knepley } 6142ba322698SMatthew G. Knepley } else { 6143ba322698SMatthew G. Knepley if (comps) { 6144ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6145ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61465da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6147ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6148ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6149ba322698SMatthew G. Knepley } 6150a5e93ea8SMatthew G. Knepley } else { 615197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 615297e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 615397e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 615497e99dd9SToby Isaac ++cind; 615597e99dd9SToby Isaac } 615697e99dd9SToby Isaac } 615797e99dd9SToby Isaac } 6158ba322698SMatthew G. Knepley } 615997e99dd9SToby Isaac } else { 616097e99dd9SToby Isaac if (perm) { 6161ba322698SMatthew G. Knepley if (comps) { 6162ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6163ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61645da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6165ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6166ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6167ba322698SMatthew G. Knepley } 6168ba322698SMatthew G. Knepley } else { 616997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 617097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 617197e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 617297e99dd9SToby Isaac ++cind; 617397e99dd9SToby Isaac } 617497e99dd9SToby Isaac } 6175ba322698SMatthew G. Knepley } 6176ba322698SMatthew G. Knepley } else { 6177ba322698SMatthew G. Knepley if (comps) { 6178ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6179ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61805da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6181ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6182ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6183ba322698SMatthew G. Knepley } 618497e99dd9SToby Isaac } else { 618597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 618697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 618797e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6188a5e93ea8SMatthew G. Knepley ++cind; 6189a5e93ea8SMatthew G. Knepley } 6190a5e93ea8SMatthew G. Knepley } 6191a5e93ea8SMatthew G. Knepley } 6192a5e93ea8SMatthew G. Knepley } 6193a5e93ea8SMatthew G. Knepley } 6194ba322698SMatthew G. Knepley } 61951a271a75SMatthew G. Knepley *offset += fdof; 6196a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6197a5e93ea8SMatthew G. Knepley } 6198a5e93ea8SMatthew G. Knepley 61999fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6200a6dfd86eSKarl Rupp { 6201552f7358SJed Brown PetscScalar *array; 62021b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 62031b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6204552f7358SJed Brown 62051b406b76SMatthew G. Knepley PetscFunctionBeginHot; 62069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 62079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 62089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 62099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 62109566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6211b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6212b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p-1]; 6213b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p-1]; 6214b6ebb6e6SMatthew G. Knepley 6215b6ebb6e6SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 62169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6217b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6218b6ebb6e6SMatthew G. Knepley { 6219b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6220b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6221b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6222b6ebb6e6SMatthew G. Knepley 62239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 62249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6225b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6226b6ebb6e6SMatthew G. Knepley if (!cdof) { 6227b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6228b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6229b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6230b6ebb6e6SMatthew G. Knepley } 6231b6ebb6e6SMatthew G. Knepley } else { 6232b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6233b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6234b6ebb6e6SMatthew G. Knepley } 6235b6ebb6e6SMatthew G. Knepley } 6236b6ebb6e6SMatthew G. Knepley } else { 62379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6238b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6239b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6240b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6241b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6242b6ebb6e6SMatthew G. Knepley } 6243b6ebb6e6SMatthew G. Knepley } else { 6244b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6245b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6246b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6247b6ebb6e6SMatthew G. Knepley } 6248b6ebb6e6SMatthew G. Knepley } 6249b6ebb6e6SMatthew G. Knepley } 6250b6ebb6e6SMatthew G. Knepley } 6251b6ebb6e6SMatthew G. Knepley } 62529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6253b6ebb6e6SMatthew G. Knepley PetscFunctionReturn(0); 6254b6ebb6e6SMatthew G. Knepley } 62551b406b76SMatthew G. Knepley 62561b406b76SMatthew G. Knepley /*@C 62571b406b76SMatthew G. Knepley DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 62581b406b76SMatthew G. Knepley 62591b406b76SMatthew G. Knepley Not collective 62601b406b76SMatthew G. Knepley 62611b406b76SMatthew G. Knepley Input Parameters: 62621b406b76SMatthew G. Knepley + dm - The DM 62631b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 62641b406b76SMatthew G. Knepley . v - The local vector 6265eaf898f9SPatrick Sanan . point - The point in the DM 62661b406b76SMatthew G. Knepley . values - The array of values 626722c1ee49SMatthew 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, 626822c1ee49SMatthew G. Knepley where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 62691b406b76SMatthew G. Knepley 62701b406b76SMatthew G. Knepley Fortran Notes: 62711b406b76SMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 62721b406b76SMatthew G. Knepley 62731b406b76SMatthew G. Knepley Level: intermediate 62741b406b76SMatthew G. Knepley 6275db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 62761b406b76SMatthew G. Knepley @*/ 62771b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 62781b406b76SMatthew G. Knepley { 62791b406b76SMatthew G. Knepley PetscSection clSection; 62801b406b76SMatthew G. Knepley IS clPoints; 62811b406b76SMatthew G. Knepley PetscScalar *array; 62821b406b76SMatthew G. Knepley PetscInt *points = NULL; 628327f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6284c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 62851b406b76SMatthew G. Knepley 62861a271a75SMatthew G. Knepley PetscFunctionBeginHot; 62871b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62889566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 62891a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 62901a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 62919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 62929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 62931b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 62949566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 62951b406b76SMatthew G. Knepley PetscFunctionReturn(0); 62961b406b76SMatthew G. Knepley } 62971a271a75SMatthew G. Knepley /* Get points */ 62989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6299c459fbc1SJed Brown for (clsize=0,p=0; p<numPoints; p++) { 6300c459fbc1SJed Brown PetscInt dof; 63019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 6302c459fbc1SJed Brown clsize += dof; 6303c459fbc1SJed Brown } 63049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 63051a271a75SMatthew G. Knepley /* Get array */ 63069566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 63071a271a75SMatthew G. Knepley /* Get values */ 6308ef90cfe2SMatthew G. Knepley if (numFields > 0) { 630997e99dd9SToby Isaac PetscInt offset = 0, f; 6310552f7358SJed Brown for (f = 0; f < numFields; ++f) { 631197e99dd9SToby Isaac const PetscInt **perms = NULL; 631297e99dd9SToby Isaac const PetscScalar **flips = NULL; 631397e99dd9SToby Isaac 63149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6315552f7358SJed Brown switch (mode) { 6316552f7358SJed Brown case INSERT_VALUES: 631797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 631897e99dd9SToby Isaac const PetscInt point = points[2*p]; 631997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 632197e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6322552f7358SJed Brown } break; 6323552f7358SJed Brown case INSERT_ALL_VALUES: 632497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632597e99dd9SToby Isaac const PetscInt point = points[2*p]; 632697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 632897e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6329552f7358SJed Brown } break; 6330a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 633197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 633297e99dd9SToby Isaac const PetscInt point = points[2*p]; 633397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 633497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6335ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6336a5e93ea8SMatthew G. Knepley } break; 6337552f7358SJed Brown case ADD_VALUES: 633897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 633997e99dd9SToby Isaac const PetscInt point = points[2*p]; 634097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 634197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 634297e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6343552f7358SJed Brown } break; 6344552f7358SJed Brown case ADD_ALL_VALUES: 634597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 634697e99dd9SToby Isaac const PetscInt point = points[2*p]; 634797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 634897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 634997e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6350552f7358SJed Brown } break; 6351304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 635297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 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; 6356ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6357304ab55fSMatthew G. Knepley } break; 6358552f7358SJed Brown default: 635998921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6360552f7358SJed Brown } 63619566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 63621a271a75SMatthew G. Knepley } 6363552f7358SJed Brown } else { 63641a271a75SMatthew G. Knepley PetscInt dof, off; 636597e99dd9SToby Isaac const PetscInt **perms = NULL; 636697e99dd9SToby Isaac const PetscScalar **flips = NULL; 63671a271a75SMatthew G. Knepley 63689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 6369552f7358SJed Brown switch (mode) { 6370552f7358SJed Brown case INSERT_VALUES: 637197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 637297e99dd9SToby Isaac const PetscInt point = points[2*p]; 637397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 637497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 637697e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6377552f7358SJed Brown } break; 6378552f7358SJed Brown case INSERT_ALL_VALUES: 637997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 638097e99dd9SToby Isaac const PetscInt point = points[2*p]; 638197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 638297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 638497e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6385552f7358SJed Brown } break; 6386a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 638797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 638897e99dd9SToby Isaac const PetscInt point = points[2*p]; 638997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 639097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 639297e99dd9SToby Isaac updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6393a5e93ea8SMatthew G. Knepley } break; 6394552f7358SJed Brown case ADD_VALUES: 639597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 639697e99dd9SToby Isaac const PetscInt point = points[2*p]; 639797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 639897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 640097e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6401552f7358SJed Brown } break; 6402552f7358SJed Brown case ADD_ALL_VALUES: 640397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 640497e99dd9SToby Isaac const PetscInt point = points[2*p]; 640597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 640697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 640897e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6409552f7358SJed Brown } break; 6410304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 641197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 641297e99dd9SToby Isaac const PetscInt point = points[2*p]; 641397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 641497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 641697e99dd9SToby Isaac updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6417304ab55fSMatthew G. Knepley } break; 6418552f7358SJed Brown default: 641998921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6420552f7358SJed Brown } 64219566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 6422552f7358SJed Brown } 64231a271a75SMatthew G. Knepley /* Cleanup points */ 64249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 64251a271a75SMatthew G. Knepley /* Cleanup array */ 64269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6427552f7358SJed Brown PetscFunctionReturn(0); 6428552f7358SJed Brown } 6429552f7358SJed Brown 64305f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 64319fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 64325f790a90SMatthew G. Knepley { 64335f790a90SMatthew G. Knepley PetscFunctionBegin; 64345f790a90SMatthew G. Knepley if (label) { 64355f790a90SMatthew G. Knepley PetscInt val, fdof; 64365f790a90SMatthew G. Knepley 64375f790a90SMatthew G. Knepley /* There is a problem with this: 64385f790a90SMatthew 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 64395f790a90SMatthew 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. 64405f790a90SMatthew G. Knepley Thus I am only going to check val != -1, not val != labelId 64415f790a90SMatthew G. Knepley */ 64429566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 64435f790a90SMatthew G. Knepley if (val < 0) { 64449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 64455f790a90SMatthew G. Knepley *offset += fdof; 64465f790a90SMatthew G. Knepley PetscFunctionReturn(1); 64475f790a90SMatthew G. Knepley } 64485f790a90SMatthew G. Knepley } 64495f790a90SMatthew G. Knepley PetscFunctionReturn(0); 64505f790a90SMatthew G. Knepley } 64515f790a90SMatthew G. Knepley 645297529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 64535f790a90SMatthew 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) 6454e07394fbSMatthew G. Knepley { 6455e07394fbSMatthew G. Knepley PetscSection clSection; 6456e07394fbSMatthew G. Knepley IS clPoints; 6457e07394fbSMatthew G. Knepley PetscScalar *array; 6458e07394fbSMatthew G. Knepley PetscInt *points = NULL; 645997529cf3SJed Brown const PetscInt *clp; 6460e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 646197e99dd9SToby Isaac PetscInt offset = 0, f; 6462e07394fbSMatthew G. Knepley 6463e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 6464e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64659566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6466e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6467e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6469e07394fbSMatthew G. Knepley /* Get points */ 64709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6471e07394fbSMatthew G. Knepley /* Get array */ 64729566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6473e07394fbSMatthew G. Knepley /* Get values */ 6474e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 647597e99dd9SToby Isaac const PetscInt **perms = NULL; 647697e99dd9SToby Isaac const PetscScalar **flips = NULL; 647797e99dd9SToby Isaac 6478e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 6479e07394fbSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 6480e07394fbSMatthew G. Knepley PetscInt fdof; 64819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 6482e07394fbSMatthew G. Knepley offset += fdof; 6483e07394fbSMatthew G. Knepley } 6484e07394fbSMatthew G. Knepley continue; 6485e07394fbSMatthew G. Knepley } 64869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6487e07394fbSMatthew G. Knepley switch (mode) { 6488e07394fbSMatthew G. Knepley case INSERT_VALUES: 648997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649097e99dd9SToby Isaac const PetscInt point = points[2*p]; 649197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64935f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64949566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 6495e07394fbSMatthew G. Knepley } break; 6496e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 649797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649897e99dd9SToby Isaac const PetscInt point = points[2*p]; 649997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 650097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65015f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65029566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 6503e07394fbSMatthew G. Knepley } break; 6504e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 650597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 650697e99dd9SToby Isaac const PetscInt point = points[2*p]; 650797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 650897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65095f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65109566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 6511e07394fbSMatthew G. Knepley } break; 6512e07394fbSMatthew G. Knepley case ADD_VALUES: 651397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 651497e99dd9SToby Isaac const PetscInt point = points[2*p]; 651597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 651697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65175f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65189566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 6519e07394fbSMatthew G. Knepley } break; 6520e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 652197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 652297e99dd9SToby Isaac const PetscInt point = points[2*p]; 652397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 652497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65255f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65269566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 6527e07394fbSMatthew G. Knepley } break; 6528e07394fbSMatthew G. Knepley default: 652998921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6530e07394fbSMatthew G. Knepley } 65319566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6532e07394fbSMatthew G. Knepley } 6533e07394fbSMatthew G. Knepley /* Cleanup points */ 65349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6535e07394fbSMatthew G. Knepley /* Cleanup array */ 65369566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 6537e07394fbSMatthew G. Knepley PetscFunctionReturn(0); 6538e07394fbSMatthew G. Knepley } 6539e07394fbSMatthew G. Knepley 65407cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6541552f7358SJed Brown { 6542552f7358SJed Brown PetscMPIInt rank; 6543552f7358SJed Brown PetscInt i, j; 6544552f7358SJed Brown 6545552f7358SJed Brown PetscFunctionBegin; 65469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 654763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 654863a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 654963a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 6550b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 6551557cf195SMatthew G. Knepley if (!values) PetscFunctionReturn(0); 6552b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 65539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 6554b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 6555519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 65569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]))); 6557552f7358SJed Brown #else 65589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j])); 6559552f7358SJed Brown #endif 6560552f7358SJed Brown } 65619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 6562552f7358SJed Brown } 6563552f7358SJed Brown PetscFunctionReturn(0); 6564552f7358SJed Brown } 6565552f7358SJed Brown 656605586334SMatthew G. Knepley /* 656705586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 656805586334SMatthew G. Knepley 656905586334SMatthew G. Knepley Input Parameters: 657005586334SMatthew G. Knepley + section - The section for this data layout 657136fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 657205586334SMatthew G. Knepley . point - The point contributing dofs with these indices 657305586334SMatthew G. Knepley . off - The global offset of this point 657405586334SMatthew G. Knepley . loff - The local offset of each field 6575a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 657605586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 657705586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 657805586334SMatthew G. Knepley 657905586334SMatthew G. Knepley Output Parameter: 658005586334SMatthew G. Knepley . indices - Indices for dofs on this point 658105586334SMatthew G. Knepley 658205586334SMatthew G. Knepley Level: developer 658305586334SMatthew G. Knepley 658405586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 658505586334SMatthew G. Knepley */ 658636fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6587a6dfd86eSKarl Rupp { 6588e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 6589552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6590552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6591552f7358SJed Brown PetscInt cind = 0, k; 6592552f7358SJed Brown 6593552f7358SJed Brown PetscFunctionBegin; 659408401ef6SPierre Jolivet PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 65959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 65969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 6597552f7358SJed Brown if (!cdof || setBC) { 659805586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 659905586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 660005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 660105586334SMatthew G. Knepley 660205586334SMatthew G. Knepley indices[ind] = off + k; 6603552f7358SJed Brown } 6604552f7358SJed Brown } else { 66059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 66064acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 660705586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 660805586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 660905586334SMatthew G. Knepley 66104acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 66114acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 661205586334SMatthew G. Knepley indices[ind] = -(off+k+1); 66134acb8e1eSToby Isaac ++cind; 66144acb8e1eSToby Isaac } else { 661536fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 6616552f7358SJed Brown } 6617552f7358SJed Brown } 6618552f7358SJed Brown } 6619e6ccafaeSMatthew G Knepley *loff += dof; 6620552f7358SJed Brown PetscFunctionReturn(0); 6621552f7358SJed Brown } 6622552f7358SJed Brown 66237e29afd2SMatthew G. Knepley /* 662436fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 66257e29afd2SMatthew G. Knepley 662636fa2b79SJed Brown Input Parameters: 662736fa2b79SJed Brown + section - a section (global or local) 662836fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 662936fa2b79SJed Brown . point - point within section 663036fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 663136fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 663236fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 663336fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 663436fa2b79SJed Brown . permsoff - offset 663536fa2b79SJed Brown - indperm - index permutation 663636fa2b79SJed Brown 663736fa2b79SJed Brown Output Parameter: 663836fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 663936fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 664036fa2b79SJed Brown 664136fa2b79SJed Brown Notes: 664236fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 664336fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 664436fa2b79SJed Brown in the local vector. 664536fa2b79SJed Brown 664636fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 664736fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 664836fa2b79SJed Brown 664936fa2b79SJed Brown Developer Note: 665036fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 665136fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 665236fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 665336fa2b79SJed Brown 665436fa2b79SJed Brown Example: 665536fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 665636fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 665736fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 665836fa2b79SJed 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. 665936fa2b79SJed Brown 666036fa2b79SJed Brown Level: developer 66617e29afd2SMatthew G. Knepley */ 666236fa2b79SJed 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[]) 6663a6dfd86eSKarl Rupp { 6664552f7358SJed Brown PetscInt numFields, foff, f; 6665552f7358SJed Brown 6666552f7358SJed Brown PetscFunctionBegin; 666708401ef6SPierre Jolivet PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 66689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6669552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 66704acb8e1eSToby Isaac PetscInt fdof, cfdof; 6671552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 66724acb8e1eSToby Isaac PetscInt cind = 0, b; 66734acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6674552f7358SJed Brown 66759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 66769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 6677552f7358SJed Brown if (!cfdof || setBC) { 667805586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 667905586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 668005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 668105586334SMatthew G. Knepley 668205586334SMatthew G. Knepley indices[ind] = off+foff+b; 668305586334SMatthew G. Knepley } 6684552f7358SJed Brown } else { 66859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 668605586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 668705586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 668805586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 668905586334SMatthew G. Knepley 66904acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 669105586334SMatthew G. Knepley indices[ind] = -(off+foff+b+1); 6692552f7358SJed Brown ++cind; 6693552f7358SJed Brown } else { 669436fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 6695552f7358SJed Brown } 6696552f7358SJed Brown } 6697552f7358SJed Brown } 669836fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6699552f7358SJed Brown foffs[f] += fdof; 6700552f7358SJed Brown } 6701552f7358SJed Brown PetscFunctionReturn(0); 6702552f7358SJed Brown } 6703552f7358SJed Brown 67047e29afd2SMatthew G. Knepley /* 67057e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 67067e29afd2SMatthew G. Knepley 67077e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 6708645102dcSJed Brown 6709645102dcSJed Brown Notes: 6710645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6711645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 67127e29afd2SMatthew G. Knepley */ 6713645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 67147e29afd2SMatthew G. Knepley { 67157e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 67167e29afd2SMatthew G. Knepley 67177e29afd2SMatthew G. Knepley PetscFunctionBegin; 67189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 67197e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 67207e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 67217e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67227e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 67237e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 67247e29afd2SMatthew G. Knepley 67259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 67279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 6728645102dcSJed Brown if (!cfdof) { 672905586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 673005586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 673105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 673205586334SMatthew G. Knepley 673305586334SMatthew G. Knepley indices[ind] = foff+b; 673405586334SMatthew G. Knepley } 67357e29afd2SMatthew G. Knepley } else { 67369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 673705586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 673805586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 673905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 674005586334SMatthew G. Knepley 67417e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 674205586334SMatthew G. Knepley indices[ind] = -(foff+b+1); 67437e29afd2SMatthew G. Knepley ++cind; 67447e29afd2SMatthew G. Knepley } else { 674505586334SMatthew G. Knepley indices[ind] = foff+b-cind; 67467e29afd2SMatthew G. Knepley } 67477e29afd2SMatthew G. Knepley } 67487e29afd2SMatthew G. Knepley } 67497e29afd2SMatthew G. Knepley foffs[f] += fdof; 67507e29afd2SMatthew G. Knepley } 67517e29afd2SMatthew G. Knepley PetscFunctionReturn(0); 67527e29afd2SMatthew G. Knepley } 67537e29afd2SMatthew G. Knepley 67544acb8e1eSToby 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) 6755d3d1a6afSToby Isaac { 6756d3d1a6afSToby Isaac Mat cMat; 6757d3d1a6afSToby Isaac PetscSection aSec, cSec; 6758d3d1a6afSToby Isaac IS aIS; 6759d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 6760d3d1a6afSToby Isaac const PetscInt *anchors; 6761e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 6762d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 6763d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 6764d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 6765d3d1a6afSToby Isaac PetscInt newOffsets[32]; 6766d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 6767d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 6768d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 67696ecaa68aSToby Isaac PetscScalar *newValues=NULL,*tmpValues; 6770d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 6771d3d1a6afSToby Isaac 6772d3d1a6afSToby Isaac PetscFunctionBegin; 6773d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6774d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 67759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6776d3d1a6afSToby Isaac 67779566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 6778d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 6779d3d1a6afSToby Isaac if (aSec) { 67809566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 67819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 67829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd)); 6783d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 6784d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 6785d3d1a6afSToby Isaac * into the global matrix anyway) */ 6786d3d1a6afSToby Isaac for (p = 0; p < 2*numPoints; p+=2) { 6787d3d1a6afSToby Isaac PetscInt b = points[p]; 67884b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6789d3d1a6afSToby Isaac 67909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 67914b2f2278SToby Isaac if (!bSecDof) { 67924b2f2278SToby Isaac continue; 67934b2f2278SToby Isaac } 6794d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 67959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,b,&bDof)); 6796d3d1a6afSToby Isaac } 6797d3d1a6afSToby Isaac if (bDof) { 6798d3d1a6afSToby Isaac /* this point is constrained */ 6799d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 6800d3d1a6afSToby Isaac PetscInt bOff, q; 6801d3d1a6afSToby Isaac 6802d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 6803d3d1a6afSToby Isaac newNumPoints += bDof; 68049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,b,&bOff)); 6805d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6806d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6807d3d1a6afSToby Isaac PetscInt aDof; 6808d3d1a6afSToby Isaac 68099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 6810d3d1a6afSToby Isaac newNumIndices += aDof; 6811d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6812d3d1a6afSToby Isaac PetscInt fDof; 6813d3d1a6afSToby Isaac 68149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 6815d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6816d3d1a6afSToby Isaac } 6817d3d1a6afSToby Isaac } 6818d3d1a6afSToby Isaac } 6819d3d1a6afSToby Isaac else { 6820d3d1a6afSToby Isaac /* this point is not constrained */ 6821d3d1a6afSToby Isaac newNumPoints++; 68224b2f2278SToby Isaac newNumIndices += bSecDof; 6823d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6824d3d1a6afSToby Isaac PetscInt fDof; 6825d3d1a6afSToby Isaac 68269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6827d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6828d3d1a6afSToby Isaac } 6829d3d1a6afSToby Isaac } 6830d3d1a6afSToby Isaac } 6831d3d1a6afSToby Isaac } 6832d3d1a6afSToby Isaac if (!anyConstrained) { 683372b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 683472b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 683572b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 683672b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 68379566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors)); 6838d3d1a6afSToby Isaac PetscFunctionReturn(0); 6839d3d1a6afSToby Isaac } 6840d3d1a6afSToby Isaac 68416ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 68426ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 68436ecaa68aSToby Isaac 6844f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6845d3d1a6afSToby Isaac 68466ecaa68aSToby Isaac if (!outPoints && !outValues) { 68476ecaa68aSToby Isaac if (offsets) { 68486ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 68496ecaa68aSToby Isaac offsets[f] = newOffsets[f]; 68506ecaa68aSToby Isaac } 68516ecaa68aSToby Isaac } 68529566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors)); 68536ecaa68aSToby Isaac PetscFunctionReturn(0); 68546ecaa68aSToby Isaac } 68556ecaa68aSToby Isaac 68561dca8a05SBarry 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); 6857d3d1a6afSToby Isaac 68589566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 6859d3d1a6afSToby Isaac 6860d3d1a6afSToby Isaac /* workspaces */ 6861d3d1a6afSToby Isaac if (numFields) { 6862d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 68639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 68649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 6865d3d1a6afSToby Isaac } 6866d3d1a6afSToby Isaac } 6867d3d1a6afSToby Isaac else { 68689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 68699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0])); 6870d3d1a6afSToby Isaac } 6871d3d1a6afSToby Isaac 6872d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 6873d3d1a6afSToby Isaac if (numFields) { 68744b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 68754b2f2278SToby Isaac 6876d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6877d3d1a6afSToby Isaac PetscInt b = points[2*p]; 68784b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6879d3d1a6afSToby Isaac 68809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 68814b2f2278SToby Isaac if (!bSecDof) { 68824b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 68834b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 68844b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 68854b2f2278SToby Isaac } 68864b2f2278SToby Isaac continue; 68874b2f2278SToby Isaac } 6888d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 68899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6890d3d1a6afSToby Isaac } 6891d3d1a6afSToby Isaac if (bDof) { 6892d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6893d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 6894d3d1a6afSToby Isaac 68959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 68969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6897d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6898d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6899d3d1a6afSToby Isaac PetscInt aFDof; 6900d3d1a6afSToby Isaac 69019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 6902d3d1a6afSToby Isaac allFDof += aFDof; 6903d3d1a6afSToby Isaac } 6904d3d1a6afSToby Isaac newPointOffsets[f][p+1] = allFDof; 6905d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = fDof * allFDof; 6906d3d1a6afSToby Isaac } 6907d3d1a6afSToby Isaac } 6908d3d1a6afSToby Isaac else { 6909d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6910d3d1a6afSToby Isaac PetscInt fDof; 6911d3d1a6afSToby Isaac 69129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 6913d3d1a6afSToby Isaac newPointOffsets[f][p+1] = fDof; 6914d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = 0; 6915d3d1a6afSToby Isaac } 6916d3d1a6afSToby Isaac } 6917d3d1a6afSToby Isaac } 69184b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 69194b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 69204b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 6921d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6922d3d1a6afSToby Isaac newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6923d3d1a6afSToby Isaac pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6924d3d1a6afSToby Isaac } 692519f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 692619f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 69279566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 6928d3d1a6afSToby Isaac } 6929d3d1a6afSToby Isaac } 6930d3d1a6afSToby Isaac else { 6931d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6932d3d1a6afSToby Isaac PetscInt b = points[2*p]; 69334b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6934d3d1a6afSToby Isaac 69359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&bSecDof)); 69364b2f2278SToby Isaac if (!bSecDof) { 69374b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 69384b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 69394b2f2278SToby Isaac continue; 69404b2f2278SToby Isaac } 6941d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6943d3d1a6afSToby Isaac } 6944d3d1a6afSToby Isaac if (bDof) { 69454b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 6946d3d1a6afSToby Isaac 69479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 6948d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6949d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 6950d3d1a6afSToby Isaac 69519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 6952d3d1a6afSToby Isaac allDof += aDof; 6953d3d1a6afSToby Isaac } 6954d3d1a6afSToby Isaac newPointOffsets[0][p+1] = allDof; 69554b2f2278SToby Isaac pointMatOffsets[0][p+1] = bSecDof * allDof; 6956d3d1a6afSToby Isaac } 6957d3d1a6afSToby Isaac else { 69584b2f2278SToby Isaac newPointOffsets[0][p+1] = bSecDof; 6959d3d1a6afSToby Isaac pointMatOffsets[0][p+1] = 0; 6960d3d1a6afSToby Isaac } 6961d3d1a6afSToby Isaac } 6962d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 6963d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 6964d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6965d3d1a6afSToby Isaac newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6966d3d1a6afSToby Isaac pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6967d3d1a6afSToby Isaac } 69689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 6969d3d1a6afSToby Isaac } 6970d3d1a6afSToby Isaac 69716ecaa68aSToby Isaac /* output arrays */ 69729566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 69736ecaa68aSToby Isaac 6974d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 69759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 69769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 69779566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices)); 69789566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 6979d3d1a6afSToby Isaac if (numFields) { 6980d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 6981d3d1a6afSToby Isaac PetscInt b = points[2*p]; 6982d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 69834b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6984d3d1a6afSToby Isaac 69859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 69864b2f2278SToby Isaac if (!bSecDof) { 69874b2f2278SToby Isaac continue; 69884b2f2278SToby Isaac } 6989d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 6991d3d1a6afSToby Isaac } 6992d3d1a6afSToby Isaac if (bDof) { 6993d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6994d3d1a6afSToby Isaac 6995d3d1a6afSToby Isaac fStart[0] = 0; 6996d3d1a6afSToby Isaac fEnd[0] = 0; 6997d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6998d3d1a6afSToby Isaac PetscInt fDof; 6999d3d1a6afSToby Isaac 70009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7001d3d1a6afSToby Isaac fStart[f+1] = fStart[f] + fDof; 7002d3d1a6afSToby Isaac fEnd[f+1] = fStart[f+1]; 7003d3d1a6afSToby Isaac } 70049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 70059566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7006d3d1a6afSToby Isaac 7007d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7008d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7009d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7010d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7011d3d1a6afSToby Isaac 7012d3d1a6afSToby Isaac fAnchorStart[f+1] = fAnchorStart[f] + fDof; 7013d3d1a6afSToby Isaac fAnchorEnd[f+1] = fAnchorStart[f + 1]; 7014d3d1a6afSToby Isaac } 70159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7016d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7017d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7018d3d1a6afSToby Isaac 7019d3d1a6afSToby 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 */ 7020d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7021d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70239566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7024d3d1a6afSToby Isaac } 7025d3d1a6afSToby Isaac newP += bDof; 7026d3d1a6afSToby Isaac 70276ecaa68aSToby Isaac if (outValues) { 7028d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 7029d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 70309566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p])); 7031d3d1a6afSToby Isaac } 7032d3d1a6afSToby Isaac } 70336ecaa68aSToby Isaac } 7034d3d1a6afSToby Isaac else { 7035d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7036d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7037d3d1a6afSToby Isaac newP++; 7038d3d1a6afSToby Isaac } 7039d3d1a6afSToby Isaac } 7040d3d1a6afSToby Isaac } else { 7041d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7042d3d1a6afSToby Isaac PetscInt b = points[2*p]; 7043d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 70444b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7045d3d1a6afSToby Isaac 70469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 70474b2f2278SToby Isaac if (!bSecDof) { 70484b2f2278SToby Isaac continue; 70494b2f2278SToby Isaac } 7050d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 70519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7052d3d1a6afSToby Isaac } 7053d3d1a6afSToby Isaac if (bDof) { 7054d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7055d3d1a6afSToby Isaac 70569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 70579566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7058d3d1a6afSToby Isaac 70599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset (aSec, b, &bOff)); 7060d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7061d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7062d3d1a6afSToby Isaac 7063d3d1a6afSToby 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 */ 7064d3d1a6afSToby Isaac 7065d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7066d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 70689566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7069d3d1a6afSToby Isaac } 7070d3d1a6afSToby Isaac newP += bDof; 7071d3d1a6afSToby Isaac 7072d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 70736ecaa68aSToby Isaac if (outValues) { 70749566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p])); 7075d3d1a6afSToby Isaac } 70766ecaa68aSToby Isaac } 7077d3d1a6afSToby Isaac else { 7078d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7079d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7080d3d1a6afSToby Isaac newP++; 7081d3d1a6afSToby Isaac } 7082d3d1a6afSToby Isaac } 7083d3d1a6afSToby Isaac } 7084d3d1a6afSToby Isaac 70856ecaa68aSToby Isaac if (outValues) { 70869566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 70879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues,newNumIndices*numIndices)); 7088d3d1a6afSToby Isaac /* multiply constraints on the right */ 7089d3d1a6afSToby Isaac if (numFields) { 7090d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7091d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7092d3d1a6afSToby Isaac 7093d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7094d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7095d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7096d3d1a6afSToby Isaac PetscInt c, r, k; 7097d3d1a6afSToby Isaac PetscInt dof; 7098d3d1a6afSToby Isaac 70999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,b,f,&dof)); 71004b2f2278SToby Isaac if (!dof) { 71014b2f2278SToby Isaac continue; 71024b2f2278SToby Isaac } 7103d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7104d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7105d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7106d3d1a6afSToby Isaac 7107d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7108d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7109d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 71104acb8e1eSToby Isaac tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7111d3d1a6afSToby Isaac } 7112d3d1a6afSToby Isaac } 7113d3d1a6afSToby Isaac } 7114d3d1a6afSToby Isaac } 7115d3d1a6afSToby Isaac else { 7116d3d1a6afSToby Isaac /* copy this column as is */ 7117d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7118d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7119d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7120d3d1a6afSToby Isaac } 7121d3d1a6afSToby Isaac } 7122d3d1a6afSToby Isaac } 7123d3d1a6afSToby Isaac oldOff += dof; 7124d3d1a6afSToby Isaac } 7125d3d1a6afSToby Isaac } 7126d3d1a6afSToby Isaac } 7127d3d1a6afSToby Isaac else { 7128d3d1a6afSToby Isaac PetscInt oldOff = 0; 7129d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7130d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7131d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7132d3d1a6afSToby Isaac PetscInt c, r, k; 7133d3d1a6afSToby Isaac PetscInt dof; 7134d3d1a6afSToby Isaac 71359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&dof)); 71364b2f2278SToby Isaac if (!dof) { 71374b2f2278SToby Isaac continue; 71384b2f2278SToby Isaac } 7139d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7140d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7141d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7142d3d1a6afSToby Isaac 7143d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7144d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7145d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7146d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7147d3d1a6afSToby Isaac } 7148d3d1a6afSToby Isaac } 7149d3d1a6afSToby Isaac } 7150d3d1a6afSToby Isaac } 7151d3d1a6afSToby Isaac else { 7152d3d1a6afSToby Isaac /* copy this column as is */ 7153d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7154d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7155d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7156d3d1a6afSToby Isaac } 7157d3d1a6afSToby Isaac } 7158d3d1a6afSToby Isaac } 7159d3d1a6afSToby Isaac oldOff += dof; 7160d3d1a6afSToby Isaac } 7161d3d1a6afSToby Isaac } 7162d3d1a6afSToby Isaac 71636ecaa68aSToby Isaac if (multiplyLeft) { 71649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues)); 71659566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues,newNumIndices*newNumIndices)); 7166d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7167d3d1a6afSToby Isaac if (numFields) { 7168d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7169d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7170d3d1a6afSToby Isaac 7171d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7172d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7173d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7174d3d1a6afSToby Isaac PetscInt c, r, k; 7175d3d1a6afSToby Isaac PetscInt dof; 7176d3d1a6afSToby Isaac 71779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,b,f,&dof)); 7178d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7179d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7180d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7181d3d1a6afSToby Isaac 7182d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7183d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7184d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7185d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7186d3d1a6afSToby Isaac } 7187d3d1a6afSToby Isaac } 7188d3d1a6afSToby Isaac } 7189d3d1a6afSToby Isaac } 7190d3d1a6afSToby Isaac else { 7191d3d1a6afSToby Isaac /* copy this row as is */ 7192d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7193d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7194d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7195d3d1a6afSToby Isaac } 7196d3d1a6afSToby Isaac } 7197d3d1a6afSToby Isaac } 7198d3d1a6afSToby Isaac oldOff += dof; 7199d3d1a6afSToby Isaac } 7200d3d1a6afSToby Isaac } 7201d3d1a6afSToby Isaac } 7202d3d1a6afSToby Isaac else { 7203d3d1a6afSToby Isaac PetscInt oldOff = 0; 7204d3d1a6afSToby Isaac 7205d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7206d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7207d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7208d3d1a6afSToby Isaac PetscInt c, r, k; 7209d3d1a6afSToby Isaac PetscInt dof; 7210d3d1a6afSToby Isaac 72119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,b,&dof)); 7212d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7213d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7214d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7215d3d1a6afSToby Isaac 7216d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7217d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7218d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7219d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7220d3d1a6afSToby Isaac } 7221d3d1a6afSToby Isaac } 7222d3d1a6afSToby Isaac } 7223d3d1a6afSToby Isaac } 7224d3d1a6afSToby Isaac else { 7225d3d1a6afSToby Isaac /* copy this row as is */ 72269fc93327SToby Isaac for (r = 0; r < dof; r++) { 7227d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7228d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7229d3d1a6afSToby Isaac } 7230d3d1a6afSToby Isaac } 7231d3d1a6afSToby Isaac } 7232d3d1a6afSToby Isaac oldOff += dof; 7233d3d1a6afSToby Isaac } 7234d3d1a6afSToby Isaac } 7235d3d1a6afSToby Isaac 72369566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 72376ecaa68aSToby Isaac } 72386ecaa68aSToby Isaac else { 72396ecaa68aSToby Isaac newValues = tmpValues; 72406ecaa68aSToby Isaac } 72416ecaa68aSToby Isaac } 72426ecaa68aSToby Isaac 7243d3d1a6afSToby Isaac /* clean up */ 72449566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices)); 72459566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 72466ecaa68aSToby Isaac 7247d3d1a6afSToby Isaac if (numFields) { 7248d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 72499566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 72509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 72519566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 7252d3d1a6afSToby Isaac } 7253d3d1a6afSToby Isaac } 7254d3d1a6afSToby Isaac else { 72559566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 72569566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 72579566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0])); 7258d3d1a6afSToby Isaac } 72599566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 7260d3d1a6afSToby Isaac 7261d3d1a6afSToby Isaac /* output */ 72626ecaa68aSToby Isaac if (outPoints) { 7263d3d1a6afSToby Isaac *outPoints = newPoints; 72646ecaa68aSToby Isaac } 72656ecaa68aSToby Isaac else { 72669566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 72676ecaa68aSToby Isaac } 726831620726SToby Isaac if (outValues) { 7269d3d1a6afSToby Isaac *outValues = newValues; 72706ecaa68aSToby Isaac } 72716ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 7272d3d1a6afSToby Isaac offsets[f] = newOffsets[f]; 7273d3d1a6afSToby Isaac } 7274d3d1a6afSToby Isaac PetscFunctionReturn(0); 7275d3d1a6afSToby Isaac } 7276d3d1a6afSToby Isaac 72774a1e0b3eSMatthew G. Knepley /*@C 727871f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 72797cd05799SMatthew G. Knepley 72807cd05799SMatthew G. Knepley Not collective 72817cd05799SMatthew G. Knepley 72827cd05799SMatthew G. Knepley Input Parameters: 72837cd05799SMatthew G. Knepley + dm - The DM 728471f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 728571f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 728671f0bbf9SMatthew G. Knepley . point - The point defining the closure 728771f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 72887cd05799SMatthew G. Knepley 728971f0bbf9SMatthew G. Knepley Output Parameters: 729071f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 729171f0bbf9SMatthew G. Knepley . indices - The dof indices 729271f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 729371f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 72947cd05799SMatthew G. Knepley 729536fa2b79SJed Brown Notes: 729636fa2b79SJed Brown Must call DMPlexRestoreClosureIndices() to free allocated memory 729736fa2b79SJed Brown 729836fa2b79SJed Brown If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 729936fa2b79SJed Brown of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 730036fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 730136fa2b79SJed Brown indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 730236fa2b79SJed Brown indices (with the above semantics) are implied. 73037cd05799SMatthew G. Knepley 73047cd05799SMatthew G. Knepley Level: advanced 73057cd05799SMatthew G. Knepley 7306db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 73074a1e0b3eSMatthew G. Knepley @*/ 730871f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 730971f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 73107773e69fSMatthew G. Knepley { 731171f0bbf9SMatthew G. Knepley /* Closure ordering */ 73127773e69fSMatthew G. Knepley PetscSection clSection; 73137773e69fSMatthew G. Knepley IS clPoints; 731471f0bbf9SMatthew G. Knepley const PetscInt *clp; 731571f0bbf9SMatthew G. Knepley PetscInt *points; 731671f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 731771f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 73184acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 731971f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 732071f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 732171f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 732271f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 732371f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 732471f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 732571f0bbf9SMatthew G. Knepley 732671f0bbf9SMatthew G. Knepley PetscInt *idx; 732771f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 732871f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 73297773e69fSMatthew G. Knepley 733071f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 73317773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 73327773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 733336fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7334dadcf809SJacob Faibussowitsch if (numIndices) PetscValidIntPointer(numIndices, 6); 733571f0bbf9SMatthew G. Knepley if (indices) PetscValidPointer(indices, 7); 7336dadcf809SJacob Faibussowitsch if (outOffsets) PetscValidIntPointer(outOffsets, 8); 733771f0bbf9SMatthew G. Knepley if (values) PetscValidPointer(values, 9); 73389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 733963a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 73409566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 734171f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 73429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7343c459fbc1SJed Brown if (useClPerm) { 7344c459fbc1SJed Brown PetscInt depth, clsize; 73459566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7346c459fbc1SJed Brown for (clsize=0,p=0; p<Ncl; p++) { 7347c459fbc1SJed Brown PetscInt dof; 73489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2*p], &dof)); 7349c459fbc1SJed Brown clsize += dof; 7350c459fbc1SJed Brown } 73519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 7352c459fbc1SJed Brown } 735371f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 735471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl*2; p += 2) { 73557773e69fSMatthew G. Knepley PetscInt dof, fdof; 73567773e69fSMatthew G. Knepley 73579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 73587773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 73599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 73607773e69fSMatthew G. Knepley offsets[f+1] += fdof; 73617773e69fSMatthew G. Knepley } 736271f0bbf9SMatthew G. Knepley Ni += dof; 73637773e69fSMatthew G. Knepley } 73647773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 73651dca8a05SBarry 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); 736671f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 736771f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73689566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73699566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 737071f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 737171f0bbf9SMatthew G. Knepley if (values && flips[f]) { 737271f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 73736ecaa68aSToby Isaac 737471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 737571f0bbf9SMatthew G. Knepley PetscInt pnt = points[2*p], fdof; 737671f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 737771f0bbf9SMatthew G. Knepley 73789566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 73799566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 738071f0bbf9SMatthew G. Knepley if (flip) { 738171f0bbf9SMatthew G. Knepley PetscInt i, j, k; 738271f0bbf9SMatthew G. Knepley 738371f0bbf9SMatthew G. Knepley if (!valCopy) { 73849566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 738571f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 738671f0bbf9SMatthew G. Knepley *values = valCopy; 738771f0bbf9SMatthew G. Knepley } 738871f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 738971f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 739071f0bbf9SMatthew G. Knepley 739171f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 739271f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 739371f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 73946ecaa68aSToby Isaac } 73956ecaa68aSToby Isaac } 739671f0bbf9SMatthew G. Knepley } 739771f0bbf9SMatthew G. Knepley foffset += fdof; 739871f0bbf9SMatthew G. Knepley } 739971f0bbf9SMatthew G. Knepley } 740071f0bbf9SMatthew G. Knepley } 740171f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 74029566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 740371f0bbf9SMatthew G. Knepley if (NclC) { 74049566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 740571f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74069566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 74079566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 740871f0bbf9SMatthew G. Knepley } 740971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74109566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 74119566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 741271f0bbf9SMatthew G. Knepley } 74139566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 741471f0bbf9SMatthew G. Knepley Ncl = NclC; 741571f0bbf9SMatthew G. Knepley Ni = NiC; 741671f0bbf9SMatthew G. Knepley points = pointsC; 741771f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 741871f0bbf9SMatthew G. Knepley } 741971f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 74209566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 742171f0bbf9SMatthew G. Knepley if (Nf) { 742271f0bbf9SMatthew G. Knepley PetscInt idxOff; 742371f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 742471f0bbf9SMatthew G. Knepley 742571f0bbf9SMatthew G. Knepley if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 74269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 742771f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 742871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 742971f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 743071f0bbf9SMatthew G. Knepley 74319566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 74327773e69fSMatthew G. Knepley } 74337773e69fSMatthew G. Knepley } else { 743471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 743571f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 743671f0bbf9SMatthew G. Knepley 74379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 743871f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 743971f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 744071f0bbf9SMatthew G. Knepley * global section. */ 74419566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 744271f0bbf9SMatthew G. Knepley } 744371f0bbf9SMatthew G. Knepley } 744471f0bbf9SMatthew G. Knepley } else { 744571f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 744671f0bbf9SMatthew G. Knepley 744771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 744871f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 74494acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 74504acb8e1eSToby Isaac 74519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 745271f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 745371f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 74549566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 74557773e69fSMatthew G. Knepley } 74567773e69fSMatthew G. Knepley } 745771f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 745871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74599566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 74609566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 74614acb8e1eSToby Isaac } 746271f0bbf9SMatthew G. Knepley if (NclC) { 74639566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC)); 74647773e69fSMatthew G. Knepley } else { 74659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 74667773e69fSMatthew G. Knepley } 746771f0bbf9SMatthew G. Knepley 746871f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 746971f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 74707773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74717773e69fSMatthew G. Knepley } 74727773e69fSMatthew G. Knepley 74737cd05799SMatthew G. Knepley /*@C 747471f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 74757cd05799SMatthew G. Knepley 74767cd05799SMatthew G. Knepley Not collective 74777cd05799SMatthew G. Knepley 74787cd05799SMatthew G. Knepley Input Parameters: 74797cd05799SMatthew G. Knepley + dm - The DM 748071f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 748171f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 748271f0bbf9SMatthew G. Knepley . point - The point defining the closure 748371f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 748471f0bbf9SMatthew G. Knepley 748571f0bbf9SMatthew G. Knepley Output Parameters: 748671f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 748771f0bbf9SMatthew G. Knepley . indices - The dof indices 748871f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 748971f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 749071f0bbf9SMatthew G. Knepley 749171f0bbf9SMatthew G. Knepley Notes: 749271f0bbf9SMatthew G. Knepley If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 749371f0bbf9SMatthew G. Knepley 749471f0bbf9SMatthew G. Knepley If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 749571f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 749671f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 749771f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 749871f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 74997cd05799SMatthew G. Knepley 75007cd05799SMatthew G. Knepley Level: advanced 75017cd05799SMatthew G. Knepley 7502db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 75037cd05799SMatthew G. Knepley @*/ 750471f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 750571f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 75067773e69fSMatthew G. Knepley { 75077773e69fSMatthew G. Knepley PetscFunctionBegin; 75087773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7509064a246eSJacob Faibussowitsch PetscValidPointer(indices, 7); 75109566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 75117773e69fSMatthew G. Knepley PetscFunctionReturn(0); 75127773e69fSMatthew G. Knepley } 75137773e69fSMatthew G. Knepley 75147f5d1fdeSMatthew G. Knepley /*@C 75157f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 75167f5d1fdeSMatthew G. Knepley 75177f5d1fdeSMatthew G. Knepley Not collective 75187f5d1fdeSMatthew G. Knepley 75197f5d1fdeSMatthew G. Knepley Input Parameters: 75207f5d1fdeSMatthew G. Knepley + dm - The DM 7521ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section 7522ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section 75237f5d1fdeSMatthew G. Knepley . A - The matrix 7524eaf898f9SPatrick Sanan . point - The point in the DM 75257f5d1fdeSMatthew G. Knepley . values - The array of values 75267f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75277f5d1fdeSMatthew G. Knepley 75287f5d1fdeSMatthew G. Knepley Fortran Notes: 75297f5d1fdeSMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 75307f5d1fdeSMatthew G. Knepley 75317f5d1fdeSMatthew G. Knepley Level: intermediate 75327f5d1fdeSMatthew G. Knepley 7533db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 75347f5d1fdeSMatthew G. Knepley @*/ 75357c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7536552f7358SJed Brown { 7537552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7538552f7358SJed Brown PetscInt *indices; 753971f0bbf9SMatthew G. Knepley PetscInt numIndices; 754071f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 7541552f7358SJed Brown PetscErrorCode ierr; 7542552f7358SJed Brown 7543552f7358SJed Brown PetscFunctionBegin; 7544552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 75459566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 75463dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 75479566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 75483dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 75493dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7550552f7358SJed Brown 75519566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75520d644c17SKarl Rupp 75539566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 7554d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 75554a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7556552f7358SJed Brown if (ierr) { 7557552f7358SJed Brown PetscMPIInt rank; 7558552f7358SJed Brown 75599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 75609566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 75619566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 75629566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75639566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 7564c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7565552f7358SJed Brown } 75664a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 75674a1e0b3eSMatthew G. Knepley PetscInt i; 75689566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 756963a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 75709566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 75714a1e0b3eSMatthew G. Knepley } 757271f0bbf9SMatthew G. Knepley 75739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75749566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 757571f0bbf9SMatthew G. Knepley PetscFunctionReturn(0); 75764acb8e1eSToby Isaac } 757771f0bbf9SMatthew G. Knepley 75784a1e0b3eSMatthew G. Knepley /*@C 75794a1e0b3eSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 75804a1e0b3eSMatthew G. Knepley 75814a1e0b3eSMatthew G. Knepley Not collective 75824a1e0b3eSMatthew G. Knepley 75834a1e0b3eSMatthew G. Knepley Input Parameters: 75844a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields 75854a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 75864a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 75874a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields 75884a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 75894a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 75904a1e0b3eSMatthew G. Knepley . A - The matrix 75914a1e0b3eSMatthew G. Knepley . point - The point in the DMs 75924a1e0b3eSMatthew G. Knepley . values - The array of values 75934a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75944a1e0b3eSMatthew G. Knepley 75954a1e0b3eSMatthew G. Knepley Level: intermediate 75964a1e0b3eSMatthew G. Knepley 7597db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 75984a1e0b3eSMatthew G. Knepley @*/ 759971f0bbf9SMatthew 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) 760071f0bbf9SMatthew G. Knepley { 760171f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmRow->data; 760271f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 760371f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 760471f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 760571f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 760671f0bbf9SMatthew G. Knepley 760771f0bbf9SMatthew G. Knepley PetscFunctionBegin; 760871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 76099566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 761071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 76119566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 761271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 761371f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 76149566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 761571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 76169566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 761771f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 761871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 761971f0bbf9SMatthew G. Knepley 76209566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76219566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 762271f0bbf9SMatthew G. Knepley 76239566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 7624d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 76254a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 762671f0bbf9SMatthew G. Knepley if (ierr) { 762771f0bbf9SMatthew G. Knepley PetscMPIInt rank; 762871f0bbf9SMatthew G. Knepley 76299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 76309566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 76319566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 76329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76339566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values)); 76349566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7635d3d1a6afSToby Isaac } 763671f0bbf9SMatthew G. Knepley 76379566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 76399566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7640552f7358SJed Brown PetscFunctionReturn(0); 7641552f7358SJed Brown } 7642552f7358SJed Brown 7643de41b84cSMatthew 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) 7644de41b84cSMatthew G. Knepley { 7645de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmf->data; 7646de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 7647de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 7648de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 764917c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7650de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 7651412e9a14SMatthew G. Knepley DMPolytopeType ct; 76524ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7653de41b84cSMatthew G. Knepley PetscErrorCode ierr; 7654de41b84cSMatthew G. Knepley 7655de41b84cSMatthew G. Knepley PetscFunctionBegin; 7656de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7657de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 76589566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 7659de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 76609566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 7661de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 76629566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 7663de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 76649566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 7665de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7666de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 76679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 766863a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 76699566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 76709566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 7671de41b84cSMatthew G. Knepley /* Column indices */ 76729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 76734ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 7674de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 7675de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 76769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 7677de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7678de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7679de41b84cSMatthew G. Knepley cpoints[q*2] = cpoints[p]; 7680de41b84cSMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 7681de41b84cSMatthew G. Knepley ++q; 7682de41b84cSMatthew G. Knepley } 7683de41b84cSMatthew G. Knepley } 7684de41b84cSMatthew G. Knepley numCPoints = q; 7685de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7686de41b84cSMatthew G. Knepley PetscInt fdof; 7687de41b84cSMatthew G. Knepley 76889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 76894ca5e9f5SMatthew G. Knepley if (!dof) continue; 7690de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 76919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 7692de41b84cSMatthew G. Knepley coffsets[f+1] += fdof; 7693de41b84cSMatthew G. Knepley } 7694de41b84cSMatthew G. Knepley numCIndices += dof; 7695de41b84cSMatthew G. Knepley } 7696de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7697de41b84cSMatthew G. Knepley /* Row indices */ 76989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7699412e9a14SMatthew G. Knepley { 7700012bc364SMatthew G. Knepley DMPlexTransform tr; 7701012bc364SMatthew G. Knepley DMPolytopeType *rct; 7702012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7703012bc364SMatthew G. Knepley 77049566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 77059566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 77069566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7707012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 77089566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7709412e9a14SMatthew G. Knepley } 77109566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 7711de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 7712de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 77139566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 7714de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 77159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 7716de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 7717de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 77189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 77194ca5e9f5SMatthew G. Knepley if (!dof) continue; 77204ca5e9f5SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 77214ca5e9f5SMatthew G. Knepley if (s < q) continue; 7722de41b84cSMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 7723de41b84cSMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 7724de41b84cSMatthew G. Knepley ++q; 7725de41b84cSMatthew G. Knepley } 7726de41b84cSMatthew G. Knepley } 77279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 7728de41b84cSMatthew G. Knepley } 7729de41b84cSMatthew G. Knepley numFPoints = q; 7730de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7731de41b84cSMatthew G. Knepley PetscInt fdof; 7732de41b84cSMatthew G. Knepley 77339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 77344ca5e9f5SMatthew G. Knepley if (!dof) continue; 7735de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 77369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 7737de41b84cSMatthew G. Knepley foffsets[f+1] += fdof; 7738de41b84cSMatthew G. Knepley } 7739de41b84cSMatthew G. Knepley numFIndices += dof; 7740de41b84cSMatthew G. Knepley } 7741de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7742de41b84cSMatthew G. Knepley 77431dca8a05SBarry 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); 77441dca8a05SBarry 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); 77459566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77469566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7747de41b84cSMatthew G. Knepley if (numFields) { 77484acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 77494acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 77504acb8e1eSToby Isaac 77514acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7754de41b84cSMatthew G. Knepley } 77554acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 77569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77579566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 77584acb8e1eSToby Isaac } 77594acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 77609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77619566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 77624acb8e1eSToby Isaac } 77634acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77649566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77659566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7766de41b84cSMatthew G. Knepley } 7767de41b84cSMatthew G. Knepley } else { 77684acb8e1eSToby Isaac const PetscInt **permsF = NULL; 77694acb8e1eSToby Isaac const PetscInt **permsC = NULL; 77704acb8e1eSToby Isaac 77719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 77734acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 77744acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 77754acb8e1eSToby Isaac 77769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77779566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 7778de41b84cSMatthew G. Knepley } 77794acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 77804acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 77814acb8e1eSToby Isaac 77829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77839566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 7784de41b84cSMatthew G. Knepley } 77859566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77869566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 7787de41b84cSMatthew G. Knepley } 77889566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77894acb8e1eSToby Isaac /* TODO: flips */ 7790d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 7791de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7792de41b84cSMatthew G. Knepley if (ierr) { 7793de41b84cSMatthew G. Knepley PetscMPIInt rank; 7794de41b84cSMatthew G. Knepley 77959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 77969566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 77979566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77989566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7800de41b84cSMatthew G. Knepley } 78019566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 78029566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78039566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 78049566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7805de41b84cSMatthew G. Knepley PetscFunctionReturn(0); 7806de41b84cSMatthew G. Knepley } 7807de41b84cSMatthew G. Knepley 78087c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 78097c927364SMatthew G. Knepley { 78107c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 78117c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 78127c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 781317c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7814412e9a14SMatthew G. Knepley DMPolytopeType ct; 78157c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 78167c927364SMatthew G. Knepley 78177c927364SMatthew G. Knepley PetscFunctionBegin; 78187c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 78197c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 78209566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 78217c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 78229566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 78237c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 78249566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 78257c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 78269566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 78277c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 78289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 782963a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 78309566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 78319566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 78327c927364SMatthew G. Knepley /* Column indices */ 78339566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78347c927364SMatthew G. Knepley maxFPoints = numCPoints; 78357c927364SMatthew G. Knepley /* Compress out points not in the section */ 78367c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 78379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 78387c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 78397c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 78407c927364SMatthew G. Knepley cpoints[q*2] = cpoints[p]; 78417c927364SMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 78427c927364SMatthew G. Knepley ++q; 78437c927364SMatthew G. Knepley } 78447c927364SMatthew G. Knepley } 78457c927364SMatthew G. Knepley numCPoints = q; 78467c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 78477c927364SMatthew G. Knepley PetscInt fdof; 78487c927364SMatthew G. Knepley 78499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 78507c927364SMatthew G. Knepley if (!dof) continue; 78517c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 78537c927364SMatthew G. Knepley coffsets[f+1] += fdof; 78547c927364SMatthew G. Knepley } 78557c927364SMatthew G. Knepley numCIndices += dof; 78567c927364SMatthew G. Knepley } 78577c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 78587c927364SMatthew G. Knepley /* Row indices */ 78599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 7860412e9a14SMatthew G. Knepley { 7861012bc364SMatthew G. Knepley DMPlexTransform tr; 7862012bc364SMatthew G. Knepley DMPolytopeType *rct; 7863012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7864012bc364SMatthew G. Knepley 78659566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 78669566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 78679566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7868012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 78699566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 7870412e9a14SMatthew G. Knepley } 78719566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 78727c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 78737c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 78749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 78757c927364SMatthew G. Knepley /* Compress out points not in the section */ 78769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 78777c927364SMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 78787c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 78799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 78807c927364SMatthew G. Knepley if (!dof) continue; 78817c927364SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 78827c927364SMatthew G. Knepley if (s < q) continue; 78837c927364SMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 78847c927364SMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 78857c927364SMatthew G. Knepley ++q; 78867c927364SMatthew G. Knepley } 78877c927364SMatthew G. Knepley } 78889566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 78897c927364SMatthew G. Knepley } 78907c927364SMatthew G. Knepley numFPoints = q; 78917c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 78927c927364SMatthew G. Knepley PetscInt fdof; 78937c927364SMatthew G. Knepley 78949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 78957c927364SMatthew G. Knepley if (!dof) continue; 78967c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 78987c927364SMatthew G. Knepley foffsets[f+1] += fdof; 78997c927364SMatthew G. Knepley } 79007c927364SMatthew G. Knepley numFIndices += dof; 79017c927364SMatthew G. Knepley } 79027c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 79037c927364SMatthew G. Knepley 79041dca8a05SBarry 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); 79051dca8a05SBarry 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); 79067c927364SMatthew G. Knepley if (numFields) { 79074acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 79084acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 79094acb8e1eSToby Isaac 79104acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 79119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 79129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 79137c927364SMatthew G. Knepley } 79144acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 79159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 79169566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 79174acb8e1eSToby Isaac } 79184acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 79199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79209566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 79214acb8e1eSToby Isaac } 79224acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 79239566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 79249566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 79257c927364SMatthew G. Knepley } 79267c927364SMatthew G. Knepley } else { 79274acb8e1eSToby Isaac const PetscInt **permsF = NULL; 79284acb8e1eSToby Isaac const PetscInt **permsC = NULL; 79294acb8e1eSToby Isaac 79309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79324acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 79334acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 79344acb8e1eSToby Isaac 79359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 79369566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 79377c927364SMatthew G. Knepley } 79384acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 79394acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 79404acb8e1eSToby Isaac 79419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79429566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 79437c927364SMatthew G. Knepley } 79449566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79459566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79467c927364SMatthew G. Knepley } 79479566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 79489566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 79497c927364SMatthew G. Knepley PetscFunctionReturn(0); 79507c927364SMatthew G. Knepley } 79517c927364SMatthew G. Knepley 79527cd05799SMatthew G. Knepley /*@C 79537cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 79547cd05799SMatthew G. Knepley 79557cd05799SMatthew G. Knepley Input Parameter: 79567cd05799SMatthew G. Knepley . dm - The DMPlex object 79577cd05799SMatthew G. Knepley 79587cd05799SMatthew G. Knepley Output Parameter: 79597cd05799SMatthew G. Knepley . cellHeight - The height of a cell 79607cd05799SMatthew G. Knepley 79617cd05799SMatthew G. Knepley Level: developer 79627cd05799SMatthew G. Knepley 7963db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()` 79647cd05799SMatthew G. Knepley @*/ 7965552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7966552f7358SJed Brown { 7967552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7968552f7358SJed Brown 7969552f7358SJed Brown PetscFunctionBegin; 7970552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7971dadcf809SJacob Faibussowitsch PetscValidIntPointer(cellHeight, 2); 7972552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 7973552f7358SJed Brown PetscFunctionReturn(0); 7974552f7358SJed Brown } 7975552f7358SJed Brown 79767cd05799SMatthew G. Knepley /*@C 79777cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 79787cd05799SMatthew G. Knepley 79797cd05799SMatthew G. Knepley Input Parameters: 79807cd05799SMatthew G. Knepley + dm - The DMPlex object 79817cd05799SMatthew G. Knepley - cellHeight - The height of a cell 79827cd05799SMatthew G. Knepley 79837cd05799SMatthew G. Knepley Level: developer 79847cd05799SMatthew G. Knepley 7985db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()` 79867cd05799SMatthew G. Knepley @*/ 7987552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7988552f7358SJed Brown { 7989552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7990552f7358SJed Brown 7991552f7358SJed Brown PetscFunctionBegin; 7992552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7993552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 7994552f7358SJed Brown PetscFunctionReturn(0); 7995552f7358SJed Brown } 7996552f7358SJed Brown 7997e6139122SMatthew G. Knepley /*@ 7998e6139122SMatthew G. Knepley DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7999e6139122SMatthew G. Knepley 8000e6139122SMatthew G. Knepley Input Parameter: 8001e6139122SMatthew G. Knepley . dm - The DMPlex object 8002e6139122SMatthew G. Knepley 8003e6139122SMatthew G. Knepley Output Parameters: 80042a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL 80052a9f31c0SMatthew G. Knepley - gcEnd - The upper bound on ghost cells, or NULL 8006e6139122SMatthew G. Knepley 80072a9f31c0SMatthew G. Knepley Level: advanced 8008e6139122SMatthew G. Knepley 8009db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()` 8010e6139122SMatthew G. Knepley @*/ 8011e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 8012e6139122SMatthew G. Knepley { 8013412e9a14SMatthew G. Knepley DMLabel ctLabel; 8014e6139122SMatthew G. Knepley 8015e6139122SMatthew G. Knepley PetscFunctionBegin; 8016e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 80189566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd)); 8019e6139122SMatthew G. Knepley PetscFunctionReturn(0); 8020e6139122SMatthew G. Knepley } 8021e6139122SMatthew G. Knepley 80229886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8023552f7358SJed Brown { 8024552f7358SJed Brown PetscSection section, globalSection; 8025552f7358SJed Brown PetscInt *numbers, p; 8026552f7358SJed Brown 8027552f7358SJed Brown PetscFunctionBegin; 80286c1ef331SVaclav Hapla if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf)); 80299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 80309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8031552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, 1)); 8033552f7358SJed Brown } 80349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 80359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 80369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8037552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart])); 8039ef48cebcSMatthew G. Knepley if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8040ef48cebcSMatthew G. Knepley else numbers[p-pStart] += shift; 8041552f7358SJed Brown } 80429566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8043ef48cebcSMatthew G. Knepley if (globalSize) { 8044ef48cebcSMatthew G. Knepley PetscLayout layout; 80459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout)); 80469566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 80479566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8048ef48cebcSMatthew G. Knepley } 80499566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 80509566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 8051552f7358SJed Brown PetscFunctionReturn(0); 8052552f7358SJed Brown } 8053552f7358SJed Brown 805481ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8055552f7358SJed Brown { 8056412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8057552f7358SJed Brown 8058552f7358SJed Brown PetscFunctionBegin; 80599566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 80609566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 80619566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 80629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 806381ed3555SMatthew G. Knepley PetscFunctionReturn(0); 8064552f7358SJed Brown } 806581ed3555SMatthew G. Knepley 80668dab3259SMatthew G. Knepley /*@ 80677cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 80687cd05799SMatthew G. Knepley 80697cd05799SMatthew G. Knepley Input Parameter: 80707cd05799SMatthew G. Knepley . dm - The DMPlex object 80717cd05799SMatthew G. Knepley 80727cd05799SMatthew G. Knepley Output Parameter: 80737cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 80747cd05799SMatthew G. Knepley 80757cd05799SMatthew G. Knepley Level: developer 80767cd05799SMatthew G. Knepley 8077db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()` 80787cd05799SMatthew G. Knepley @*/ 807981ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 808081ed3555SMatthew G. Knepley { 808181ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 808281ed3555SMatthew G. Knepley 808381ed3555SMatthew G. Knepley PetscFunctionBegin; 808481ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80859566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8086552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 8087552f7358SJed Brown PetscFunctionReturn(0); 8088552f7358SJed Brown } 8089552f7358SJed Brown 809081ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 809181ed3555SMatthew G. Knepley { 8092412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 809381ed3555SMatthew G. Knepley 809481ed3555SMatthew G. Knepley PetscFunctionBegin; 809581ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 80979566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 809881ed3555SMatthew G. Knepley PetscFunctionReturn(0); 809981ed3555SMatthew G. Knepley } 810081ed3555SMatthew G. Knepley 81018dab3259SMatthew G. Knepley /*@ 81026aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 81037cd05799SMatthew G. Knepley 81047cd05799SMatthew G. Knepley Input Parameter: 81057cd05799SMatthew G. Knepley . dm - The DMPlex object 81067cd05799SMatthew G. Knepley 81077cd05799SMatthew G. Knepley Output Parameter: 81087cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 81097cd05799SMatthew G. Knepley 81107cd05799SMatthew G. Knepley Level: developer 81117cd05799SMatthew G. Knepley 8112db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 81137cd05799SMatthew G. Knepley @*/ 8114552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8115552f7358SJed Brown { 8116552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 8117552f7358SJed Brown 8118552f7358SJed Brown PetscFunctionBegin; 8119552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81209566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8121552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 8122552f7358SJed Brown PetscFunctionReturn(0); 8123552f7358SJed Brown } 8124552f7358SJed Brown 81258dab3259SMatthew G. Knepley /*@ 81267cd05799SMatthew G. Knepley DMPlexCreatePointNumbering - Create a global numbering for all points on this process 81277cd05799SMatthew G. Knepley 81287cd05799SMatthew G. Knepley Input Parameter: 81297cd05799SMatthew G. Knepley . dm - The DMPlex object 81307cd05799SMatthew G. Knepley 81317cd05799SMatthew G. Knepley Output Parameter: 81327cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 81337cd05799SMatthew G. Knepley 81347cd05799SMatthew G. Knepley Level: developer 81357cd05799SMatthew G. Knepley 8136db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()` 81377cd05799SMatthew G. Knepley @*/ 8138ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8139ef48cebcSMatthew G. Knepley { 8140ef48cebcSMatthew G. Knepley IS nums[4]; 8141862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8142ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 8143ef48cebcSMatthew G. Knepley 8144ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8145ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 81478abc87a0SMichael Lange /* For unstratified meshes use dim instead of depth */ 81489566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 8149862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8150862913ffSStefano Zampini PetscInt end; 8151862913ffSStefano Zampini 8152862913ffSStefano Zampini depths[d] = depth-d; 81539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 8154862913ffSStefano Zampini if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8155862913ffSStefano Zampini } 81569566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(depth+1, starts, depths)); 81571c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm))); 8158862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 81591dca8a05SBarry 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]); 8160862913ffSStefano Zampini } 8161ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8162ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8163ef48cebcSMatthew G. Knepley 81649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 81659566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8166ef48cebcSMatthew G. Knepley shift += gsize; 8167ef48cebcSMatthew G. Knepley } 81689566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers)); 81699566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 8170ef48cebcSMatthew G. Knepley PetscFunctionReturn(0); 8171ef48cebcSMatthew G. Knepley } 8172ef48cebcSMatthew G. Knepley 817308a22f4bSMatthew G. Knepley /*@ 817408a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 817508a22f4bSMatthew G. Knepley 817608a22f4bSMatthew G. Knepley Input Parameter: 817708a22f4bSMatthew G. Knepley . dm - The DMPlex object 817808a22f4bSMatthew G. Knepley 817908a22f4bSMatthew G. Knepley Output Parameter: 818008a22f4bSMatthew G. Knepley . ranks - The rank field 818108a22f4bSMatthew G. Knepley 818208a22f4bSMatthew G. Knepley Options Database Keys: 818308a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 818408a22f4bSMatthew G. Knepley 818508a22f4bSMatthew G. Knepley Level: intermediate 818608a22f4bSMatthew G. Knepley 8187db781477SPatrick Sanan .seealso: `DMView()` 818808a22f4bSMatthew G. Knepley @*/ 818908a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 819008a22f4bSMatthew G. Knepley { 819108a22f4bSMatthew G. Knepley DM rdm; 819208a22f4bSMatthew G. Knepley PetscFE fe; 819308a22f4bSMatthew G. Knepley PetscScalar *r; 819408a22f4bSMatthew G. Knepley PetscMPIInt rank; 8195a55f9a55SMatthew G. Knepley DMPolytopeType ct; 819608a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8197a55f9a55SMatthew G. Knepley PetscBool simplex; 819808a22f4bSMatthew G. Knepley 819908a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8200f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8201f95ace6aSMatthew G. Knepley PetscValidPointer(ranks, 2); 82029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 82039566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 82049566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 82059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8207a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 82089566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 82099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) fe, "rank")); 82109566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 82119566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 82129566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 82139566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 82149566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *ranks, "partition")); 82159566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 821608a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 821708a22f4bSMatthew G. Knepley PetscScalar *lr; 821808a22f4bSMatthew G. Knepley 82199566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 822071f09efeSPierre Jolivet if (lr) *lr = rank; 822108a22f4bSMatthew G. Knepley } 82229566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 82239566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 822408a22f4bSMatthew G. Knepley PetscFunctionReturn(0); 822508a22f4bSMatthew G. Knepley } 822608a22f4bSMatthew G. Knepley 8227ca8062c8SMatthew G. Knepley /*@ 822818e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 822918e14f0cSMatthew G. Knepley 823018e14f0cSMatthew G. Knepley Input Parameters: 823118e14f0cSMatthew G. Knepley + dm - The DMPlex 823218e14f0cSMatthew G. Knepley - label - The DMLabel 823318e14f0cSMatthew G. Knepley 823418e14f0cSMatthew G. Knepley Output Parameter: 823518e14f0cSMatthew G. Knepley . val - The label value field 823618e14f0cSMatthew G. Knepley 823718e14f0cSMatthew G. Knepley Options Database Keys: 823818e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 823918e14f0cSMatthew G. Knepley 824018e14f0cSMatthew G. Knepley Level: intermediate 824118e14f0cSMatthew G. Knepley 8242db781477SPatrick Sanan .seealso: `DMView()` 824318e14f0cSMatthew G. Knepley @*/ 824418e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 824518e14f0cSMatthew G. Knepley { 824618e14f0cSMatthew G. Knepley DM rdm; 824718e14f0cSMatthew G. Knepley PetscFE fe; 824818e14f0cSMatthew G. Knepley PetscScalar *v; 824918e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 825018e14f0cSMatthew G. Knepley 825118e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 825218e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 825318e14f0cSMatthew G. Knepley PetscValidPointer(label, 2); 825418e14f0cSMatthew G. Knepley PetscValidPointer(val, 3); 82559566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 82569566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 82579566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 82589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) fe, "label_value")); 82599566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 82609566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 82619566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 82629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82639566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 82649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *val, "label_value")); 82659566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 826618e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 826718e14f0cSMatthew G. Knepley PetscScalar *lv; 826818e14f0cSMatthew G. Knepley PetscInt cval; 826918e14f0cSMatthew G. Knepley 82709566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 82719566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 827218e14f0cSMatthew G. Knepley *lv = cval; 827318e14f0cSMatthew G. Knepley } 82749566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 82759566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 827618e14f0cSMatthew G. Knepley PetscFunctionReturn(0); 827718e14f0cSMatthew G. Knepley } 827818e14f0cSMatthew G. Knepley 827918e14f0cSMatthew G. Knepley /*@ 8280ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8281ca8062c8SMatthew G. Knepley 828269916449SMatthew G. Knepley Input Parameter: 828369916449SMatthew G. Knepley . dm - The DMPlex object 8284ca8062c8SMatthew G. Knepley 828595eb5ee5SVaclav Hapla Notes: 828695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 828795eb5ee5SVaclav Hapla 828895eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8289ca8062c8SMatthew G. Knepley 8290ca8062c8SMatthew G. Knepley Level: developer 8291ca8062c8SMatthew G. Knepley 8292db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8293ca8062c8SMatthew G. Knepley @*/ 8294ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm) 8295ca8062c8SMatthew G. Knepley { 8296ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8297ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8298ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 829957beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 830057beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8301ca8062c8SMatthew G. Knepley 8302ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8303ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 83049566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 83059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 83069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8307ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 83089566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8309ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 83109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 83119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8312ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 831342e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 831442e66dfaSMatthew G. Knepley PetscInt d; 831542e66dfaSMatthew G. Knepley for (d = c-1; d >= 0; --d) { 831642e66dfaSMatthew G. Knepley if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 831742e66dfaSMatthew G. Knepley } 83189566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 83199566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8320ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8321ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8322ca8062c8SMatthew G. Knepley } 832342e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s+1] != p))) { 832463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 8325ca8062c8SMatthew G. Knepley for (s = 0; s < coneSize; ++s) { 832663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 8327ca8062c8SMatthew G. Knepley } 83289566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 832963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 8330ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 833163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 8332ca8062c8SMatthew G. Knepley } 83339566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 833463a3b9bcSJacob 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]); 833563a3b9bcSJacob Faibussowitsch else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8336ca8062c8SMatthew G. Knepley } 833742e66dfaSMatthew G. Knepley } 83389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 833957beb4faSStefano Zampini if (p != pp) { storagecheck = PETSC_FALSE; continue; } 83409566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 83419566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8342ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 83439566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 83449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8345ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 83469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 834757beb4faSStefano Zampini if (cone[c] != pp) { c = 0; break; } 8348ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8349ca8062c8SMatthew G. Knepley } 8350ca8062c8SMatthew G. Knepley if (c >= coneSize) { 835163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 8352ca8062c8SMatthew G. Knepley for (c = 0; c < supportSize; ++c) { 835363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 8354ca8062c8SMatthew G. Knepley } 83559566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 835663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 8357ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 835863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 8359ca8062c8SMatthew G. Knepley } 83609566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 836163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8362ca8062c8SMatthew G. Knepley } 8363ca8062c8SMatthew G. Knepley } 8364ca8062c8SMatthew G. Knepley } 836557beb4faSStefano Zampini if (storagecheck) { 83669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 83679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 836863a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 836957beb4faSStefano Zampini } 8370ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8371ca8062c8SMatthew G. Knepley } 8372ca8062c8SMatthew G. Knepley 8373412e9a14SMatthew G. Knepley /* 8374412e9a14SMatthew 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. 8375412e9a14SMatthew G. Knepley */ 8376412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8377412e9a14SMatthew G. Knepley { 8378412e9a14SMatthew G. Knepley DMPolytopeType cct; 8379412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8380412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8381412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8382412e9a14SMatthew G. Knepley 8383412e9a14SMatthew G. Knepley PetscFunctionBegin; 8384412e9a14SMatthew G. Knepley *unsplit = 0; 8385412e9a14SMatthew G. Knepley switch (ct) { 8386b5a892a1SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 8387b5a892a1SMatthew G. Knepley ptpoints[npt++] = c; 8388b5a892a1SMatthew G. Knepley break; 8389412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 83909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 83919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8392412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 8394412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8395412e9a14SMatthew G. Knepley } 8396412e9a14SMatthew G. Knepley break; 8397412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8398412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 83999566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 84009566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8401412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 84029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 84039566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8404412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 84059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8406412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8407412e9a14SMatthew G. Knepley PetscInt p; 8408412e9a14SMatthew G. Knepley for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8409412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8410412e9a14SMatthew G. Knepley } 8411412e9a14SMatthew G. Knepley } 8412412e9a14SMatthew G. Knepley } 8413412e9a14SMatthew G. Knepley break; 8414412e9a14SMatthew G. Knepley default: break; 8415412e9a14SMatthew G. Knepley } 8416412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 84179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8418412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8419412e9a14SMatthew G. Knepley } 8420412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 8421412e9a14SMatthew G. Knepley } 8422412e9a14SMatthew G. Knepley 8423ca8062c8SMatthew G. Knepley /*@ 8424ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8425ca8062c8SMatthew G. Knepley 8426ca8062c8SMatthew G. Knepley Input Parameters: 8427ca8062c8SMatthew G. Knepley + dm - The DMPlex object 842858723a97SMatthew G. Knepley - cellHeight - Normally 0 8429ca8062c8SMatthew G. Knepley 843095eb5ee5SVaclav Hapla Notes: 843195eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 843225c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 8433ca8062c8SMatthew G. Knepley 843495eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 843595eb5ee5SVaclav Hapla 8436ca8062c8SMatthew G. Knepley Level: developer 8437ca8062c8SMatthew G. Knepley 8438db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8439ca8062c8SMatthew G. Knepley @*/ 844025c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8441ca8062c8SMatthew G. Knepley { 8442412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 8443412e9a14SMatthew G. Knepley DMPolytopeType ct; 8444412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 8445ca8062c8SMatthew G. Knepley 8446ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8447ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84489566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 84499566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 84509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8451412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8452412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 8453412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 845458723a97SMatthew G. Knepley 84559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 845663a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt) ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 8457412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 8458412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 84599566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 846063a3b9bcSJacob 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)); 8461412e9a14SMatthew G. Knepley } 84629566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 846358723a97SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 846458723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 8465412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 846658723a97SMatthew G. Knepley } 84679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8468412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 8469412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8470412e9a14SMatthew G. Knepley PetscInt unsplit; 847142363296SMatthew G. Knepley 84729566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8473412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 847442363296SMatthew G. Knepley } 847563a3b9bcSJacob 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)); 847642363296SMatthew G. Knepley } 8477ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8478ca8062c8SMatthew G. Knepley } 84799bf0dad6SMatthew G. Knepley 84809bf0dad6SMatthew G. Knepley /*@ 84819bf0dad6SMatthew 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 84829bf0dad6SMatthew G. Knepley 84838f6815adSVaclav Hapla Collective 8484899ea2b8SJacob Faibussowitsch 84859bf0dad6SMatthew G. Knepley Input Parameters: 84869bf0dad6SMatthew G. Knepley + dm - The DMPlex object 84879bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 84889bf0dad6SMatthew G. Knepley 848945da879fSVaclav Hapla Notes: 849045da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 849145da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 849245da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 849345da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 84949bf0dad6SMatthew G. Knepley 849595eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 849695eb5ee5SVaclav Hapla 84979bf0dad6SMatthew G. Knepley Level: developer 84989bf0dad6SMatthew G. Knepley 8499db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 85009bf0dad6SMatthew G. Knepley @*/ 850125c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 85029bf0dad6SMatthew G. Knepley { 8503ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8504899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 85059bf0dad6SMatthew G. Knepley 85069bf0dad6SMatthew G. Knepley PetscFunctionBegin; 85079bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85088f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 850945da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 85108f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 85118f6815adSVaclav Hapla PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"); 85128f6815adSVaclav Hapla PetscFunctionReturn(0); 8513899ea2b8SJacob Faibussowitsch } 8514899ea2b8SJacob Faibussowitsch 85159566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 85169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 85179566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8518ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 85199566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 85203554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8521412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 8522412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 8523ba2698f1SMatthew G. Knepley DMPolytopeType ct; 8524412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 8525412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 85269bf0dad6SMatthew G. Knepley 85279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 85289566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8529412e9a14SMatthew G. Knepley if (unsplit) continue; 85309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 85319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 85329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 85339566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85349bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 85359bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 85369bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 85379bf0dad6SMatthew G. Knepley } 85389566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 853963a3b9bcSJacob 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); 85409bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 8541d4961f80SStefano Zampini DMPolytopeType fct; 85429bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 85439bf0dad6SMatthew G. Knepley 85449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 85459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 85469bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize*2; cl += 2) { 85479bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 85489bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 85499bf0dad6SMatthew G. Knepley } 855063a3b9bcSJacob 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]); 85519bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 8552b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff+v]) { 8553b5a892a1SMatthew G. Knepley PetscInt v1; 8554b5a892a1SMatthew G. Knepley 85559566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 855663a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 85579566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 855863a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff+v1])); 85599566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 856063a3b9bcSJacob 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]); 8561b5a892a1SMatthew G. Knepley } 85629bf0dad6SMatthew G. Knepley } 85639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 8564412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 85659bf0dad6SMatthew G. Knepley } 85669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 85679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85689bf0dad6SMatthew G. Knepley } 85693554e41dSMatthew G. Knepley } 8570552f7358SJed Brown PetscFunctionReturn(0); 8571552f7358SJed Brown } 85723913d7c8SMatthew G. Knepley 8573bb6a34a8SMatthew G. Knepley /*@ 8574bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 8575bb6a34a8SMatthew G. Knepley 8576bb6a34a8SMatthew G. Knepley Input Parameter: 8577bb6a34a8SMatthew G. Knepley . dm - The DMPlex object 8578bb6a34a8SMatthew G. Knepley 857995eb5ee5SVaclav Hapla Notes: 858095eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 858195eb5ee5SVaclav Hapla 858295eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8583bb6a34a8SMatthew G. Knepley 8584bb6a34a8SMatthew G. Knepley Level: developer 8585bb6a34a8SMatthew G. Knepley 8586db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()` 8587bb6a34a8SMatthew G. Knepley @*/ 8588bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm) 8589bb6a34a8SMatthew G. Knepley { 8590a2a9e04cSMatthew G. Knepley Vec coordinates; 8591bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 8592bb6a34a8SMatthew G. Knepley PetscReal vol; 8593412e9a14SMatthew G. Knepley PetscBool periodic; 859451a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 8595bb6a34a8SMatthew G. Knepley 8596bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 85979566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 85989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 859951a74b61SMatthew G. Knepley if (dim != dE) PetscFunctionReturn(0); 86009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 86019566063dSJacob Faibussowitsch PetscCall(DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL)); 8602bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 86039566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8604a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 86059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8606412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8607412e9a14SMatthew G. Knepley DMPolytopeType ct; 8608412e9a14SMatthew G. Knepley PetscInt unsplit; 8609412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 8610412e9a14SMatthew G. Knepley 86119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 8612412e9a14SMatthew G. Knepley switch (ct) { 8613412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 8614412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8615412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8616412e9a14SMatthew G. Knepley ignoreZeroVol = PETSC_TRUE; break; 8617412e9a14SMatthew G. Knepley default: break; 8618412e9a14SMatthew G. Knepley } 8619412e9a14SMatthew G. Knepley switch (ct) { 8620412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 8621412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8622412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8623a2a9e04cSMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 8624412e9a14SMatthew G. Knepley continue; 8625412e9a14SMatthew G. Knepley default: break; 8626412e9a14SMatthew G. Knepley } 86279566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8628412e9a14SMatthew G. Knepley if (unsplit) continue; 86299566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 86301dca8a05SBarry 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); 863163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ*refVol))); 8632412e9a14SMatthew G. Knepley if (depth > 1 && !periodic) { 86339566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 86341dca8a05SBarry Smith PetscCheck(vol >= -PETSC_SMALL && (vol > 0.0 || ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double) vol); 863563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double) vol)); 8636bb6a34a8SMatthew G. Knepley } 8637bb6a34a8SMatthew G. Knepley } 8638bb6a34a8SMatthew G. Knepley PetscFunctionReturn(0); 8639bb6a34a8SMatthew G. Knepley } 8640bb6a34a8SMatthew G. Knepley 864103da9461SVaclav Hapla /*@ 86427726db96SVaclav Hapla DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex. 86437726db96SVaclav Hapla 86447726db96SVaclav Hapla Collective 864503da9461SVaclav Hapla 864603da9461SVaclav Hapla Input Parameters: 86477726db96SVaclav Hapla + dm - The DMPlex object 86487726db96SVaclav Hapla - pointSF - The Point SF, or NULL for Point SF attached to DM 864903da9461SVaclav Hapla 8650e83a0d2dSVaclav Hapla Notes: 8651e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 865203da9461SVaclav Hapla 865395eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 865495eb5ee5SVaclav Hapla 865503da9461SVaclav Hapla Level: developer 865603da9461SVaclav Hapla 8657db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()` 865803da9461SVaclav Hapla @*/ 86597726db96SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF) 866003da9461SVaclav Hapla { 86617726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 86627726db96SVaclav Hapla const PetscInt *locals; 86637726db96SVaclav Hapla const PetscSFNode *remotes; 8664f0cfc026SVaclav Hapla PetscBool distributed; 86657726db96SVaclav Hapla MPI_Comm comm; 86667726db96SVaclav Hapla PetscMPIInt rank; 866703da9461SVaclav Hapla 866803da9461SVaclav Hapla PetscFunctionBegin; 866903da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86707726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 86717726db96SVaclav Hapla else pointSF = dm->sf; 86727726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 86737726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 86747726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 86757726db96SVaclav Hapla { 86767726db96SVaclav Hapla PetscMPIInt mpiFlag; 86777726db96SVaclav Hapla 86787726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF),&mpiFlag)); 86797726db96SVaclav Hapla PetscCheck(mpiFlag == MPI_CONGRUENT || mpiFlag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "DM and Point SF have different communicators (flag %d)",mpiFlag); 86807726db96SVaclav Hapla } 86817726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 86829566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 86837726db96SVaclav Hapla if (!distributed) { 86847726db96SVaclav Hapla PetscCheck(nroots < 0 || nleaves == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Undistributed DMPlex cannot have non-empty PointSF (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves); 86858918e3e2SVaclav Hapla PetscFunctionReturn(0); 86868918e3e2SVaclav Hapla } 86877726db96SVaclav Hapla PetscCheck(nroots >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves); 86887726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 868903da9461SVaclav Hapla 86907726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 86917726db96SVaclav Hapla { 86927726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 86937726db96SVaclav Hapla 86947726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86957726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 86967726db96SVaclav Hapla PetscCheck(pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd-pStart, nroots); 86977726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 86987726db96SVaclav Hapla } 86997726db96SVaclav Hapla 87007726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 87017726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 87027726db96SVaclav Hapla PetscAssert(remotes[l].rank != (PetscInt) rank, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains local point %" PetscInt_FMT " <- (%" PetscInt_FMT ",%" PetscInt_FMT ")", locals ? locals[l] : l, remotes[l].rank, remotes[l].index); 87037726db96SVaclav Hapla } 87047726db96SVaclav Hapla 87057726db96SVaclav Hapla /* Check there are no cells in interface */ 87067726db96SVaclav Hapla if (!overlap) { 87077726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 87087726db96SVaclav Hapla 87099566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 8711f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 87127726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 8713f5869d18SMatthew G. Knepley 87147726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 87157726db96SVaclav Hapla } 871603da9461SVaclav Hapla } 8717ece87651SVaclav Hapla 87187726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 87197726db96SVaclav Hapla { 87207726db96SVaclav Hapla const PetscInt *rootdegree; 87217726db96SVaclav Hapla 87227726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 87237726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 8724f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 87257726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 8726f5869d18SMatthew G. Knepley const PetscInt *cone; 8727f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 8728f5869d18SMatthew G. Knepley 87299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 87309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 8731f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8732f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 87337726db96SVaclav Hapla if (locals) { 87349566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 87357726db96SVaclav Hapla } else { 87367726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 87377726db96SVaclav Hapla } 873863a3b9bcSJacob Faibussowitsch PetscCheck(idx >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " but not %" PetscInt_FMT " from its cone", point, cone[c]); 8739f5869d18SMatthew G. Knepley } 8740f5869d18SMatthew G. Knepley } 8741ece87651SVaclav Hapla } 87427726db96SVaclav Hapla } 874303da9461SVaclav Hapla PetscFunctionReturn(0); 874403da9461SVaclav Hapla } 874503da9461SVaclav Hapla 87467f9d8d6cSVaclav Hapla /*@ 87477f9d8d6cSVaclav Hapla DMPlexCheck - Perform various checks of Plex sanity 87487f9d8d6cSVaclav Hapla 87497f9d8d6cSVaclav Hapla Input Parameter: 87507f9d8d6cSVaclav Hapla . dm - The DMPlex object 87517f9d8d6cSVaclav Hapla 87527f9d8d6cSVaclav Hapla Notes: 87537f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 87547f9d8d6cSVaclav Hapla 87557f9d8d6cSVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 87567f9d8d6cSVaclav Hapla 87577f9d8d6cSVaclav Hapla Currently does not include DMPlexCheckCellShape(). 87587f9d8d6cSVaclav Hapla 87597f9d8d6cSVaclav Hapla Level: developer 87607f9d8d6cSVaclav Hapla 87617f9d8d6cSVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 87627f9d8d6cSVaclav Hapla @*/ 87637f9d8d6cSVaclav Hapla PetscErrorCode DMPlexCheck(DM dm) 8764b5a892a1SMatthew G. Knepley { 87657f9d8d6cSVaclav Hapla PetscInt cellHeight; 87667f9d8d6cSVaclav Hapla 8767b5a892a1SMatthew G. Knepley PetscFunctionBegin; 87687f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87699566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 87709566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 87719566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 87729566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 87737726db96SVaclav Hapla PetscCall(DMPlexCheckPointSF(dm, NULL)); 87749566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 8775b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 8776b5a892a1SMatthew G. Knepley } 8777b5a892a1SMatthew G. Knepley 8778068a5610SStefano Zampini typedef struct cell_stats 8779068a5610SStefano Zampini { 8780068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 8781068a5610SStefano Zampini PetscInt count; 8782068a5610SStefano Zampini } cell_stats_t; 8783068a5610SStefano Zampini 878425befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8785068a5610SStefano Zampini { 8786068a5610SStefano Zampini PetscInt i, N = *len; 8787068a5610SStefano Zampini 8788068a5610SStefano Zampini for (i = 0; i < N; i++) { 8789068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *) a; 8790068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *) b; 8791068a5610SStefano Zampini 8792068a5610SStefano Zampini B->min = PetscMin(A->min,B->min); 8793068a5610SStefano Zampini B->max = PetscMax(A->max,B->max); 8794068a5610SStefano Zampini B->sum += A->sum; 8795068a5610SStefano Zampini B->squaresum += A->squaresum; 8796068a5610SStefano Zampini B->count += A->count; 8797068a5610SStefano Zampini } 8798068a5610SStefano Zampini } 8799068a5610SStefano Zampini 8800068a5610SStefano Zampini /*@ 880143fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8802068a5610SStefano Zampini 88038261a58bSMatthew G. Knepley Collective on dm 88048261a58bSMatthew G. Knepley 8805068a5610SStefano Zampini Input Parameters: 8806068a5610SStefano Zampini + dm - The DMPlex object 880743fa8764SMatthew G. Knepley . output - If true, statistics will be displayed on stdout 880843fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8809068a5610SStefano Zampini 881095eb5ee5SVaclav Hapla Notes: 881195eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 881295eb5ee5SVaclav Hapla 881395eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8814068a5610SStefano Zampini 8815068a5610SStefano Zampini Level: developer 8816068a5610SStefano Zampini 8817db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 8818068a5610SStefano Zampini @*/ 881943fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8820068a5610SStefano Zampini { 8821068a5610SStefano Zampini DM dmCoarse; 882243fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 882343fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 882443fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 882543fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8826412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 882743fa8764SMatthew G. Knepley PetscMPIInt rank,size; 8828068a5610SStefano Zampini 8829068a5610SStefano Zampini PetscFunctionBegin; 8830068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8831068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 8832068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 8833068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 8834068a5610SStefano Zampini stats.count = 0; 8835068a5610SStefano Zampini 88369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 88379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 88389566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm,&cdim)); 88399566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 88409566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd)); 88419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd)); 8842412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 8843068a5610SStefano Zampini PetscInt i; 8844068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8845068a5610SStefano Zampini 88469566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ)); 884763a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 884843fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 8849068a5610SStefano Zampini frobJ += J[i] * J[i]; 8850068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 8851068a5610SStefano Zampini } 8852068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 8853068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 8854068a5610SStefano Zampini 8855068a5610SStefano Zampini stats.min = PetscMin(stats.min,cond); 8856068a5610SStefano Zampini stats.max = PetscMax(stats.max,cond); 8857068a5610SStefano Zampini stats.sum += cond; 8858068a5610SStefano Zampini stats.squaresum += cond2; 8859068a5610SStefano Zampini stats.count++; 88608261a58bSMatthew G. Knepley if (output && cond > limit) { 886143fa8764SMatthew G. Knepley PetscSection coordSection; 886243fa8764SMatthew G. Knepley Vec coordsLocal; 886343fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 886443fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 886543fa8764SMatthew G. Knepley 88669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 88679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 88689566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 886963a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double) cond)); 887043fa8764SMatthew G. Knepley for (i = 0; i < Nv/cdim; ++i) { 887163a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 887243fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 88739566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 88749566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]))); 887543fa8764SMatthew G. Knepley } 88769566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 887743fa8764SMatthew G. Knepley } 88789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 887943fa8764SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) { 888043fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 888143fa8764SMatthew G. Knepley 888243fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 888343fa8764SMatthew G. Knepley PetscReal len; 888443fa8764SMatthew G. Knepley 88859566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 888663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double) len)); 888743fa8764SMatthew G. Knepley } 888843fa8764SMatthew G. Knepley } 88899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 88909566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 889143fa8764SMatthew G. Knepley } 8892068a5610SStefano Zampini } 88939566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 8894068a5610SStefano Zampini 8895068a5610SStefano Zampini if (size > 1) { 8896068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4,1}; 8897068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8898068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8899068a5610SStefano Zampini MPI_Op statReduce; 8900068a5610SStefano Zampini 89019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType)); 89029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 89039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 89049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm)); 89059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 89069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 8907068a5610SStefano Zampini } else { 89089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats,&stats,1)); 8909068a5610SStefano Zampini } 8910dd400576SPatrick Sanan if (rank == 0) { 8911068a5610SStefano Zampini count = globalStats.count; 8912068a5610SStefano Zampini min = globalStats.min; 8913068a5610SStefano Zampini max = globalStats.max; 8914068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 8915068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8916068a5610SStefano Zampini } 8917068a5610SStefano Zampini 8918068a5610SStefano Zampini if (output) { 891963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(comm,"Mesh with %" PetscInt_FMT " cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double) min, (double) max, (double) mean, (double) stdev)); 8920068a5610SStefano Zampini } 89219566063dSJacob Faibussowitsch PetscCall(PetscFree2(J,invJ)); 8922068a5610SStefano Zampini 89239566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm,&dmCoarse)); 8924068a5610SStefano Zampini if (dmCoarse) { 8925068a5610SStefano Zampini PetscBool isplex; 8926068a5610SStefano Zampini 89279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex)); 8928068a5610SStefano Zampini if (isplex) { 89299566063dSJacob Faibussowitsch PetscCall(DMPlexCheckCellShape(dmCoarse,output,condLimit)); 8930068a5610SStefano Zampini } 8931068a5610SStefano Zampini } 8932068a5610SStefano Zampini PetscFunctionReturn(0); 8933068a5610SStefano Zampini } 8934068a5610SStefano Zampini 8935f108dbd7SJacob Faibussowitsch /*@ 8936f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8937f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 8938f108dbd7SJacob Faibussowitsch 89396ed19f2fSJacob Faibussowitsch Collective on dm 8940f108dbd7SJacob Faibussowitsch 8941f108dbd7SJacob Faibussowitsch Input Parameters: 8942f108dbd7SJacob Faibussowitsch + dm - The DMPlex object 8943f108dbd7SJacob Faibussowitsch . fv - Optional PetscFV object for pre-computed cell/face centroid information 8944f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 8945f108dbd7SJacob Faibussowitsch 8946f108dbd7SJacob Faibussowitsch Output Parameters: 8947f108dbd7SJacob Faibussowitsch + OrthQual - Vec containing orthogonal quality per cell 8948f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8949f108dbd7SJacob Faibussowitsch 8950f108dbd7SJacob Faibussowitsch Options Database Keys: 8951f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8952f108dbd7SJacob Faibussowitsch supported. 8953f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8954f108dbd7SJacob Faibussowitsch 8955f108dbd7SJacob Faibussowitsch Notes: 8956f108dbd7SJacob Faibussowitsch Orthogonal quality is given by the following formula: 8957f108dbd7SJacob Faibussowitsch 8958f108dbd7SJacob Faibussowitsch \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8959f108dbd7SJacob Faibussowitsch 8960f108dbd7SJacob 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 8961f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8962f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8963f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 8964f108dbd7SJacob Faibussowitsch 8965f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 8966f108dbd7SJacob Faibussowitsch 8967f108dbd7SJacob Faibussowitsch This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8968f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8969f108dbd7SJacob Faibussowitsch 8970f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8971f108dbd7SJacob Faibussowitsch 8972f108dbd7SJacob Faibussowitsch Level: intermediate 8973f108dbd7SJacob Faibussowitsch 8974db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()` 8975f108dbd7SJacob Faibussowitsch @*/ 8976f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8977f108dbd7SJacob Faibussowitsch { 89786ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 89796ed19f2fSJacob Faibussowitsch PetscInt *idx; 89806ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 8981f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 89826ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 8983f108dbd7SJacob Faibussowitsch MPI_Comm comm; 8984f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 8985f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 8986f108dbd7SJacob Faibussowitsch IS glob; 8987f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 8988f108dbd7SJacob Faibussowitsch PetscViewer vwr; 8989f108dbd7SJacob Faibussowitsch 8990f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 8991f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89926ed19f2fSJacob Faibussowitsch if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8993f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQual, 4); 89946bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 89959566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 89969566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 899763a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 89986ed19f2fSJacob Faibussowitsch { 89996ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 90006ed19f2fSJacob Faibussowitsch 90019566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9002f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9003f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9004f108dbd7SJacob Faibussowitsch 90059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 900698921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9007f108dbd7SJacob Faibussowitsch } 90086ed19f2fSJacob Faibussowitsch } 9009f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 9010f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQualLabel, 5); 90119566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 90129566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 90136ed19f2fSJacob Faibussowitsch } else {*OrthQualLabel = NULL;} 90149566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 90159566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 90169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 90179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 90189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 90199566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 90209566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 90219566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE)); 90229566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 90239566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 90249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 90259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 90269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 90279566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 90289566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 90299566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 90309566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 90319566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 90326ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++,cell++) { 90336ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9034f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9035f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9036898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9037f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9038f108dbd7SJacob Faibussowitsch 90396ed19f2fSJacob Faibussowitsch idx[cellIter] = cell-cStart; 9040f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9041f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 90429566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 90439566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9044f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 90459566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 90466ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 90476ed19f2fSJacob Faibussowitsch PetscInt i; 90486ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9049f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9050f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9051f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9052f108dbd7SJacob Faibussowitsch 9053f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9054f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 90559566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9056f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 90576ed19f2fSJacob Faibussowitsch { 90586ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 90596ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 90606ed19f2fSJacob Faibussowitsch 90619566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 90629566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 90639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 90646ed19f2fSJacob Faibussowitsch } 9065f108dbd7SJacob Faibussowitsch 9066f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9067f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9068f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9069f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9070f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9071addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9072addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9073addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9074f108dbd7SJacob Faibussowitsch } 9075addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9076addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9077addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9078f108dbd7SJacob Faibussowitsch 9079f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9080f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9081f108dbd7SJacob Faibussowitsch ci[i] = ci[i]/normci; 9082f108dbd7SJacob Faibussowitsch fi[i] = fi[i]/normfi; 9083f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i]/normai; 9084f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9085f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9086f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9087f108dbd7SJacob Faibussowitsch } 9088f108dbd7SJacob Faibussowitsch if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9089f108dbd7SJacob Faibussowitsch minvalc = PetscRealPart(cArr[cellneighiter]); 9090f108dbd7SJacob Faibussowitsch } 9091f108dbd7SJacob Faibussowitsch if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9092f108dbd7SJacob Faibussowitsch minvalf = PetscRealPart(fArr[cellneighiter]); 9093f108dbd7SJacob Faibussowitsch } 9094f108dbd7SJacob Faibussowitsch } 90959566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 90969566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9097f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 90986ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9099f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 91009566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9101f108dbd7SJacob Faibussowitsch } 9102f108dbd7SJacob Faibussowitsch } 91039566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES)); 91049566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 91059566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 91069566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 91079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 91089566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9109f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 91109566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9111f108dbd7SJacob Faibussowitsch } 91129566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 91139566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vwr)); 91149566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 9115f108dbd7SJacob Faibussowitsch PetscFunctionReturn(0); 9116f108dbd7SJacob Faibussowitsch } 9117f108dbd7SJacob Faibussowitsch 91181eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 91191eb70e55SToby Isaac * interpolator construction */ 91201eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 91211eb70e55SToby Isaac { 91221eb70e55SToby Isaac PetscSection section, newSection, gsection; 91231eb70e55SToby Isaac PetscSF sf; 91241eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 91251eb70e55SToby Isaac 91261eb70e55SToby Isaac PetscFunctionBegin; 91271eb70e55SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 91281eb70e55SToby Isaac PetscValidPointer(odm,2); 91299566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 91309566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 91319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm))); 91321eb70e55SToby Isaac if (!ghasConstraints) { 91339566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 91341eb70e55SToby Isaac *odm = dm; 91351eb70e55SToby Isaac PetscFunctionReturn(0); 91361eb70e55SToby Isaac } 91379566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 91389566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 91399566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 91409566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 91419566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 91429566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 91439566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 91441eb70e55SToby Isaac PetscFunctionReturn(0); 91451eb70e55SToby Isaac } 91461eb70e55SToby Isaac 91471eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 91481eb70e55SToby Isaac { 91491eb70e55SToby Isaac DM dmco, dmfo; 91501eb70e55SToby Isaac Mat interpo; 91511eb70e55SToby Isaac Vec rscale; 91521eb70e55SToby Isaac Vec cglobalo, clocal; 91531eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 91541eb70e55SToby Isaac PetscBool regular; 91551eb70e55SToby Isaac 91561eb70e55SToby Isaac PetscFunctionBegin; 91579566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 91589566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 91599566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 91609566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 91619566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 91629566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 91639566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 91649566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 91659566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 91669566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 91679566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 91689566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 91699566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 91709566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 91719566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 91729566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 91739566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 91749566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 91759566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 91769566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 91779566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 91789566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 91799566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 91809566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 91811eb70e55SToby Isaac *shift = fglobal; 91829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 91839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 91849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 91859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 91869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 91879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 91889566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 91899566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 91901eb70e55SToby Isaac PetscFunctionReturn(0); 91911eb70e55SToby Isaac } 91921eb70e55SToby Isaac 91931eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 91941eb70e55SToby Isaac { 91951eb70e55SToby Isaac PetscObject shifto; 91961eb70e55SToby Isaac Vec shift; 91971eb70e55SToby Isaac 91981eb70e55SToby Isaac PetscFunctionBegin; 91991eb70e55SToby Isaac if (!interp) { 92001eb70e55SToby Isaac Vec rscale; 92011eb70e55SToby Isaac 92029566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 92039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 92041eb70e55SToby Isaac } else { 92059566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 92061eb70e55SToby Isaac } 92079566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 92081eb70e55SToby Isaac if (!shifto) { 92099566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 92109566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift)); 92111eb70e55SToby Isaac shifto = (PetscObject) shift; 92129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 92131eb70e55SToby Isaac } 92141eb70e55SToby Isaac shift = (Vec) shifto; 92159566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 92169566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 92179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 92181eb70e55SToby Isaac PetscFunctionReturn(0); 92191eb70e55SToby Isaac } 92201eb70e55SToby Isaac 9221bceba477SMatthew G. Knepley /* Pointwise interpolation 9222bceba477SMatthew G. Knepley Just code FEM for now 9223bceba477SMatthew G. Knepley u^f = I u^c 92244ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 92254ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 92264ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9227bceba477SMatthew G. Knepley */ 9228bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9229bceba477SMatthew G. Knepley { 9230bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9231bceba477SMatthew G. Knepley PetscInt m, n; 9232a063dac3SMatthew G. Knepley void *ctx; 923368132eb9SMatthew G. Knepley DM cdm; 9234cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9235bceba477SMatthew G. Knepley 9236bceba477SMatthew G. Knepley PetscFunctionBegin; 92379566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 92389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 92399566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 92409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 924168132eb9SMatthew G. Knepley 92429566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 92439566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation)); 92449566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 92459566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 92469566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 924768132eb9SMatthew G. Knepley 92489566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 92499566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 92509566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 92519566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 92529566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 92534db47ee9SStefano Zampini if (scaling) { 92545d1c2e58SMatthew G. Knepley /* Use naive scaling */ 92559566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 92564db47ee9SStefano Zampini } 9257a063dac3SMatthew G. Knepley PetscFunctionReturn(0); 9258a063dac3SMatthew G. Knepley } 9259bceba477SMatthew G. Knepley 92606dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9261a063dac3SMatthew G. Knepley { 92626dbf9973SLawrence Mitchell VecScatter ctx; 926390748bafSMatthew G. Knepley 9264a063dac3SMatthew G. Knepley PetscFunctionBegin; 92659566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 92669566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 92679566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 9268bceba477SMatthew G. Knepley PetscFunctionReturn(0); 9269bceba477SMatthew G. Knepley } 9270bceba477SMatthew G. Knepley 92713e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 92723e9753d6SMatthew G. Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 92733e9753d6SMatthew G. Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 92743e9753d6SMatthew G. Knepley PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 92753e9753d6SMatthew G. Knepley { 927600635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 927700635df3SMatthew G. Knepley PetscInt c; 927800635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 92793e9753d6SMatthew G. Knepley } 92803e9753d6SMatthew G. Knepley 9281b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9282b4937a87SMatthew G. Knepley { 9283b4937a87SMatthew G. Knepley DM dmc; 9284b4937a87SMatthew G. Knepley PetscDS ds; 9285b4937a87SMatthew G. Knepley Vec ones, locmass; 9286b4937a87SMatthew G. Knepley IS cellIS; 9287b4937a87SMatthew G. Knepley PetscFormKey key; 9288b4937a87SMatthew G. Knepley PetscInt depth; 9289b4937a87SMatthew G. Knepley 9290b4937a87SMatthew G. Knepley PetscFunctionBegin; 92919566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 92929566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 92939566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 92949566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92959566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 92969566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 92979566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 92989566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 92999566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 93009566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 93019566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9302b4937a87SMatthew G. Knepley key.label = NULL; 9303b4937a87SMatthew G. Knepley key.value = 0; 9304b4937a87SMatthew G. Knepley key.field = 0; 9305b4937a87SMatthew G. Knepley key.part = 0; 93069566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 93079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 93089566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 93099566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 93109566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 93119566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 93129566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 93139566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 9314b4937a87SMatthew G. Knepley PetscFunctionReturn(0); 9315b4937a87SMatthew G. Knepley } 9316b4937a87SMatthew G. Knepley 9317bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9318bd041c0cSMatthew G. Knepley { 9319bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9320bd041c0cSMatthew G. Knepley PetscInt m, n; 9321bd041c0cSMatthew G. Knepley void *ctx; 9322bd041c0cSMatthew G. Knepley DM cdm; 9323bd041c0cSMatthew G. Knepley PetscBool regular; 9324bd041c0cSMatthew G. Knepley 9325bd041c0cSMatthew G. Knepley PetscFunctionBegin; 93263e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 93273e9753d6SMatthew G. Knepley DM dmc; 93283e9753d6SMatthew G. Knepley PetscDS ds; 9329b4937a87SMatthew G. Knepley PetscWeakForm wf; 93303e9753d6SMatthew G. Knepley Vec u; 93313e9753d6SMatthew G. Knepley IS cellIS; 933206ad1575SMatthew G. Knepley PetscFormKey key; 93333e9753d6SMatthew G. Knepley PetscInt depth; 93343e9753d6SMatthew G. Knepley 93359566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 93369566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 93379566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 93389566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 93399566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 93409566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 93419566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 93429566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmc, &u)); 93439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 93449566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 93459566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 93466528b96dSMatthew G. Knepley key.label = NULL; 93476528b96dSMatthew G. Knepley key.value = 0; 93486528b96dSMatthew G. Knepley key.field = 0; 934906ad1575SMatthew G. Knepley key.part = 0; 93509566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 93519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 93529566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmc, &u)); 93539566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 93543e9753d6SMatthew G. Knepley } else { 93559566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 93569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 93579566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 93589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9359bd041c0cSMatthew G. Knepley 93609566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass)); 93619566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 93629566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 93639566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9364bd041c0cSMatthew G. Knepley 93659566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 93669566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 93679566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 93689566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 93693e9753d6SMatthew G. Knepley } 93709566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 9371bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 9372bd041c0cSMatthew G. Knepley } 9373bd041c0cSMatthew G. Knepley 93740aef6b92SMatthew G. Knepley /*@ 93750aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93760aef6b92SMatthew G. Knepley 93770aef6b92SMatthew G. Knepley Input Parameter: 93780aef6b92SMatthew G. Knepley . dm - The DMPlex object 93790aef6b92SMatthew G. Knepley 93800aef6b92SMatthew G. Knepley Output Parameter: 93810aef6b92SMatthew G. Knepley . regular - The flag 93820aef6b92SMatthew G. Knepley 93830aef6b92SMatthew G. Knepley Level: intermediate 93840aef6b92SMatthew G. Knepley 9385db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()` 93860aef6b92SMatthew G. Knepley @*/ 93870aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 93880aef6b92SMatthew G. Knepley { 93890aef6b92SMatthew G. Knepley PetscFunctionBegin; 93900aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9391dadcf809SJacob Faibussowitsch PetscValidBoolPointer(regular, 2); 93920aef6b92SMatthew G. Knepley *regular = ((DM_Plex *) dm->data)->regularRefinement; 93930aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93940aef6b92SMatthew G. Knepley } 93950aef6b92SMatthew G. Knepley 93960aef6b92SMatthew G. Knepley /*@ 93970aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93980aef6b92SMatthew G. Knepley 93990aef6b92SMatthew G. Knepley Input Parameters: 94000aef6b92SMatthew G. Knepley + dm - The DMPlex object 94010aef6b92SMatthew G. Knepley - regular - The flag 94020aef6b92SMatthew G. Knepley 94030aef6b92SMatthew G. Knepley Level: intermediate 94040aef6b92SMatthew G. Knepley 9405db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()` 94060aef6b92SMatthew G. Knepley @*/ 94070aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 94080aef6b92SMatthew G. Knepley { 94090aef6b92SMatthew G. Knepley PetscFunctionBegin; 94100aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94110aef6b92SMatthew G. Knepley ((DM_Plex *) dm->data)->regularRefinement = regular; 94120aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 94130aef6b92SMatthew G. Knepley } 94140aef6b92SMatthew G. Knepley 9415f7c74593SToby Isaac /* anchors */ 9416a68b90caSToby Isaac /*@ 9417f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9418ebdb1bfaSJed Brown call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9419a68b90caSToby Isaac 9420e228b242SToby Isaac not collective 9421a68b90caSToby Isaac 9422f899ff85SJose E. Roman Input Parameter: 9423a68b90caSToby Isaac . dm - The DMPlex object 9424a68b90caSToby Isaac 9425a68b90caSToby Isaac Output Parameters: 9426a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9427a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9428a68b90caSToby Isaac 9429a68b90caSToby Isaac Level: intermediate 9430a68b90caSToby Isaac 9431db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9432a68b90caSToby Isaac @*/ 9433a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9434a68b90caSToby Isaac { 9435a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9436a68b90caSToby Isaac 9437a68b90caSToby Isaac PetscFunctionBegin; 9438a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94399566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 9440a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 9441a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 9442a68b90caSToby Isaac PetscFunctionReturn(0); 9443a68b90caSToby Isaac } 9444a68b90caSToby Isaac 9445a68b90caSToby Isaac /*@ 9446f7c74593SToby Isaac DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9447f7c74593SToby Isaac when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9448a68b90caSToby Isaac point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9449a68b90caSToby Isaac 9450a17985deSToby Isaac After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9451ebdb1bfaSJed Brown DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9452a68b90caSToby Isaac 9453e228b242SToby Isaac collective on dm 9454a68b90caSToby Isaac 9455a68b90caSToby Isaac Input Parameters: 9456a68b90caSToby Isaac + dm - The DMPlex object 9457e228b242SToby 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). 9458e228b242SToby Isaac - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9459a68b90caSToby Isaac 9460a68b90caSToby Isaac The reference counts of anchorSection and anchorIS are incremented. 9461a68b90caSToby Isaac 9462a68b90caSToby Isaac Level: intermediate 9463a68b90caSToby Isaac 9464db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 9465a68b90caSToby Isaac @*/ 9466a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9467a68b90caSToby Isaac { 9468a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9469e228b242SToby Isaac PetscMPIInt result; 9470a68b90caSToby Isaac 9471a68b90caSToby Isaac PetscFunctionBegin; 9472a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9473e228b242SToby Isaac if (anchorSection) { 9474e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 94759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result)); 94761dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9477e228b242SToby Isaac } 9478e228b242SToby Isaac if (anchorIS) { 9479e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 94809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result)); 94811dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9482e228b242SToby Isaac } 9483a68b90caSToby Isaac 94849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 94859566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 9486a68b90caSToby Isaac plex->anchorSection = anchorSection; 9487a68b90caSToby Isaac 94889566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 94899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 9490a68b90caSToby Isaac plex->anchorIS = anchorIS; 9491a68b90caSToby Isaac 9492cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9493a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 9494a68b90caSToby Isaac const PetscInt *anchors; 9495a68b90caSToby Isaac 94969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 94979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS,&size)); 94989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS,&anchors)); 9499a68b90caSToby Isaac for (a = 0; a < size; a++) { 9500a68b90caSToby Isaac PetscInt p; 9501a68b90caSToby Isaac 9502a68b90caSToby Isaac p = anchors[a]; 9503a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 9504a68b90caSToby Isaac PetscInt dof; 9505a68b90caSToby Isaac 95069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection,p,&dof)); 9507a68b90caSToby Isaac if (dof) { 9508a68b90caSToby Isaac 95099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS,&anchors)); 951063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %" PetscInt_FMT " cannot be constrained and an anchor",p); 9511a68b90caSToby Isaac } 9512a68b90caSToby Isaac } 9513a68b90caSToby Isaac } 95149566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS,&anchors)); 9515a68b90caSToby Isaac } 9516f7c74593SToby Isaac /* reset the generic constraints */ 95179566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,NULL,NULL,NULL)); 9518a68b90caSToby Isaac PetscFunctionReturn(0); 9519a68b90caSToby Isaac } 9520a68b90caSToby Isaac 9521f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9522a68b90caSToby Isaac { 9523f7c74593SToby Isaac PetscSection anchorSection; 95246995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9525a68b90caSToby Isaac 9526a68b90caSToby Isaac PetscFunctionBegin; 9527a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95289566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL)); 95299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,cSec)); 95309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numFields)); 95316995de1eSToby Isaac if (numFields) { 9532719ab38cSToby Isaac PetscInt f; 95339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec,numFields)); 9534719ab38cSToby Isaac 9535719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 9536719ab38cSToby Isaac PetscInt numComp; 9537719ab38cSToby Isaac 95389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section,f,&numComp)); 95399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec,f,numComp)); 9540719ab38cSToby Isaac } 95416995de1eSToby Isaac } 95429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 95439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&sStart,&sEnd)); 95446995de1eSToby Isaac pStart = PetscMax(pStart,sStart); 95456995de1eSToby Isaac pEnd = PetscMin(pEnd,sEnd); 95466995de1eSToby Isaac pEnd = PetscMax(pStart,pEnd); 95479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec,pStart,pEnd)); 9548a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 95499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection,p,&dof)); 9550a68b90caSToby Isaac if (dof) { 95519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,p,&dof)); 95529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec,p,dof)); 9553a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 95549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,p,f,&dof)); 95559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec,p,f,dof)); 9556a68b90caSToby Isaac } 9557a68b90caSToby Isaac } 9558a68b90caSToby Isaac } 95599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 95609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *cSec, "Constraint Section")); 9561a68b90caSToby Isaac PetscFunctionReturn(0); 9562a68b90caSToby Isaac } 9563a68b90caSToby Isaac 9564f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9565a68b90caSToby Isaac { 9566f7c74593SToby Isaac PetscSection aSec; 9567ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 95680ac89760SToby Isaac const PetscInt *anchors; 95690ac89760SToby Isaac PetscInt numFields, f; 957066ad2231SToby Isaac IS aIS; 9571e19f7ee6SMark Adams MatType mtype; 9572e19f7ee6SMark Adams PetscBool iscuda,iskokkos; 95730ac89760SToby Isaac 95740ac89760SToby Isaac PetscFunctionBegin; 95750ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 95779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 95789566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,cMat)); 95799566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat,m,n,m,n)); 95809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda)); 95819566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda)); 95829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos)); 95839566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos)); 9584e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 9585e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9586e19f7ee6SMark Adams else mtype = MATSEQAIJ; 95879566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat,mtype)); 95889566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 95899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 95906995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 95919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec,&pStart,&pEnd)); 95929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&sStart,&sEnd)); 95939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&i)); 95940ac89760SToby Isaac i[0] = 0; 95959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numFields)); 95960ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 9597f19733c5SToby Isaac PetscInt rDof, rOff, r; 9598f19733c5SToby Isaac 95999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 9600f19733c5SToby Isaac if (!rDof) continue; 96019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96020ac89760SToby Isaac if (numFields) { 96030ac89760SToby Isaac for (f = 0; f < numFields; f++) { 96040ac89760SToby Isaac annz = 0; 9605f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 9606f19733c5SToby Isaac a = anchors[rOff + r]; 9607ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof)); 96090ac89760SToby Isaac annz += aDof; 96100ac89760SToby Isaac } 96119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof)); 96129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&off)); 96130ac89760SToby Isaac for (q = 0; q < dof; q++) { 96140ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 96150ac89760SToby Isaac } 96160ac89760SToby Isaac } 96172f7452b8SBarry Smith } else { 96180ac89760SToby Isaac annz = 0; 96199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96200ac89760SToby Isaac for (q = 0; q < dof; q++) { 9621ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 9622ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 96240ac89760SToby Isaac annz += aDof; 96250ac89760SToby Isaac } 96269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec,p,&off)); 96280ac89760SToby Isaac for (q = 0; q < dof; q++) { 96290ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 96300ac89760SToby Isaac } 96310ac89760SToby Isaac } 96320ac89760SToby Isaac } 96330ac89760SToby Isaac nnz = i[m]; 96349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&j)); 96350ac89760SToby Isaac offset = 0; 96360ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 96370ac89760SToby Isaac if (numFields) { 96380ac89760SToby Isaac for (f = 0; f < numFields; f++) { 96399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof)); 96400ac89760SToby Isaac for (q = 0; q < dof; q++) { 96410ac89760SToby Isaac PetscInt rDof, rOff, r; 96429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 96439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96440ac89760SToby Isaac for (r = 0; r < rDof; r++) { 96450ac89760SToby Isaac PetscInt s; 96460ac89760SToby Isaac 96470ac89760SToby Isaac a = anchors[rOff + r]; 9648ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof)); 96509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section,a,f,&aOff)); 96510ac89760SToby Isaac for (s = 0; s < aDof; s++) { 96520ac89760SToby Isaac j[offset++] = aOff + s; 96530ac89760SToby Isaac } 96540ac89760SToby Isaac } 96550ac89760SToby Isaac } 96560ac89760SToby Isaac } 96572f7452b8SBarry Smith } else { 96589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&dof)); 96590ac89760SToby Isaac for (q = 0; q < dof; q++) { 96600ac89760SToby Isaac PetscInt rDof, rOff, r; 96619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&rDof)); 96629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&rOff)); 96630ac89760SToby Isaac for (r = 0; r < rDof; r++) { 96640ac89760SToby Isaac PetscInt s; 96650ac89760SToby Isaac 96660ac89760SToby Isaac a = anchors[rOff + r]; 9667ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 96689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aDof)); 96699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,a,&aOff)); 96700ac89760SToby Isaac for (s = 0; s < aDof; s++) { 96710ac89760SToby Isaac j[offset++] = aOff + s; 96720ac89760SToby Isaac } 96730ac89760SToby Isaac } 96740ac89760SToby Isaac } 96750ac89760SToby Isaac } 96760ac89760SToby Isaac } 96779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL)); 96789566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 96799566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 96809566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 96810ac89760SToby Isaac PetscFunctionReturn(0); 96820ac89760SToby Isaac } 96830ac89760SToby Isaac 968466ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 968566ad2231SToby Isaac { 9686f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9687f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 968866ad2231SToby Isaac Mat cMat; 968966ad2231SToby Isaac 969066ad2231SToby Isaac PetscFunctionBegin; 969166ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 96929566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL)); 969366ad2231SToby Isaac if (anchorSection) { 969444a7f3ddSMatthew G. Knepley PetscInt Nf; 9695e228b242SToby Isaac 96969566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm,§ion)); 96979566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec)); 96989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat)); 96999566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm,&Nf)); 97009566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm,section,cSec,cMat)); 97019566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,cSec,cMat,NULL)); 97029566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 97039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 970466ad2231SToby Isaac } 970566ad2231SToby Isaac PetscFunctionReturn(0); 970666ad2231SToby Isaac } 9707a93c429eSMatthew G. Knepley 9708a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9709a93c429eSMatthew G. Knepley { 9710a93c429eSMatthew G. Knepley IS subis; 9711a93c429eSMatthew G. Knepley PetscSection section, subsection; 9712a93c429eSMatthew G. Knepley 9713a93c429eSMatthew G. Knepley PetscFunctionBegin; 97149566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 971528b400f6SJacob Faibussowitsch PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 971628b400f6SJacob Faibussowitsch PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9717a93c429eSMatthew G. Knepley /* Create subdomain */ 97189566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 9719a93c429eSMatthew G. Knepley /* Create submodel */ 97209566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 97219566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 97229566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 97239566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 97249566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 9725a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 9726a93c429eSMatthew G. Knepley if (is) { 9727a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 9728a93c429eSMatthew G. Knepley IS spIS; 9729a93c429eSMatthew G. Knepley const PetscInt *spmap; 9730a93c429eSMatthew G. Knepley PetscInt *subIndices; 9731a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9732a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9733a93c429eSMatthew G. Knepley 97349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 97359566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 97369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 97379566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 97389566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 97399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 9740a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9741a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 9742a93c429eSMatthew G. Knepley 97439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 9744a93c429eSMatthew G. Knepley if (gdof > 0) { 9745a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9746a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 9747a93c429eSMatthew G. Knepley 97489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 97499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 9750a93c429eSMatthew G. Knepley pSubSize += fdof-fcdof; 9751a93c429eSMatthew G. Knepley } 9752a93c429eSMatthew G. Knepley subSize += pSubSize; 9753a93c429eSMatthew G. Knepley if (pSubSize) { 9754a93c429eSMatthew G. Knepley if (bs < 0) { 9755a93c429eSMatthew G. Knepley bs = pSubSize; 9756a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 9757a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 9758a93c429eSMatthew G. Knepley bs = 1; 9759a93c429eSMatthew G. Knepley } 9760a93c429eSMatthew G. Knepley } 9761a93c429eSMatthew G. Knepley } 9762a93c429eSMatthew G. Knepley } 9763a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 9764a93c429eSMatthew G. Knepley bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 97659566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 9766a93c429eSMatthew G. Knepley if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9767a93c429eSMatthew G. Knepley else {bs = bsMinMax[0];} 97689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 9769a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9770a93c429eSMatthew G. Knepley PetscInt gdof, goff; 9771a93c429eSMatthew G. Knepley 97729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 9773a93c429eSMatthew G. Knepley if (gdof > 0) { 9774a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 9775a93c429eSMatthew G. Knepley 97769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 9777a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9778a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 9779a93c429eSMatthew G. Knepley 9780a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 9781a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 97829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 97839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 9784a93c429eSMatthew G. Knepley poff += fdof-fcdof; 9785a93c429eSMatthew G. Knepley } 97869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 97879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 9788a93c429eSMatthew G. Knepley for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9789a93c429eSMatthew G. Knepley subIndices[subOff] = goff+poff+fc; 9790a93c429eSMatthew G. Knepley } 9791a93c429eSMatthew G. Knepley } 9792a93c429eSMatthew G. Knepley } 9793a93c429eSMatthew G. Knepley } 97949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 97959566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 9796a93c429eSMatthew G. Knepley if (bs > 1) { 9797a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 9798a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 9799a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 9800a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 9801a93c429eSMatthew G. Knepley if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9802a93c429eSMatthew G. Knepley } 9803a93c429eSMatthew G. Knepley } 98049566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 9805a93c429eSMatthew G. Knepley } 9806a93c429eSMatthew G. Knepley /* Attach nullspace */ 9807a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9808a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9809a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 9810a93c429eSMatthew G. Knepley } 9811a93c429eSMatthew G. Knepley if (f < Nf) { 9812a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 98139566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 98146823f3c5SBlaise Bourdin 98159566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace)); 98169566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 9817a93c429eSMatthew G. Knepley } 9818a93c429eSMatthew G. Knepley } 9819a93c429eSMatthew G. Knepley PetscFunctionReturn(0); 9820a93c429eSMatthew G. Knepley } 9821c0f0dcc3SMatthew G. Knepley 9822c0f0dcc3SMatthew G. Knepley /*@ 9823c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 9824c0f0dcc3SMatthew G. Knepley 9825c0f0dcc3SMatthew G. Knepley Input Parameter: 9826c0f0dcc3SMatthew G. Knepley - dm - The DM 9827c0f0dcc3SMatthew G. Knepley 9828c0f0dcc3SMatthew G. Knepley Level: developer 9829c0f0dcc3SMatthew G. Knepley 9830c0f0dcc3SMatthew G. Knepley Options Database Keys: 9831c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor 9832c0f0dcc3SMatthew G. Knepley 9833db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()` 9834c0f0dcc3SMatthew G. Knepley @*/ 9835c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9836c0f0dcc3SMatthew G. Knepley { 9837e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG) 9838c0f0dcc3SMatthew G. Knepley PetscStageLog stageLog; 9839c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 9840c0f0dcc3SMatthew G. Knepley PetscLogStage stage; 9841c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 9842c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 9843c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 9844c0f0dcc3SMatthew G. Knepley const char *name; 9845e5ed2c37SJose E. Roman #endif 9846c0f0dcc3SMatthew G. Knepley 9847c0f0dcc3SMatthew G. Knepley PetscFunctionBegin; 9848c0f0dcc3SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9849c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG) 98509566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 98519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 98529566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 98539566063dSJacob Faibussowitsch PetscCall(PetscLogGetStageLog(&stageLog)); 98549566063dSJacob Faibussowitsch PetscCall(PetscStageLogGetCurrent(stageLog, &stage)); 98559566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 98569566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 9857c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart)*Nf*eventInfo.count; 9858c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops/eventInfo.time; 9859c0f0dcc3SMatthew G. Knepley cellRate = N/eventInfo.time; 986063a3b9bcSJacob 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))); 9861c0f0dcc3SMatthew G. Knepley #else 9862c0f0dcc3SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9863c0f0dcc3SMatthew G. Knepley #endif 9864c0f0dcc3SMatthew G. Knepley PetscFunctionReturn(0); 9865c0f0dcc3SMatthew G. Knepley } 9866