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 309318fe57SMatthew G. Knepley .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; 385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 399318fe57SMatthew G. Knepley if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 405f80ce2aSJacob Faibussowitsch CHKERRQ(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 608065b584SMatthew Knepley .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; 685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE)); 69412e9a14SMatthew G. Knepley for (c = cS; c < cE; ++c) { 70412e9a14SMatthew G. Knepley DMPolytopeType cct; 71412e9a14SMatthew G. Knepley 725f80ce2aSJacob Faibussowitsch CHKERRQ(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 905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellTypeLabel(dm, &ctLabel)); 915f80ce2aSJacob Faibussowitsch CHKERRQ(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; 1055f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &cdim)); 1065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 1085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd)); 1097e42fee7SMatthew G. Knepley if (field >= 0) { 1105f80ce2aSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) CHKERRQ(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 1115f80ce2aSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) CHKERRQ(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 1127e42fee7SMatthew G. Knepley } else { 1135f80ce2aSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) CHKERRQ(PetscSectionGetDof(section, vStart, &vcdof[0])); 1145f80ce2aSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) CHKERRQ(PetscSectionGetDof(section, cStart, &vcdof[1])); 1157e42fee7SMatthew G. Knepley } 1165f80ce2aSJacob Faibussowitsch CHKERRMPI(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 1315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldName(section, field, &fieldname)); 1325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname)); 133e630c359SToby Isaac } else { 1345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\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 1536913077dSMatthew G. Knepley .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; 1685f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm, &ds)); 1695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds, &Nf)); 1705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetTotalComponents(ds, &Nl)); 1715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetComponents(ds, &Nc)); 1726913077dSMatthew G. Knepley 1735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDrawGetDraw(viewer, 0, &draw)); 1746913077dSMatthew G. Knepley if (!draw) PetscFunctionReturn(0); 1755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLGCreate(draw, n*Nl, &lg)); 1766913077dSMatthew G. Knepley 1775f80ce2aSJacob Faibussowitsch CHKERRQ(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 1815f80ce2aSJacob Faibussowitsch CHKERRQ(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 1875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(ds, f, &disc)); 1886913077dSMatthew G. Knepley /* TODO Create names for components */ 1896913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 1905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName(disc, &fname)); 1915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(tmpname, vname)); 1925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN)); 1935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN)); 1945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrallocpy(tmpname, &names[l])); 1956913077dSMatthew G. Knepley } 1966913077dSMatthew G. Knepley } 1976913077dSMatthew G. Knepley } 1985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLGSetLegend(lg, (const char *const *) names)); 1996913077dSMatthew G. Knepley /* Just add P_1 support for now */ 2005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2015f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates)); 2025f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(coordinates, &coords)); 2035f80ce2aSJacob Faibussowitsch for (i = 0; i < n; ++i) CHKERRQ(VecGetArrayRead(u[i], &sol[i])); 2046913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 2056913077dSMatthew G. Knepley PetscScalar *x, *svals; 2066913077dSMatthew G. Knepley 2075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointLocalRead(dm, v, coords, &x)); 2086913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 2095f80ce2aSJacob Faibussowitsch CHKERRQ(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 } 2125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 2136913077dSMatthew G. Knepley } 2145f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(coordinates, &coords)); 2155f80ce2aSJacob Faibussowitsch for (i = 0; i < n; ++i) CHKERRQ(VecRestoreArrayRead(u[i], &sol[i])); 2165f80ce2aSJacob Faibussowitsch for (l = 0; l < n*Nl; ++l) CHKERRQ(PetscFree(names[l])); 2175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(sol, names, vals)); 2186913077dSMatthew G. Knepley 2195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLGDraw(lg)); 2205f80ce2aSJacob Faibussowitsch CHKERRQ(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; 2295f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(u, &dm)); 2305f80ce2aSJacob Faibussowitsch CHKERRQ(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; 2515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2525f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(v, &dm)); 2535f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &dim)); 2545f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm, &s)); 2555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(s, &Nf)); 2565f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarsenLevel(dm, &level)); 2575f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 2585f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(cdm, &coordSection)); 2595f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates)); 2605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2615f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 262e412dcbdSMatthew G. Knepley 2635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) v, &name)); 2645f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetOutputSequenceNumber(dm, &step, &time)); 265e412dcbdSMatthew G. Knepley 2665f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(coordinates, &N)); 2675f80ce2aSJacob Faibussowitsch CHKERRQ(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 } 2725f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(coordinates, &coords)); 2735f80ce2aSJacob Faibussowitsch CHKERRQ(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 2835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldComponents(s, f, &Nc)); 2845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldName(s, f, &fname)); 285d1df6f1dSMatthew G. Knepley 2865f80ce2aSJacob Faibussowitsch if (v->hdr.prefix) CHKERRQ(PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix))); 287d1df6f1dSMatthew G. Knepley else {prefix[0] = '\0';} 288d1df6f1dSMatthew G. Knepley if (Nf > 1) { 2895f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 2905f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSubVector(v, fis, &fv)); 2915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(prefix, fname,sizeof(prefix))); 2925f80ce2aSJacob Faibussowitsch CHKERRQ(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 2975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDrawGetDraw(viewer, w, &draw)); 2985f80ce2aSJacob Faibussowitsch if (Nc > 1) CHKERRQ(PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time)); 2995f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time)); 3005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawSetTitle(draw, title)); 301d1df6f1dSMatthew G. Knepley 302d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 3035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 304339e3443SMatthew G. Knepley if (!flg) { 3055f80ce2aSJacob Faibussowitsch CHKERRQ(VecMin(fv, NULL, &vbound[0])); 3065f80ce2aSJacob Faibussowitsch CHKERRQ(VecMax(fv, NULL, &vbound[1])); 307d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 308339e3443SMatthew G. Knepley } 3095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawGetPopup(draw, &popup)); 3105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 3115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3])); 312e412dcbdSMatthew G. Knepley 3135f80ce2aSJacob Faibussowitsch CHKERRQ(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 3185f80ce2aSJacob Faibussowitsch CHKERRQ(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 3265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 3272c71b3e2SJacob Faibussowitsch PetscCheckFalse(numVals % Nc,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", 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; 33798921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 338339e3443SMatthew G. Knepley } 3395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 340339e3443SMatthew G. Knepley } 3415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 342e412dcbdSMatthew G. Knepley switch (numCoords) { 343e412dcbdSMatthew G. Knepley case 6: 3449edc3542SMatthew Knepley case 12: /* Localized triangle */ 3455f80ce2aSJacob Faibussowitsch CHKERRQ(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 */ 3495f80ce2aSJacob Faibussowitsch CHKERRQ(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])); 3505f80ce2aSJacob Faibussowitsch CHKERRQ(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; 35298921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 353e412dcbdSMatthew G. Knepley } 3545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 355e412dcbdSMatthew G. Knepley } 3565f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(fv, &array)); 3575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawFlush(draw)); 3585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawPause(draw)); 3595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawSave(draw)); 360d1df6f1dSMatthew G. Knepley } 361d1df6f1dSMatthew G. Knepley if (Nf > 1) { 3625f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreSubVector(v, fis, &fv)); 3635f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&fis)); 3645f80ce2aSJacob Faibussowitsch CHKERRQ(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; 3785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawIsNull(draw, &isnull)); 3806913077dSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 3816913077dSMatthew G. Knepley 3825f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(v, &dm)); 3835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &dim)); 3846913077dSMatthew G. Knepley switch (dim) { 3855f80ce2aSJacob Faibussowitsch case 1: CHKERRQ(VecView_Plex_Local_Draw_1D(v, viewer));break; 3865f80ce2aSJacob Faibussowitsch case 2: CHKERRQ(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; 4035f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(v, &dm)); 4045f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 4055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) v, &name)); 4065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) locv, name)); 4075f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(v, locv)); 4085f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm, §ion)); 4095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &numFields)); 410e630c359SToby Isaac if (!numFields) { 4115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 4125f80ce2aSJacob Faibussowitsch CHKERRQ(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++) { 4175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 418e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 4195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)locv)); 4205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv)); 421e630c359SToby Isaac } 4225f80ce2aSJacob Faibussowitsch CHKERRQ(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; 4335f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(v, &dm)); 43428b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 4355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 4365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 4375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 4385f80ce2aSJacob Faibussowitsch CHKERRQ(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 4485f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumFields(dm, &numFields)); 449684b87d9SLisandro Dalcin for (i=0; i<numFields; i++) { 4505f80ce2aSJacob Faibussowitsch CHKERRQ(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 4565f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(dm, &locv)); 4575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) v, &name)); 4585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) locv, name)); 4595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero)); 4605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero)); 4615f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(v, locv)); 4625f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetOutputSequenceNumber(dm, NULL, &time)); 4635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 464ef31f671SMatthew G. Knepley } 465552f7358SJed Brown if (isvtk) { 4665f80ce2aSJacob Faibussowitsch CHKERRQ(VecView_Plex_Local_VTK(locv, viewer)); 467b136c2c9SMatthew G. Knepley } else if (ishdf5) { 468b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 4695f80ce2aSJacob Faibussowitsch CHKERRQ(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) { 4745f80ce2aSJacob Faibussowitsch CHKERRQ(VecView_Plex_Local_Draw(locv, viewer)); 475684b87d9SLisandro Dalcin } else if (isglvis) { 4765f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetOutputSequenceNumber(dm, &step, NULL)); 4775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGLVisSetSnapId(viewer, step)); 4785f80ce2aSJacob Faibussowitsch CHKERRQ(VecView_GLVis(locv, viewer)); 479684b87d9SLisandro Dalcin } 480798534f6SMatthew G. Knepley if (fem) { 4815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL)); 4825f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(dm, &locv)); 483798534f6SMatthew G. Knepley } 484552f7358SJed Brown } else { 485684b87d9SLisandro Dalcin PetscBool isseq; 486684b87d9SLisandro Dalcin 4875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 4885f80ce2aSJacob Faibussowitsch if (isseq) CHKERRQ(VecView_Seq(v, viewer)); 4895f80ce2aSJacob Faibussowitsch else CHKERRQ(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; 5005f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(v, &dm)); 50128b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 5035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 5045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 5055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 5065f80ce2aSJacob Faibussowitsch CHKERRQ(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 5125f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(dm, &locv)); 5135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) v, &name)); 5145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) locv, name)); 5155f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 5165f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 5175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero)); 5185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero)); 5195f80ce2aSJacob Faibussowitsch CHKERRQ(VecView_Plex_Local(locv, viewer)); 5205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL)); 5215f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(dm, &locv)); 522b136c2c9SMatthew G. Knepley } else if (ishdf5) { 523b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5245f80ce2aSJacob Faibussowitsch CHKERRQ(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) 5305f80ce2aSJacob Faibussowitsch CHKERRQ(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 5375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 5385f80ce2aSJacob Faibussowitsch if (isseq) CHKERRQ(VecView_Seq(v, viewer)); 5395f80ce2aSJacob Faibussowitsch else CHKERRQ(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; 5535f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(originalv, &dm)); 5545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) originalv, &comm)); 55528b400f6SJacob Faibussowitsch PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 5575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 5585f80ce2aSJacob Faibussowitsch CHKERRQ(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 5675f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(originalv, &n)); 5685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 569d930f514SMatthew G. Knepley if (n == nroots) { 5705f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalVector(dm, &v)); 5715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 5725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 5735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) originalv, &vecname)); 5745f80ce2aSJacob Faibussowitsch CHKERRQ(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) 5825f80ce2aSJacob Faibussowitsch CHKERRQ(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 5915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq)); 5925f80ce2aSJacob Faibussowitsch if (isseq) CHKERRQ(VecView_Seq(v, viewer)); 5935f80ce2aSJacob Faibussowitsch else CHKERRQ(VecView_MPI(v, viewer)); 594d930f514SMatthew G. Knepley } 5955f80ce2aSJacob Faibussowitsch if (v != originalv) CHKERRQ(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; 6055f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(v, &dm)); 60628b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6075f80ce2aSJacob Faibussowitsch CHKERRQ(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 6135f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetOutputDM(dm, &dmBC)); 6145f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalVector(dmBC, &gv)); 6155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) v, &name)); 6165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) gv, name)); 6175f80ce2aSJacob Faibussowitsch CHKERRQ(VecLoad_Default(gv, viewer)); 6185f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 6195f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 6205f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreGlobalVector(dmBC, &gv)); 6212c40f234SMatthew G. Knepley } else { 6225f80ce2aSJacob Faibussowitsch CHKERRQ(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; 6335f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(v, &dm)); 63428b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 6365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6372c40f234SMatthew G. Knepley if (ishdf5) { 638878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6395f80ce2aSJacob Faibussowitsch CHKERRQ(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) 6455f80ce2aSJacob Faibussowitsch CHKERRQ(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 { 6505f80ce2aSJacob Faibussowitsch CHKERRQ(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; 6625f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(originalv, &dm)); 66328b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 6655f80ce2aSJacob Faibussowitsch CHKERRQ(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 6745f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalVector(dm, &v)); 6755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) originalv, &vecname)); 6765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) v, vecname)); 6775f80ce2aSJacob Faibussowitsch CHKERRQ(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 6785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 6795f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 6805f80ce2aSJacob Faibussowitsch CHKERRQ(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 { 6875f80ce2aSJacob Faibussowitsch CHKERRQ(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; 7035f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 7045f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates)); 7055f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 7065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm, &depthLabel)); 7075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 7085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 7095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 7105f80ce2aSJacob Faibussowitsch CHKERRQ(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 7195f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(celltypeLabel, c, &ct)); 7205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct])); 7215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7225f80ce2aSJacob Faibussowitsch CHKERRQ(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; 7275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(coordSection, point, &dof)); 728731e8ddeSMatthew G. Knepley if (!dof) continue; 7295f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(depthLabel, point, &depth)); 7305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, point, &off)); 7315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point)); 732731e8ddeSMatthew G. Knepley for (p = 0; p < dof/dim; ++p) { 7335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " (")); 734731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 7355f80ce2aSJacob Faibussowitsch if (d > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, ", ")); 7365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]))); 737731e8ddeSMatthew G. Knepley } 7385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, ")")); 739731e8ddeSMatthew G. Knepley } 7405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\n")); 741731e8ddeSMatthew G. Knepley } 7425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 7435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(viewer)); 744731e8ddeSMatthew G. Knepley } 7455f80ce2aSJacob Faibussowitsch CHKERRQ(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) { 7585f80ce2aSJacob Faibussowitsch for (i = 0; i < dim; ++i) CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]))); 75919ad8254SMatthew G. Knepley } else { 76019ad8254SMatthew G. Knepley PetscReal coords[3], trcoords[3]; 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: 7662c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim != 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %D", 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: 7712c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %D", 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: 7772c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %D", 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 } 7835f80ce2aSJacob Faibussowitsch for (i = 0; i < dim; ++i) CHKERRQ(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; 7975f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 7985f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(cdm, &coordSection)); 7995f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates)); 8005f80ce2aSJacob Faibussowitsch CHKERRQ(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 8075f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8085f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 8095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) dm, &name)); 8105f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 8115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 8125f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 8135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight)); 8145f80ce2aSJacob Faibussowitsch if (name) CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 8155f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s")); 8165f80ce2aSJacob Faibussowitsch if (cellHeight) CHKERRQ(PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight)); 8175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Supports:\n", name)); 8185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(viewer)); 8195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize)); 820552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 821552f7358SJed Brown PetscInt dof, off, s; 822552f7358SJed Brown 8235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off)); 825552f7358SJed Brown for (s = off; s < off+dof; ++s) { 8265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s])); 827552f7358SJed Brown } 828552f7358SJed Brown } 8295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(viewer)); 8305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Cones:\n", name)); 8315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize)); 832552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 833552f7358SJed Brown PetscInt dof, off, c; 834552f7358SJed Brown 8355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof)); 8365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 837552f7358SJed Brown for (c = off; c < off+dof; ++c) { 8385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c])); 839552f7358SJed Brown } 840552f7358SJed Brown } 8415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(viewer)); 8425f80ce2aSJacob Faibussowitsch CHKERRQ(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 8505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL)); 8515f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 8525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(coordSection, &Nf)); 8532c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nf != 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf); 8545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 8555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 8565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) coordinates, &name)); 8575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf)); 8585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " field 0 with %D components\n", Nc)); 8595f80ce2aSJacob Faibussowitsch if (cs != CS_CARTESIAN) CHKERRQ(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 86019ad8254SMatthew G. Knepley 8615f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(coordinates, &array)); 8625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(viewer)); 8635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 86419ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 86519ad8254SMatthew G. Knepley PetscInt dof, off; 86619ad8254SMatthew G. Knepley 8675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(coordSection, p, &dof)); 8685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, p, &off)); 8695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, " (%4D) dim %2D offset %3D", p, dof, off)); 8705f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 8715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 87219ad8254SMatthew G. Knepley } 8735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(viewer)); 8745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopSynchronized(viewer)); 8755f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(coordinates, &array)); 8763d2e540fSStefano Zampini } 8775f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumLabels(dm, &numLabels)); 8785f80ce2aSJacob Faibussowitsch if (numLabels) CHKERRQ(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 8845f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabelName(dm, l, &name)); 8855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(name, "depth", &isdepth)); 8869318fe57SMatthew G. Knepley if (isdepth) continue; 8875f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, name, &label)); 8885f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelView(label, viewer)); 8899318fe57SMatthew G. Knepley } 890552f7358SJed Brown if (size > 1) { 891552f7358SJed Brown PetscSF sf; 892552f7358SJed Brown 8935f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 8945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFView(sf, viewer)); 895552f7358SJed Brown } 8965f80ce2aSJacob Faibussowitsch CHKERRQ(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 9145f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 9155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 9165f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumLabels(dm, &numLabels)); 9170588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 9180588280cSMatthew G. Knepley numColors = 10; 9190588280cSMatthew G. Knepley numLColors = 10; 9205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 9215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 9225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 9235f80ce2aSJacob Faibussowitsch CHKERRQ(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; 9275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 9282c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 9295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 9302c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 9315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 9320588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 9335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 9340588280cSMatthew G. Knepley if (!useColors) { 9350588280cSMatthew G. Knepley numColors = 3; 9365f80ce2aSJacob Faibussowitsch for (c = 0; c < numColors; ++c) CHKERRQ(PetscStrallocpy(defcolors[c], &colors[c])); 9370588280cSMatthew G. Knepley } 9385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 9390588280cSMatthew G. Knepley if (!useColors) { 9400588280cSMatthew G. Knepley numLColors = 4; 9415f80ce2aSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) CHKERRQ(PetscStrallocpy(deflcolors[c], &lcolors[c])); 9420588280cSMatthew G. Knepley } 9435f80ce2aSJacob Faibussowitsch CHKERRQ(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); 9455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 9462c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg && plotEdges && depth < dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 947202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 9485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 949fe1cc32dSStefano Zampini 950fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 9515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 9525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 955fe1cc32dSStefano Zampini if (lflg) { 956fe1cc32dSStefano Zampini DMLabel lbl; 957fe1cc32dSStefano Zampini 9585f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, lname, &lbl)); 959fe1cc32dSStefano Zampini if (lbl) { 960fe1cc32dSStefano Zampini PetscInt val, defval; 961fe1cc32dSStefano Zampini 9625f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetDefaultValue(lbl, &defval)); 9635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(pEnd-pStart, &wp)); 964fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 965fe1cc32dSStefano Zampini PetscInt *closure = NULL; 966fe1cc32dSStefano Zampini PetscInt closureSize; 967fe1cc32dSStefano Zampini 9685f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(lbl, c, &val)); 969fe1cc32dSStefano Zampini if (val == defval) continue; 970fe1cc32dSStefano Zampini 9715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 972fe1cc32dSStefano Zampini for (p = 0; p < closureSize*2; p += 2) { 9735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(wp, closure[p] - pStart)); 974fe1cc32dSStefano Zampini } 9755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 976fe1cc32dSStefano Zampini } 977fe1cc32dSStefano Zampini } 978fe1cc32dSStefano Zampini } 979fe1cc32dSStefano Zampini 9805f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9815f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) dm, &name)); 9835f80ce2aSJacob Faibussowitsch CHKERRQ(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) { 9905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 991770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 992770b213bSMatthew G Knepley if (p > 0 && p == size-1) { 9935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p)); 994770b213bSMatthew G Knepley } else if (p > 0) { 9955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p)); 996770b213bSMatthew G Knepley } 9975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p)); 998770b213bSMatthew G Knepley } 9995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 10000588280cSMatthew G. Knepley } 1001b7f6ffafSMatthew G. Knepley if (drawHasse) { 1002b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 1003b7f6ffafSMatthew G. Knepley 10045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart)); 10055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1)); 10065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart)); 10075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.)); 10085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart)); 10095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1)); 10105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.)); 10115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart)); 10125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart)); 10135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1)); 10145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart)); 10155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.)); 1016b7f6ffafSMatthew G. Knepley } 10175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale)); 1018fe1cc32dSStefano Zampini 1019552f7358SJed Brown /* Plot vertices */ 10205f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 10215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(viewer)); 1022552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1023552f7358SJed Brown PetscInt off, dof, d; 10240588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1025552f7358SJed Brown 1026fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,v - pStart)) continue; 10275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(coordSection, v, &dof)); 10285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, v, &off)); 10295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 10305f80ce2aSJacob Faibussowitsch PetscCheck(dof <= 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 10310588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10320588280cSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1033c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 10340588280cSMatthew G. Knepley } 10350588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 10360588280cSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1037552f7358SJed Brown for (d = 0; d < dof; ++d) { 10385f80ce2aSJacob Faibussowitsch if (d > 0) CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d])); 1040552f7358SJed Brown } 1041b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0%numColors]; 1042b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 10430588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10440588280cSMatthew G. Knepley PetscInt val; 10455f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabelValue(dm, names[l], v, &val)); 10460588280cSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 10470588280cSMatthew G. Knepley } 1048b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 10495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v)); 1050b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 10515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 1052b7f6ffafSMatthew G. Knepley } else { 10535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank)); 10540588280cSMatthew G. Knepley } 1055552f7358SJed Brown } 10565f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 10575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(viewer)); 1058b7f6ffafSMatthew G. Knepley /* Plot edges */ 1059b7f6ffafSMatthew G. Knepley if (plotEdges) { 10605f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 10615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1062b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1063b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1064b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1065b7f6ffafSMatthew G. Knepley 1066b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp,e - pStart)) continue; 10675f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, e, &coneSize)); 10682c71b3e2SJacob Faibussowitsch PetscCheckFalse(coneSize != 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 10695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, e, &cone)); 10705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(coordSection, cone[0], &dof)); 10715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, cone[0], &offA)); 10725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, cone[1], &offB)); 10735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1074b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1075b7f6ffafSMatthew G. Knepley tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 1076b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1077b7f6ffafSMatthew G. Knepley } 1078b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1079b7f6ffafSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1080b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10815f80ce2aSJacob Faibussowitsch if (d > 0) CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 10825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1083b7f6ffafSMatthew G. Knepley } 1084b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1%numColors]; 1085b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 1086b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1087b7f6ffafSMatthew G. Knepley PetscInt val; 10885f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabelValue(dm, names[l], v, &val)); 1089b7f6ffafSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 1090b7f6ffafSMatthew G. Knepley } 10915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e)); 1092b7f6ffafSMatthew G. Knepley } 10935f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 10945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(viewer)); 10955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1096b7f6ffafSMatthew G. Knepley } 1097846a3e8bSMatthew G. Knepley /* Plot cells */ 1098b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1099846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1100846a3e8bSMatthew G. Knepley const PetscInt *cone; 1101846a3e8bSMatthew G. Knepley 1102fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1103846a3e8bSMatthew G. Knepley color = colors[rank%numColors]; 1104846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1105846a3e8bSMatthew G. Knepley PetscInt val; 11065f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabelValue(dm, names[l], e, &val)); 1107846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 1108846a3e8bSMatthew G. Knepley } 11095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, e, &cone)); 11105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank)); 1111846a3e8bSMatthew G. Knepley } 1112846a3e8bSMatthew G. Knepley } else { 1113b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1114846a3e8bSMatthew G. Knepley 1115b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1116b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1117fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 11185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, c, &ct)); 1119b7f6ffafSMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1120b7f6ffafSMatthew G. Knepley ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1121b7f6ffafSMatthew G. Knepley ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1122b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1123b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1124b7f6ffafSMatthew G. Knepley 11255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 11265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize)); 1127b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1128b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1129b7f6ffafSMatthew G. Knepley 11305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, cone[e], &econe)); 11315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d) -- (%D_%d);\n", colors[rank%numColors], econe[0], rank, cone[e], rank, econe[1], rank)); 1132b7f6ffafSMatthew G. Knepley } 1133b7f6ffafSMatthew G. Knepley } else { 1134b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1135b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1136b7f6ffafSMatthew G. Knepley 11375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1138846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 1139846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1140846a3e8bSMatthew G. Knepley 1141b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1142846a3e8bSMatthew G. Knepley } 11435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors])); 1144b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1145b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v%Nv]; 1146b7f6ffafSMatthew G. Knepley 1147b7f6ffafSMatthew G. Knepley if (v > 0) { 1148b7f6ffafSMatthew G. Knepley if (plotEdges) { 1149b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1150b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1151b7f6ffafSMatthew G. Knepley 1152b7f6ffafSMatthew G. Knepley endpoints[0] = closure[v-1]; endpoints[1] = vertex; 11535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 11542c71b3e2SJacob Faibussowitsch PetscCheckFalse(ne != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]); 11555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank)); 11565f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 1157b7f6ffafSMatthew G. Knepley } else { 11585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1159b7f6ffafSMatthew G. Knepley } 1160b7f6ffafSMatthew G. Knepley } 11615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank)); 1162b7f6ffafSMatthew G. Knepley } 11635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 11645f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1165846a3e8bSMatthew G. Knepley } 1166846a3e8bSMatthew G. Knepley } 1167b7f6ffafSMatthew G. Knepley } 11685f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 1169846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1170846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1171846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1172846a3e8bSMatthew G. Knepley PetscInt *closure = NULL; 1173846a3e8bSMatthew G. Knepley PetscInt closureSize, dof, d, n = 0; 1174846a3e8bSMatthew G. Knepley 1175fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,c - pStart)) continue; 11765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 11775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1178846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 1179846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1180846a3e8bSMatthew G. Knepley PetscInt off; 1181846a3e8bSMatthew G. Knepley 1182846a3e8bSMatthew G. Knepley if ((point < vStart) || (point >= vEnd)) continue; 11835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(coordSection, point, &dof)); 11845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, point, &off)); 1185846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1186846a3e8bSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1187846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1188846a3e8bSMatthew G. Knepley } 1189846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1190846a3e8bSMatthew G. Knepley if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1191846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1192846a3e8bSMatthew G. Knepley ++n; 1193846a3e8bSMatthew G. Knepley } 1194846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 11955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1196846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11975f80ce2aSJacob Faibussowitsch if (d > 0) CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d])); 1199846a3e8bSMatthew G. Knepley } 1200b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth%numColors]; 1201b7f6ffafSMatthew G. Knepley else color = colors[rank%numColors]; 1202846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1203846a3e8bSMatthew G. Knepley PetscInt val; 12045f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabelValue(dm, names[l], c, &val)); 1205846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1206846a3e8bSMatthew G. Knepley } 1207b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 12085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c)); 1209b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 12105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 1211b7f6ffafSMatthew G. Knepley } else { 12125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank)); 1213846a3e8bSMatthew G. Knepley } 1214846a3e8bSMatthew G. Knepley } 12155f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 1216b7f6ffafSMatthew G. Knepley if (drawHasse) { 1217b7f6ffafSMatthew G. Knepley color = colors[depth%numColors]; 12185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 12195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 12205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "{\n")); 12215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 12225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "}\n")); 1223552f7358SJed Brown 1224b7f6ffafSMatthew G. Knepley color = colors[1%numColors]; 12255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 12265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 12275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "{\n")); 12285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 12295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "}\n")); 1230b7f6ffafSMatthew G. Knepley 1231b7f6ffafSMatthew G. Knepley color = colors[0%numColors]; 12325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 12335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 12345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "{\n")); 12355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 12365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "}\n")); 1237b7f6ffafSMatthew G. Knepley 1238b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1239b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1240b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1241b7f6ffafSMatthew G. Knepley 12425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 12435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 1244b7f6ffafSMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 12455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank)); 1246552f7358SJed Brown } 12470588280cSMatthew G. Knepley } 12480588280cSMatthew G. Knepley } 12495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(viewer)); 12505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopSynchronized(viewer)); 12515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 12525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name)); 12535f80ce2aSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) CHKERRQ(PetscFree(names[l])); 12545f80ce2aSJacob Faibussowitsch for (c = 0; c < numColors; ++c) CHKERRQ(PetscFree(colors[c])); 12555f80ce2aSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) CHKERRQ(PetscFree(lcolors[c])); 12565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(names, colors, lcolors)); 12575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&wp)); 12580f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 12590f7d6e4aSStefano Zampini Vec cown,acown; 12600f7d6e4aSStefano Zampini VecScatter sct; 12610f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 12620f7d6e4aSStefano Zampini IS gid,acis; 12630f7d6e4aSStefano Zampini MPI_Comm comm,ncomm = MPI_COMM_NULL; 12640f7d6e4aSStefano Zampini MPI_Group ggroup,ngroup; 12650f7d6e4aSStefano Zampini PetscScalar *array,nid; 12660f7d6e4aSStefano Zampini const PetscInt *idxs; 12670f7d6e4aSStefano Zampini PetscInt *idxs2,*start,*adjacency,*work; 12680f7d6e4aSStefano Zampini PetscInt64 lm[3],gm[3]; 12690f7d6e4aSStefano Zampini PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 12700f7d6e4aSStefano Zampini PetscMPIInt d1,d2,rank; 12710f7d6e4aSStefano Zampini 12725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm)); 12735f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm,&rank)); 1274b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 12755f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm)); 12760f7d6e4aSStefano Zampini #endif 12770f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 12785f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_group(comm,&ggroup)); 12795f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_group(ncomm,&ngroup)); 12800f7d6e4aSStefano Zampini d1 = 0; 12815f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2)); 12820f7d6e4aSStefano Zampini nid = d2; 12835f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Group_free(&ggroup)); 12845f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Group_free(&ngroup)); 12855f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_free(&ncomm)); 12860f7d6e4aSStefano Zampini } else nid = 0.0; 12870f7d6e4aSStefano Zampini 12880f7d6e4aSStefano Zampini /* Get connectivity */ 12895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetVTKCellHeight(dm,&cellHeight)); 12905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid)); 12910f7d6e4aSStefano Zampini 12920f7d6e4aSStefano Zampini /* filter overlapped local cells */ 12935f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd)); 12945f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(gid,&idxs)); 12955f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(gid,&cum)); 12965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(cum,&idxs2)); 12970f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 12980f7d6e4aSStefano Zampini if (idxs[c-cStart] < 0) continue; 12990f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c-cStart]; 13000f7d6e4aSStefano Zampini } 13015f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(gid,&idxs)); 13022c71b3e2SJacob Faibussowitsch PetscCheckFalse(numVertices != cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 13035f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&gid)); 13045f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid)); 13050f7d6e4aSStefano Zampini 13060f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 13075f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis)); 13085f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown)); 13095f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown)); 13105f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(cown,&array)); 13110f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 13125f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(cown,&array)); 13135f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(cown,acis,acown,NULL,&sct)); 13145f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD)); 13155f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD)); 13165f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&acis)); 13175f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&sct)); 13185f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&cown)); 13190f7d6e4aSStefano Zampini 13200f7d6e4aSStefano Zampini /* compute edgeCut */ 13210f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 13225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(cum,&work)); 13235f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(gid,&g2l)); 13245f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH)); 13255f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&gid)); 13265f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(acown,&array)); 13270f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 13280f7d6e4aSStefano Zampini PetscInt totl; 13290f7d6e4aSStefano Zampini 13300f7d6e4aSStefano Zampini totl = start[c+1]-start[c]; 13315f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work)); 13320f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 13330f7d6e4aSStefano Zampini if (work[i] < 0) { 13340f7d6e4aSStefano Zampini ect += 1; 13350f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 13360f7d6e4aSStefano Zampini } 13370f7d6e4aSStefano Zampini } 13380f7d6e4aSStefano Zampini } 13395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(work)); 13405f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(acown,&array)); 13410f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 13420f7d6e4aSStefano Zampini lm[1] = -numVertices; 13435f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm)); 13445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0])); 13450f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 13460f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 13470f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 13485f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm)); 13495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2])); 1350b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 13515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.)); 13520f7d6e4aSStefano Zampini #else 13535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0)); 13540f7d6e4aSStefano Zampini #endif 13555f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&g2l)); 13565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(start)); 13575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjacency)); 13585f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&acown)); 1359552f7358SJed Brown } else { 1360412e9a14SMatthew G. Knepley const char *name; 1361d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1362412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1363d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1364ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 13659318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1366412e9a14SMatthew G. Knepley MPI_Comm comm; 1367412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1368552f7358SJed Brown 13695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 13705f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 13715f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 13725f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 13735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight)); 13745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) dm, &name)); 13755f80ce2aSJacob Faibussowitsch if (name) CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 13765f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s")); 13775f80ce2aSJacob Faibussowitsch if (cellHeight) CHKERRQ(PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight)); 13785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &locDepth)); 13795f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 13805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd)); 1381d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 13825f80ce2aSJacob Faibussowitsch if (size < maxSize) CHKERRQ(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 13835f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1384412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1385412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1386412e9a14SMatthew G. Knepley 13875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 13885f80ce2aSJacob Faibussowitsch if (pStart < pEnd) CHKERRQ(DMPlexGetCellType(dm, pStart, &ct0)); 1389412e9a14SMatthew G. Knepley ict = ct0; 13905f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1391412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType) ict; 1392412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1393412e9a14SMatthew G. Knepley DMPolytopeType ct; 1394412e9a14SMatthew G. Knepley 13955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, p, &ct)); 1396412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1397412e9a14SMatthew G. Knepley else ++Nc[1]; 1398412e9a14SMatthew G. Knepley } 1399ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 14005f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 14015f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 14025f80ce2aSJacob Faibussowitsch if (d == depth) CHKERRMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 14035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " Number of %D-cells per rank:", (depth == 1) && d ? dim : d)); 1404834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1405dd400576SPatrick Sanan if (rank == 0) { 14065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p])); 14075f80ce2aSJacob Faibussowitsch if (hybsizes[p] > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p])); 14085f80ce2aSJacob Faibussowitsch if (ghostsizes[p] > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p])); 1409834065abSMatthew G. Knepley } 1410cbb7f117SMark Adams } 1411ca7bf7eeSMatthew G. Knepley } else { 1412ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1413ca7bf7eeSMatthew G. Knepley 1414ca7bf7eeSMatthew G. Knepley locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1]; 14155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 1416ca7bf7eeSMatthew G. Knepley locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1]; 14175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1418ca7bf7eeSMatthew G. Knepley if (d == depth) { 1419ca7bf7eeSMatthew G. Knepley locMinMax[0] = gcNum; locMinMax[1] = gcNum; 14205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1421ca7bf7eeSMatthew G. Knepley } 14225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " Min/Max of %D-cells per rank:", (depth == 1) && d ? dim : d)); 14235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 14245f80ce2aSJacob Faibussowitsch if (hybsizes[0] > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 14255f80ce2aSJacob Faibussowitsch if (ghostsizes[0] > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1426ca7bf7eeSMatthew G. Knepley } 14275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\n")); 1428552f7358SJed Brown } 14295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(sizes, hybsizes, ghostsizes)); 14309318fe57SMatthew G. Knepley { 14319318fe57SMatthew G. Knepley const PetscReal *maxCell; 14329318fe57SMatthew G. Knepley const PetscReal *L; 14339318fe57SMatthew G. Knepley const DMBoundaryType *bd; 14349318fe57SMatthew G. Knepley PetscBool per, localized; 14359318fe57SMatthew G. Knepley 14365f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dm, &per, &maxCell, &L, &bd)); 14375f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocalized(dm, &localized)); 14389318fe57SMatthew G. Knepley if (per) { 14395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Periodic mesh (")); 14405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 14419318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 14425f80ce2aSJacob Faibussowitsch if (bd && d > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, ", ")); 14435f80ce2aSJacob Faibussowitsch if (bd) CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]])); 14449318fe57SMatthew G. Knepley } 14455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized")); 14465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14479318fe57SMatthew G. Knepley } 14489318fe57SMatthew G. Knepley } 14495f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumLabels(dm, &numLabels)); 14505f80ce2aSJacob Faibussowitsch if (numLabels) CHKERRQ(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1451a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1452a57dd577SMatthew G Knepley DMLabel label; 1453a57dd577SMatthew G Knepley const char *name; 1454a57dd577SMatthew G Knepley IS valueIS; 1455a57dd577SMatthew G Knepley const PetscInt *values; 1456a57dd577SMatthew G Knepley PetscInt numValues, v; 1457a57dd577SMatthew G Knepley 14585f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabelName(dm, l, &name)); 14595f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, name, &label)); 14605f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetNumValues(label, &numValues)); 14615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues)); 14625f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValueIS(label, &valueIS)); 14635f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(valueIS, &values)); 14645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1465a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1466a57dd577SMatthew G Knepley PetscInt size; 1467a57dd577SMatthew G Knepley 14685f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumSize(label, values[v], &size)); 14695f80ce2aSJacob Faibussowitsch if (v > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, ", ")); 14705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size)); 1471a57dd577SMatthew G Knepley } 14725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, ")\n")); 14735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 14745f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(valueIS, &values)); 14755f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&valueIS)); 1476a57dd577SMatthew G Knepley } 1477c1cad2e7SMatthew G. Knepley { 1478c1cad2e7SMatthew G. Knepley char **labelNames; 1479c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1480c1cad2e7SMatthew G. Knepley PetscBool flg; 1481c1cad2e7SMatthew G. Knepley 14825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Nl, &labelNames)); 14835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1484c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1485c1cad2e7SMatthew G. Knepley DMLabel label; 1486c1cad2e7SMatthew G. Knepley 14875f80ce2aSJacob Faibussowitsch CHKERRQ(DMHasLabel(dm, labelNames[l], &flg)); 1488c1cad2e7SMatthew G. Knepley if (flg) { 14895f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, labelNames[l], &label)); 14905f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelView(label, viewer)); 1491c1cad2e7SMatthew G. Knepley } 14925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(labelNames[l])); 1493c1cad2e7SMatthew G. Knepley } 14945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(labelNames)); 1495c1cad2e7SMatthew G. Knepley } 149634aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 149734aa8a36SMatthew G. Knepley if (dm->Nf) { 149834aa8a36SMatthew G. Knepley PetscInt f; 149934aa8a36SMatthew G. Knepley 150034aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 150134aa8a36SMatthew G. Knepley const char *name; 150234aa8a36SMatthew G. Knepley 15035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName(dm->fields[f].disc, &name)); 15045f80ce2aSJacob Faibussowitsch if (numLabels) CHKERRQ(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 15055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(viewer)); 15065f80ce2aSJacob Faibussowitsch if (dm->fields[f].label) CHKERRQ(DMLabelView(dm->fields[f].label, viewer)); 150734aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 15085f80ce2aSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) CHKERRQ(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 15095f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 151034aa8a36SMatthew G. Knepley } else { 15115f80ce2aSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) CHKERRQ(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 15125f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 151334aa8a36SMatthew G. Knepley } 15145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(viewer)); 151534aa8a36SMatthew G. Knepley } 151634aa8a36SMatthew G. Knepley } 15175f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(dm, &cdm)); 15188e7ff633SMatthew G. Knepley if (cdm) { 15195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(viewer)); 15205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexView_Ascii(cdm, viewer)); 15215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(viewer)); 15228e7ff633SMatthew G. Knepley } 1523552f7358SJed Brown } 1524552f7358SJed Brown PetscFunctionReturn(0); 1525552f7358SJed Brown } 1526552f7358SJed Brown 1527e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1528e5c487bfSMatthew G. Knepley { 1529e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1530e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1531a12d352dSMatthew G. Knepley PetscInt cdim; 1532e5c487bfSMatthew G. Knepley 1533e5c487bfSMatthew G. Knepley PetscFunctionBegin; 15345f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 15355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cell, &ct)); 15365f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &cdim)); 1537e5c487bfSMatthew G. Knepley switch (ct) { 1538a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1539a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1540a12d352dSMatthew G. Knepley switch (cdim) { 1541a12d352dSMatthew G. Knepley case 1: 1542a12d352dSMatthew G. Knepley { 1543a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1544a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1545a12d352dSMatthew G. Knepley 15465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 15475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK)); 15485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK)); 1549a12d352dSMatthew G. Knepley } 1550a12d352dSMatthew G. Knepley break; 1551a12d352dSMatthew G. Knepley case 2: 1552a12d352dSMatthew G. Knepley { 1553a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1554a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1555a12d352dSMatthew G. Knepley const PetscReal l = 0.1/PetscSqrtReal(dx*dx + dy*dy); 1556a12d352dSMatthew G. Knepley 15575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15585f80ce2aSJacob Faibussowitsch CHKERRQ(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)); 15595f80ce2aSJacob Faibussowitsch CHKERRQ(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)); 1560a12d352dSMatthew G. Knepley } 1561a12d352dSMatthew G. Knepley break; 156298921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %D", cdim); 1563a12d352dSMatthew G. Knepley } 1564a12d352dSMatthew G. Knepley break; 1565e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 15665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1567e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1568e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15695f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1573e5c487bfSMatthew G. Knepley break; 1574e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 15755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1576e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1577e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15785f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1580e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1581e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 15825f80ce2aSJacob Faibussowitsch PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2)); 15835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 15845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 15855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 15865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1587e5c487bfSMatthew G. Knepley break; 158898921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1589e5c487bfSMatthew G. Knepley } 1590e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1591e5c487bfSMatthew G. Knepley } 1592e5c487bfSMatthew G. Knepley 1593e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1594e5c487bfSMatthew G. Knepley { 1595e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1596e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1597e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1598e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1599e5c487bfSMatthew G. Knepley 1600e5c487bfSMatthew G. Knepley PetscFunctionBegin; 16015f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 16025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cell, &ct)); 1603e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1604e5c487bfSMatthew G. Knepley switch (ct) { 1605e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 1606e5c487bfSMatthew G. Knepley { 1607e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1608e5c487bfSMatthew G. Knepley 1609e5c487bfSMatthew G. Knepley for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1610e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1611e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e*2+0]; 1612e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e*2+1]; 1613e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1614e5c487bfSMatthew G. Knepley refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1615e5c487bfSMatthew G. Knepley refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1616e5c487bfSMatthew G. Knepley } 16175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords)); 1618e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 16195f80ce2aSJacob Faibussowitsch CHKERRQ(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)); 16205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawLine(draw, edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], PETSC_DRAW_BLACK)); 1621e5c487bfSMatthew G. Knepley } 1622e5c487bfSMatthew G. Knepley } 1623e5c487bfSMatthew G. Knepley } 1624e5c487bfSMatthew G. Knepley break; 162598921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1626e5c487bfSMatthew G. Knepley } 1627e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1628e5c487bfSMatthew G. Knepley } 1629e5c487bfSMatthew G. Knepley 16307cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1631e412dcbdSMatthew G. Knepley { 1632e412dcbdSMatthew G. Knepley PetscDraw draw; 1633e412dcbdSMatthew G. Knepley DM cdm; 1634e412dcbdSMatthew G. Knepley PetscSection coordSection; 1635e412dcbdSMatthew G. Knepley Vec coordinates; 1636e412dcbdSMatthew G. Knepley const PetscScalar *coords; 163729494db1SLisandro Dalcin PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1638e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1639e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1640e5c487bfSMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1641e412dcbdSMatthew G. Knepley 1642e412dcbdSMatthew G. Knepley PetscFunctionBegin; 16435f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &dim)); 16442c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim > 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 16455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 16465f80ce2aSJacob Faibussowitsch if (!drawAffine) CHKERRQ(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords)); 16475f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 16485f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(cdm, &coordSection)); 16495f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates)); 16505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 16515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1652e412dcbdSMatthew G. Knepley 16535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDrawGetDraw(viewer, 0, &draw)); 16545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawIsNull(draw, &isnull)); 1655e412dcbdSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 16565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawSetTitle(draw, "Mesh")); 1657e412dcbdSMatthew G. Knepley 16585f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(coordinates, &N)); 16595f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(coordinates, &coords)); 1660e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 16610c81f2a8SMatthew G. Knepley bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 16620c81f2a8SMatthew G. Knepley bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1663e412dcbdSMatthew G. Knepley } 16645f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(coordinates, &coords)); 16655f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm))); 16665f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm))); 16675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 16685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawClear(draw)); 1669e412dcbdSMatthew G. Knepley 1670cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1671cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1672ba2698f1SMatthew G. Knepley PetscInt numCoords; 1673cf3064d3SMatthew G. Knepley 16745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords)); 1675e5c487bfSMatthew G. Knepley if (drawAffine) { 16765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDrawCell(dm, draw, c, coords)); 1677e5c487bfSMatthew G. Knepley } else { 16785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1679cf3064d3SMatthew G. Knepley } 16805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords)); 1681cf3064d3SMatthew G. Knepley } 16825f80ce2aSJacob Faibussowitsch if (!drawAffine) CHKERRQ(PetscFree2(refCoords, edgeCoords)); 16835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawFlush(draw)); 16845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawPause(draw)); 16855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawSave(draw)); 1686e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 1687e412dcbdSMatthew G. Knepley } 1688e412dcbdSMatthew G. Knepley 16891e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 16901e50132fSMatthew G. Knepley #include <exodusII.h> 16916823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 16921e50132fSMatthew G. Knepley #endif 16931e50132fSMatthew G. Knepley 1694552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1695552f7358SJed Brown { 16961e50132fSMatthew G. Knepley PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1697002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1698552f7358SJed Brown 1699552f7358SJed Brown PetscFunctionBegin; 1700552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1701552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii)); 17035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 17045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 17055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 17065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 17075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus)); 1708552f7358SJed Brown if (iascii) { 17098135c375SStefano Zampini PetscViewerFormat format; 17105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 17118135c375SStefano Zampini if (format == PETSC_VIEWER_ASCII_GLVIS) { 17125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexView_GLVis(dm, viewer)); 17138135c375SStefano Zampini } else { 17145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexView_Ascii(dm, viewer)); 17158135c375SStefano Zampini } 1716c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1717c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 17185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexView_HDF5_Internal(dm, viewer)); 1719c6ccd67eSMatthew G. Knepley #else 1720c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1721552f7358SJed Brown #endif 1722e412dcbdSMatthew G. Knepley } else if (isvtk) { 17235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVTKWriteAll((PetscObject) dm,viewer)); 1724e412dcbdSMatthew G. Knepley } else if (isdraw) { 17255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexView_Draw(dm, viewer)); 17268135c375SStefano Zampini } else if (isglvis) { 17275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexView_GLVis(dm, viewer)); 17281e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 17291e50132fSMatthew G. Knepley } else if (isexodus) { 17306823f3c5SBlaise Bourdin /* 17316823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 17326823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 17336823f3c5SBlaise Bourdin with ID 1, containig all cells. 17346823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 17356823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 17366823f3c5SBlaise Bourdin */ 17376823f3c5SBlaise Bourdin PetscInt numCS; 17385f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabelSize(dm,"Cell Sets",&numCS)); 17396823f3c5SBlaise Bourdin if (!numCS) { 17401e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 17415f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "Cell Sets")); 17425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 17435f80ce2aSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) CHKERRQ(DMSetLabelValue(dm, "Cell Sets", c, 1)); 17446823f3c5SBlaise Bourdin } 17455f80ce2aSJacob Faibussowitsch CHKERRQ(DMView_PlexExodusII(dm, viewer)); 17461e50132fSMatthew G. Knepley #endif 174762201deeSVaclav Hapla } else { 174898921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1749fcf6c8fdSToby Isaac } 1750cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 17515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg)); 1752cb3ba0daSMatthew G. Knepley if (flg) { 1753cb3ba0daSMatthew G. Knepley Vec ranks; 17545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateRankField(dm, &ranks)); 17555f80ce2aSJacob Faibussowitsch CHKERRQ(VecView(ranks, viewer)); 17565f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&ranks)); 1757cb3ba0daSMatthew G. Knepley } 1758002a2709SMatthew G. Knepley /* Optionally view a label */ 17595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1760002a2709SMatthew G. Knepley if (flg) { 1761002a2709SMatthew G. Knepley DMLabel label; 1762002a2709SMatthew G. Knepley Vec val; 1763002a2709SMatthew G. Knepley 17645f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, name, &label)); 176528b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 17665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateLabelField(dm, label, &val)); 17675f80ce2aSJacob Faibussowitsch CHKERRQ(VecView(val, viewer)); 17685f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&val)); 1769002a2709SMatthew G. Knepley } 1770552f7358SJed Brown PetscFunctionReturn(0); 1771552f7358SJed Brown } 1772552f7358SJed Brown 17737f96f51bSksagiyam /*@ 17747f96f51bSksagiyam DMPlexTopologyView - Saves a DMPlex topology into a file 17757f96f51bSksagiyam 17767f96f51bSksagiyam Collective on DM 17777f96f51bSksagiyam 17787f96f51bSksagiyam Input Parameters: 17797f96f51bSksagiyam + dm - The DM whose topology is to be saved 17807f96f51bSksagiyam - viewer - The PetscViewer for saving 17817f96f51bSksagiyam 17827f96f51bSksagiyam Level: advanced 17837f96f51bSksagiyam 17847f96f51bSksagiyam .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 17857f96f51bSksagiyam @*/ 17867f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 17877f96f51bSksagiyam { 17887f96f51bSksagiyam PetscBool ishdf5; 17897f96f51bSksagiyam 17907f96f51bSksagiyam PetscFunctionBegin; 17917f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17927f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 17945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0)); 17957f96f51bSksagiyam if (ishdf5) { 17967f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 17977f96f51bSksagiyam PetscViewerFormat format; 17985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 17997f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18007f96f51bSksagiyam IS globalPointNumbering; 18017f96f51bSksagiyam 18025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18045f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&globalPointNumbering)); 180598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 18067f96f51bSksagiyam #else 18077f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 18087f96f51bSksagiyam #endif 18097f96f51bSksagiyam } 18105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0)); 18117f96f51bSksagiyam PetscFunctionReturn(0); 18127f96f51bSksagiyam } 18137f96f51bSksagiyam 181477b8e257Sksagiyam /*@ 181577b8e257Sksagiyam DMPlexCoordinatesView - Saves DMPlex coordinates into a file 181677b8e257Sksagiyam 181777b8e257Sksagiyam Collective on DM 181877b8e257Sksagiyam 181977b8e257Sksagiyam Input Parameters: 182077b8e257Sksagiyam + dm - The DM whose coordinates are to be saved 182177b8e257Sksagiyam - viewer - The PetscViewer for saving 182277b8e257Sksagiyam 182377b8e257Sksagiyam Level: advanced 182477b8e257Sksagiyam 182577b8e257Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 182677b8e257Sksagiyam @*/ 182777b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 182877b8e257Sksagiyam { 182977b8e257Sksagiyam PetscBool ishdf5; 183077b8e257Sksagiyam 183177b8e257Sksagiyam PetscFunctionBegin; 183277b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 183377b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 18355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0)); 183677b8e257Sksagiyam if (ishdf5) { 183777b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 183877b8e257Sksagiyam PetscViewerFormat format; 18395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 184077b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 184298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 184377b8e257Sksagiyam #else 184477b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 184577b8e257Sksagiyam #endif 184677b8e257Sksagiyam } 18475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0)); 184877b8e257Sksagiyam PetscFunctionReturn(0); 184977b8e257Sksagiyam } 185077b8e257Sksagiyam 1851bd6565f1Sksagiyam /*@ 1852bd6565f1Sksagiyam DMPlexLabelsView - Saves DMPlex labels into a file 1853bd6565f1Sksagiyam 1854bd6565f1Sksagiyam Collective on DM 1855bd6565f1Sksagiyam 1856bd6565f1Sksagiyam Input Parameters: 1857bd6565f1Sksagiyam + dm - The DM whose labels are to be saved 1858bd6565f1Sksagiyam - viewer - The PetscViewer for saving 1859bd6565f1Sksagiyam 1860bd6565f1Sksagiyam Level: advanced 1861bd6565f1Sksagiyam 1862bd6565f1Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1863bd6565f1Sksagiyam @*/ 1864bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1865bd6565f1Sksagiyam { 1866bd6565f1Sksagiyam PetscBool ishdf5; 1867bd6565f1Sksagiyam 1868bd6565f1Sksagiyam PetscFunctionBegin; 1869bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1870bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 18715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 18725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0)); 1873bd6565f1Sksagiyam if (ishdf5) { 1874bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 1875bd6565f1Sksagiyam IS globalPointNumbering; 1876bd6565f1Sksagiyam PetscViewerFormat format; 1877bd6565f1Sksagiyam 18785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 1879bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 18805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 18815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 18825f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&globalPointNumbering)); 188398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1884bd6565f1Sksagiyam #else 1885bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1886bd6565f1Sksagiyam #endif 1887bd6565f1Sksagiyam } 18885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0)); 1889bd6565f1Sksagiyam PetscFunctionReturn(0); 1890bd6565f1Sksagiyam } 1891bd6565f1Sksagiyam 1892021affd3Sksagiyam /*@ 1893021affd3Sksagiyam DMPlexSectionView - Saves a section associated with a DMPlex 1894021affd3Sksagiyam 1895021affd3Sksagiyam Collective on DM 1896021affd3Sksagiyam 1897021affd3Sksagiyam Input Parameters: 1898021affd3Sksagiyam + dm - The DM that contains the topology on which the section to be saved is defined 1899021affd3Sksagiyam . viewer - The PetscViewer for saving 1900021affd3Sksagiyam - sectiondm - The DM that contains the section to be saved 1901021affd3Sksagiyam 1902021affd3Sksagiyam Level: advanced 1903021affd3Sksagiyam 1904021affd3Sksagiyam Notes: 1905021affd3Sksagiyam 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. 1906021affd3Sksagiyam 1907021affd3Sksagiyam 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. 1908021affd3Sksagiyam 1909021affd3Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1910021affd3Sksagiyam @*/ 1911021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1912021affd3Sksagiyam { 1913021affd3Sksagiyam PetscBool ishdf5; 1914021affd3Sksagiyam 1915021affd3Sksagiyam PetscFunctionBegin; 1916021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1917021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1918021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 19205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0)); 1921021affd3Sksagiyam if (ishdf5) { 1922021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 19235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 1924021affd3Sksagiyam #else 1925021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1926021affd3Sksagiyam #endif 1927021affd3Sksagiyam } 19285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0)); 1929021affd3Sksagiyam PetscFunctionReturn(0); 1930021affd3Sksagiyam } 1931021affd3Sksagiyam 19323e97647fSksagiyam /*@ 19333e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 19343e97647fSksagiyam 19353e97647fSksagiyam Collective on DM 19363e97647fSksagiyam 19373e97647fSksagiyam Input Parameters: 19383e97647fSksagiyam + dm - The DM that represents the topology 19393e97647fSksagiyam . viewer - The PetscViewer to save data with 19403e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined 19413e97647fSksagiyam - vec - The global vector to be saved 19423e97647fSksagiyam 19433e97647fSksagiyam Level: advanced 19443e97647fSksagiyam 19453e97647fSksagiyam Notes: 19463e97647fSksagiyam 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. 19473e97647fSksagiyam 19483e97647fSksagiyam Typical calling sequence 19493e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 19503e97647fSksagiyam $ DMSetType(dm, DMPLEX); 19513e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 19523e97647fSksagiyam $ DMClone(dm, §iondm); 19533e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 19543e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 19553e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 19563e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 19573e97647fSksagiyam $ PetscSectionSetUp(section); 19583e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 19593e97647fSksagiyam $ PetscSectionDestroy(§ion); 19603e97647fSksagiyam $ DMGetGlobalVector(sectiondm, &vec); 19613e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 19623e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 19633e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 19643e97647fSksagiyam $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 19653e97647fSksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 19663e97647fSksagiyam $ DMDestroy(§iondm); 19673e97647fSksagiyam $ DMDestroy(&dm); 19683e97647fSksagiyam 19693e97647fSksagiyam .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 19703e97647fSksagiyam @*/ 19713e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 19723e97647fSksagiyam { 19733e97647fSksagiyam PetscBool ishdf5; 19743e97647fSksagiyam 19753e97647fSksagiyam PetscFunctionBegin; 19763e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19773e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19783e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 19793e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 19803e97647fSksagiyam /* Check consistency */ 19813e97647fSksagiyam { 19823e97647fSksagiyam PetscSection section; 19833e97647fSksagiyam PetscBool includesConstraints; 19843e97647fSksagiyam PetscInt m, m1; 19853e97647fSksagiyam 19865f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(vec, &m1)); 19875f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(sectiondm, §ion)); 19885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 19895f80ce2aSJacob Faibussowitsch if (includesConstraints) CHKERRQ(PetscSectionGetStorageSize(section, &m)); 19905f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetConstrainedStorageSize(section, &m)); 19912c71b3e2SJacob Faibussowitsch PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 19923e97647fSksagiyam } 19935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0)); 19953e97647fSksagiyam if (ishdf5) { 19963e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 19975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 19983e97647fSksagiyam #else 19993e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20003e97647fSksagiyam #endif 20013e97647fSksagiyam } 20025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0)); 20033e97647fSksagiyam PetscFunctionReturn(0); 20043e97647fSksagiyam } 20053e97647fSksagiyam 20063e97647fSksagiyam /*@ 20073e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 20083e97647fSksagiyam 20093e97647fSksagiyam Collective on DM 20103e97647fSksagiyam 20113e97647fSksagiyam Input Parameters: 20123e97647fSksagiyam + dm - The DM that represents the topology 20133e97647fSksagiyam . viewer - The PetscViewer to save data with 20143e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 20153e97647fSksagiyam - vec - The local vector to be saved 20163e97647fSksagiyam 20173e97647fSksagiyam Level: advanced 20183e97647fSksagiyam 20193e97647fSksagiyam Notes: 20203e97647fSksagiyam 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. 20213e97647fSksagiyam 20223e97647fSksagiyam Typical calling sequence 20233e97647fSksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 20243e97647fSksagiyam $ DMSetType(dm, DMPLEX); 20253e97647fSksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 20263e97647fSksagiyam $ DMClone(dm, §iondm); 20273e97647fSksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 20283e97647fSksagiyam $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 20293e97647fSksagiyam $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 20303e97647fSksagiyam $ PetscSectionSetChart(section, pStart, pEnd); 20313e97647fSksagiyam $ PetscSectionSetUp(section); 20323e97647fSksagiyam $ DMSetLocalSection(sectiondm, section); 20333e97647fSksagiyam $ DMGetLocalVector(sectiondm, &vec); 20343e97647fSksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 20353e97647fSksagiyam $ DMPlexTopologyView(dm, viewer); 20363e97647fSksagiyam $ DMPlexSectionView(dm, viewer, sectiondm); 20373e97647fSksagiyam $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 20383e97647fSksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 20393e97647fSksagiyam $ DMDestroy(§iondm); 20403e97647fSksagiyam $ DMDestroy(&dm); 20413e97647fSksagiyam 20423e97647fSksagiyam .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 20433e97647fSksagiyam @*/ 20443e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 20453e97647fSksagiyam { 20463e97647fSksagiyam PetscBool ishdf5; 20473e97647fSksagiyam 20483e97647fSksagiyam PetscFunctionBegin; 20493e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20503e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20513e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 20523e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 20533e97647fSksagiyam /* Check consistency */ 20543e97647fSksagiyam { 20553e97647fSksagiyam PetscSection section; 20563e97647fSksagiyam PetscBool includesConstraints; 20573e97647fSksagiyam PetscInt m, m1; 20583e97647fSksagiyam 20595f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(vec, &m1)); 20605f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(sectiondm, §ion)); 20615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 20625f80ce2aSJacob Faibussowitsch if (includesConstraints) CHKERRQ(PetscSectionGetStorageSize(section, &m)); 20635f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetConstrainedStorageSize(section, &m)); 20642c71b3e2SJacob Faibussowitsch PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 20653e97647fSksagiyam } 20665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0)); 20683e97647fSksagiyam if (ishdf5) { 20693e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 20705f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 20713e97647fSksagiyam #else 20723e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20733e97647fSksagiyam #endif 20743e97647fSksagiyam } 20755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0)); 20763e97647fSksagiyam PetscFunctionReturn(0); 20773e97647fSksagiyam } 20783e97647fSksagiyam 20792c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 20802c40f234SMatthew G. Knepley { 2081d4f5a9a0SVaclav Hapla PetscBool ishdf5; 20822c40f234SMatthew G. Knepley 20832c40f234SMatthew G. Knepley PetscFunctionBegin; 20842c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20852c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 2087d4f5a9a0SVaclav Hapla if (ishdf5) { 20882c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 20899c48423bSVaclav Hapla PetscViewerFormat format; 20905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 20919c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 20925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2093509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLoad_HDF5_Internal(dm, viewer)); 209598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2096b458e8f1SJose E. Roman PetscFunctionReturn(0); 20972c40f234SMatthew G. Knepley #else 20982c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2099552f7358SJed Brown #endif 210098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2101552f7358SJed Brown } 2102552f7358SJed Brown 2103ea8e1828Sksagiyam /*@ 2104ea8e1828Sksagiyam DMPlexTopologyLoad - Loads a topology into a DMPlex 2105ea8e1828Sksagiyam 2106ea8e1828Sksagiyam Collective on DM 2107ea8e1828Sksagiyam 2108ea8e1828Sksagiyam Input Parameters: 2109ea8e1828Sksagiyam + dm - The DM into which the topology is loaded 2110ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology 2111ea8e1828Sksagiyam 2112dec9e869Sksagiyam Output Parameters: 2113f84dd6b4Sksagiyam . 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 2114dec9e869Sksagiyam 2115ea8e1828Sksagiyam Level: advanced 2116ea8e1828Sksagiyam 2117b08ad5deSksagiyam .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2118ea8e1828Sksagiyam @*/ 2119f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2120ea8e1828Sksagiyam { 2121ea8e1828Sksagiyam PetscBool ishdf5; 2122ea8e1828Sksagiyam 2123ea8e1828Sksagiyam PetscFunctionBegin; 2124ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2125ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2126f84dd6b4Sksagiyam if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 21275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 21285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0)); 2129ea8e1828Sksagiyam if (ishdf5) { 2130ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2131ea8e1828Sksagiyam PetscViewerFormat format; 21325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 2133ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 213598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2136ea8e1828Sksagiyam #else 2137ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2138ea8e1828Sksagiyam #endif 2139ea8e1828Sksagiyam } 21405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0)); 2141ea8e1828Sksagiyam PetscFunctionReturn(0); 2142ea8e1828Sksagiyam } 2143ea8e1828Sksagiyam 21443e701f1cSksagiyam /*@ 21453e701f1cSksagiyam DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 21463e701f1cSksagiyam 21473e701f1cSksagiyam Collective on DM 21483e701f1cSksagiyam 21493e701f1cSksagiyam Input Parameters: 21503e701f1cSksagiyam + dm - The DM into which the coordinates are loaded 2151c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates 2152c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 21533e701f1cSksagiyam 21543e701f1cSksagiyam Level: advanced 21553e701f1cSksagiyam 2156b08ad5deSksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 21573e701f1cSksagiyam @*/ 2158c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 21593e701f1cSksagiyam { 21603e701f1cSksagiyam PetscBool ishdf5; 21613e701f1cSksagiyam 21623e701f1cSksagiyam PetscFunctionBegin; 21633e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21643e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2165c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 21665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 21675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0)); 21683e701f1cSksagiyam if (ishdf5) { 21693e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 21703e701f1cSksagiyam PetscViewerFormat format; 21715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 21723e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 217498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 21753e701f1cSksagiyam #else 21763e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21773e701f1cSksagiyam #endif 21783e701f1cSksagiyam } 21795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0)); 21803e701f1cSksagiyam PetscFunctionReturn(0); 21813e701f1cSksagiyam } 21823e701f1cSksagiyam 2183b08ad5deSksagiyam /*@ 2184b08ad5deSksagiyam DMPlexLabelsLoad - Loads labels into a DMPlex 2185b08ad5deSksagiyam 2186b08ad5deSksagiyam Collective on DM 2187b08ad5deSksagiyam 2188b08ad5deSksagiyam Input Parameters: 2189b08ad5deSksagiyam + dm - The DM into which the labels are loaded 2190e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels 2191e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2192b08ad5deSksagiyam 2193b08ad5deSksagiyam Level: advanced 2194b08ad5deSksagiyam 2195e6368b79SVaclav Hapla Notes: 2196e6368b79SVaclav Hapla The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs. 2197e6368b79SVaclav Hapla 2198b08ad5deSksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2199b08ad5deSksagiyam @*/ 2200e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2201b08ad5deSksagiyam { 2202b08ad5deSksagiyam PetscBool ishdf5; 2203b08ad5deSksagiyam 2204b08ad5deSksagiyam PetscFunctionBegin; 2205b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2206b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2207e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 22085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 22095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0)); 2210b08ad5deSksagiyam if (ishdf5) { 2211b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2212b08ad5deSksagiyam PetscViewerFormat format; 2213b08ad5deSksagiyam 22145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer, &format)); 2215b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 22165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 221798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2218b08ad5deSksagiyam #else 2219b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2220b08ad5deSksagiyam #endif 2221b08ad5deSksagiyam } 22225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0)); 2223b08ad5deSksagiyam PetscFunctionReturn(0); 2224b08ad5deSksagiyam } 2225b08ad5deSksagiyam 2226f84dd6b4Sksagiyam /*@ 2227f84dd6b4Sksagiyam DMPlexSectionLoad - Loads section into a DMPlex 2228f84dd6b4Sksagiyam 2229f84dd6b4Sksagiyam Collective on DM 2230f84dd6b4Sksagiyam 2231f84dd6b4Sksagiyam Input Parameters: 2232f84dd6b4Sksagiyam + dm - The DM that represents the topology 2233f84dd6b4Sksagiyam . viewer - The PetscViewer that represents the on-disk section (sectionA) 2234f84dd6b4Sksagiyam . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2235f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2236f84dd6b4Sksagiyam 2237f84dd6b4Sksagiyam Output Parameters 2238f84dd6b4Sksagiyam + 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) 2239f84dd6b4Sksagiyam - 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) 2240f84dd6b4Sksagiyam 2241f84dd6b4Sksagiyam Level: advanced 2242f84dd6b4Sksagiyam 2243f84dd6b4Sksagiyam Notes: 2244f84dd6b4Sksagiyam 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. 2245f84dd6b4Sksagiyam 2246f84dd6b4Sksagiyam 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. 2247f84dd6b4Sksagiyam 2248f84dd6b4Sksagiyam 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. 2249f84dd6b4Sksagiyam 2250f84dd6b4Sksagiyam Example using 2 processes: 2251f84dd6b4Sksagiyam $ NX (number of points on dm): 4 2252f84dd6b4Sksagiyam $ sectionA : the on-disk section 2253f84dd6b4Sksagiyam $ vecA : a vector associated with sectionA 2254f84dd6b4Sksagiyam $ sectionB : sectiondm's local section constructed in this function 2255f84dd6b4Sksagiyam $ vecB (local) : a vector associated with sectiondm's local section 2256f84dd6b4Sksagiyam $ vecB (global) : a vector associated with sectiondm's global section 2257f84dd6b4Sksagiyam $ 2258f84dd6b4Sksagiyam $ rank 0 rank 1 2259f84dd6b4Sksagiyam $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2260f84dd6b4Sksagiyam $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2261f84dd6b4Sksagiyam $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2262f84dd6b4Sksagiyam $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2263f84dd6b4Sksagiyam $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2264f84dd6b4Sksagiyam $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2265f84dd6b4Sksagiyam $ sectionB->atlasDof : 1 0 1 | 1 3 2266f84dd6b4Sksagiyam $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2267f84dd6b4Sksagiyam $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2268f84dd6b4Sksagiyam $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2269f84dd6b4Sksagiyam $ 2270f84dd6b4Sksagiyam $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2271f84dd6b4Sksagiyam 2272f84dd6b4Sksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 2273f84dd6b4Sksagiyam @*/ 2274f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2275f84dd6b4Sksagiyam { 2276f84dd6b4Sksagiyam PetscBool ishdf5; 2277f84dd6b4Sksagiyam 2278f84dd6b4Sksagiyam PetscFunctionBegin; 2279f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2280f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2281f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2282f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2283f84dd6b4Sksagiyam if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2284f84dd6b4Sksagiyam if (localDofSF) PetscValidPointer(localDofSF, 6); 22855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 22865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0)); 2287f84dd6b4Sksagiyam if (ishdf5) { 2288f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 22895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2290f84dd6b4Sksagiyam #else 2291f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2292f84dd6b4Sksagiyam #endif 2293f84dd6b4Sksagiyam } 22945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0)); 2295f84dd6b4Sksagiyam PetscFunctionReturn(0); 2296f84dd6b4Sksagiyam } 2297f84dd6b4Sksagiyam 22988be3dfe1Sksagiyam /*@ 22998be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 23008be3dfe1Sksagiyam 23018be3dfe1Sksagiyam Collective on DM 23028be3dfe1Sksagiyam 23038be3dfe1Sksagiyam Input Parameters: 23048be3dfe1Sksagiyam + dm - The DM that represents the topology 23058be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23068be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined 23078be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23088be3dfe1Sksagiyam - vec - The global vector to set values of 23098be3dfe1Sksagiyam 23108be3dfe1Sksagiyam Level: advanced 23118be3dfe1Sksagiyam 23128be3dfe1Sksagiyam Notes: 23138be3dfe1Sksagiyam 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. 23148be3dfe1Sksagiyam 23158be3dfe1Sksagiyam Typical calling sequence 23168be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23178be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23188be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23198be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23208be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23218be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23228be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 23238be3dfe1Sksagiyam $ DMGetGlobalVector(sectiondm, &vec); 23248be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23258be3dfe1Sksagiyam $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 23268be3dfe1Sksagiyam $ DMRestoreGlobalVector(sectiondm, &vec); 23278be3dfe1Sksagiyam $ PetscSFDestroy(&gsf); 23288be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 23298be3dfe1Sksagiyam $ DMDestroy(§iondm); 23308be3dfe1Sksagiyam $ DMDestroy(&dm); 23318be3dfe1Sksagiyam 23328be3dfe1Sksagiyam .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 23338be3dfe1Sksagiyam @*/ 23348be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 23358be3dfe1Sksagiyam { 23368be3dfe1Sksagiyam PetscBool ishdf5; 23378be3dfe1Sksagiyam 23388be3dfe1Sksagiyam PetscFunctionBegin; 23398be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23408be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23418be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 23428be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 23438be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 23448be3dfe1Sksagiyam /* Check consistency */ 23458be3dfe1Sksagiyam { 23468be3dfe1Sksagiyam PetscSection section; 23478be3dfe1Sksagiyam PetscBool includesConstraints; 23488be3dfe1Sksagiyam PetscInt m, m1; 23498be3dfe1Sksagiyam 23505f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(vec, &m1)); 23515f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(sectiondm, §ion)); 23525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 23535f80ce2aSJacob Faibussowitsch if (includesConstraints) CHKERRQ(PetscSectionGetStorageSize(section, &m)); 23545f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetConstrainedStorageSize(section, &m)); 23552c71b3e2SJacob Faibussowitsch PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 23568be3dfe1Sksagiyam } 23575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 23585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0)); 23598be3dfe1Sksagiyam if (ishdf5) { 23608be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 23615f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 23628be3dfe1Sksagiyam #else 23638be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23648be3dfe1Sksagiyam #endif 23658be3dfe1Sksagiyam } 23665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0)); 23678be3dfe1Sksagiyam PetscFunctionReturn(0); 23688be3dfe1Sksagiyam } 23698be3dfe1Sksagiyam 23708be3dfe1Sksagiyam /*@ 23718be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 23728be3dfe1Sksagiyam 23738be3dfe1Sksagiyam Collective on DM 23748be3dfe1Sksagiyam 23758be3dfe1Sksagiyam Input Parameters: 23768be3dfe1Sksagiyam + dm - The DM that represents the topology 23778be3dfe1Sksagiyam . viewer - The PetscViewer that represents the on-disk vector data 23788be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined 23798be3dfe1Sksagiyam . sf - The SF that migrates the on-disk vector data into vec 23808be3dfe1Sksagiyam - vec - The local vector to set values of 23818be3dfe1Sksagiyam 23828be3dfe1Sksagiyam Level: advanced 23838be3dfe1Sksagiyam 23848be3dfe1Sksagiyam Notes: 23858be3dfe1Sksagiyam 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. 23868be3dfe1Sksagiyam 23878be3dfe1Sksagiyam Typical calling sequence 23888be3dfe1Sksagiyam $ DMCreate(PETSC_COMM_WORLD, &dm); 23898be3dfe1Sksagiyam $ DMSetType(dm, DMPLEX); 23908be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 23918be3dfe1Sksagiyam $ DMPlexTopologyLoad(dm, viewer, &sfX); 23928be3dfe1Sksagiyam $ DMClone(dm, §iondm); 23938be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 23948be3dfe1Sksagiyam $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 23958be3dfe1Sksagiyam $ DMGetLocalVector(sectiondm, &vec); 23968be3dfe1Sksagiyam $ PetscObjectSetName((PetscObject)vec, "vec_name"); 23978be3dfe1Sksagiyam $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 23988be3dfe1Sksagiyam $ DMRestoreLocalVector(sectiondm, &vec); 23998be3dfe1Sksagiyam $ PetscSFDestroy(&lsf); 24008be3dfe1Sksagiyam $ PetscSFDestroy(&sfX); 24018be3dfe1Sksagiyam $ DMDestroy(§iondm); 24028be3dfe1Sksagiyam $ DMDestroy(&dm); 24038be3dfe1Sksagiyam 24048be3dfe1Sksagiyam .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 24058be3dfe1Sksagiyam @*/ 24068be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 24078be3dfe1Sksagiyam { 24088be3dfe1Sksagiyam PetscBool ishdf5; 24098be3dfe1Sksagiyam 24108be3dfe1Sksagiyam PetscFunctionBegin; 24118be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24128be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24138be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24148be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 24158be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 24168be3dfe1Sksagiyam /* Check consistency */ 24178be3dfe1Sksagiyam { 24188be3dfe1Sksagiyam PetscSection section; 24198be3dfe1Sksagiyam PetscBool includesConstraints; 24208be3dfe1Sksagiyam PetscInt m, m1; 24218be3dfe1Sksagiyam 24225f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(vec, &m1)); 24235f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(sectiondm, §ion)); 24245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24255f80ce2aSJacob Faibussowitsch if (includesConstraints) CHKERRQ(PetscSectionGetStorageSize(section, &m)); 24265f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetConstrainedStorageSize(section, &m)); 24272c71b3e2SJacob Faibussowitsch PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 24288be3dfe1Sksagiyam } 24295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5)); 24305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0)); 24318be3dfe1Sksagiyam if (ishdf5) { 24328be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 24335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 24348be3dfe1Sksagiyam #else 24358be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24368be3dfe1Sksagiyam #endif 24378be3dfe1Sksagiyam } 24385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0)); 24398be3dfe1Sksagiyam PetscFunctionReturn(0); 24408be3dfe1Sksagiyam } 24418be3dfe1Sksagiyam 2442552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm) 2443552f7358SJed Brown { 2444552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2445552f7358SJed Brown 2446552f7358SJed Brown PetscFunctionBegin; 24475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL)); 24485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL)); 24495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL)); 24505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL)); 24510d644c17SKarl Rupp if (--mesh->refct > 0) PetscFunctionReturn(0); 24525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->coneSection)); 24535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->cones)); 24545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->coneOrientations)); 24555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->supportSection)); 24565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->subdomainSection)); 24575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->supports)); 24585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->facesTmp)); 24595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->tetgenOpts)); 24605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->triangleOpts)); 24615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->transformType)); 24625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerDestroy(&mesh->partitioner)); 24635f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&mesh->subpointMap)); 24645f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&mesh->subpointIS)); 24655f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&mesh->globalVertexNumbers)); 24665f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&mesh->globalCellNumbers)); 24675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->anchorSection)); 24685f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&mesh->anchorIS)); 24695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->parentSection)); 24705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->parents)); 24715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->childIDs)); 24725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->childSection)); 24735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->children)); 24745f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&mesh->referenceTree)); 24755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGridHashDestroy(&mesh->lbox)); 24765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->neighbors)); 24775f80ce2aSJacob Faibussowitsch if (mesh->metricCtx) CHKERRQ(PetscFree(mesh->metricCtx)); 2478552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 24795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh)); 2480552f7358SJed Brown PetscFunctionReturn(0); 2481552f7358SJed Brown } 2482552f7358SJed Brown 2483b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2484552f7358SJed Brown { 24858d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2486acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 2487552f7358SJed Brown PetscInt localSize; 2488837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2489b412c318SBarry Smith MatType mtype; 24901428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2491552f7358SJed Brown 2492552f7358SJed Brown PetscFunctionBegin; 24935f80ce2aSJacob Faibussowitsch CHKERRQ(MatInitializePackage()); 2494b412c318SBarry Smith mtype = dm->mattype; 24955f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(dm, §ionGlobal)); 24965f80ce2aSJacob Faibussowitsch /* CHKERRQ(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 24975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 24985f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)dm), J)); 24995f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 25005f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(*J, mtype)); 25015f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetFromOptions(*J)); 25025f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(*J, &mbs)); 2503acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 25045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(mtype, MATSHELL, &isShell)); 25055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 25065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 25075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 25085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 25095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 25105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 25115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(mtype, MATIS, &isMatIS)); 2512552f7358SJed Brown if (!isShell) { 2513837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2514e432b41dSStefano Zampini PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2]; 2515fad22124SMatthew G Knepley PetscInt pStart, pEnd, p, dof, cdof; 2516552f7358SJed Brown 25175f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalToGlobalMapping(dm,<og)); 25185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2519e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2520a9d99c84SMatthew G. Knepley PetscInt bdof; 2521a9d99c84SMatthew G. Knepley 25225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(sectionGlobal, p, &dof)); 25235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 25241d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof+1) : dof; 25251d17a0a3SMatthew G. Knepley bdof = cdof && (dof-cdof) ? 1 : dof; 25261d17a0a3SMatthew G. Knepley if (dof) { 25271d17a0a3SMatthew G. Knepley if (bs < 0) {bs = bdof;} 2528e432b41dSStefano Zampini else if (bs != bdof) {bs = 1; break;} 2529552f7358SJed Brown } 25302a28c762SMatthew G Knepley } 25312a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2532e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2533e432b41dSStefano Zampini bsLocal[1] = bs; 25345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 2535e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2536e432b41dSStefano Zampini else bs = bsMinMax[0]; 25376fd5c86aSStefano Zampini bs = PetscMax(1,bs); 25385f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetLocalToGlobalMapping(*J,ltog,ltog)); 25390682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 25405f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetBlockSize(*J, bs)); 25415f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(*J)); 25420682b8bbSJed Brown } else { 25435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu)); 25445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 25455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(dnz, onz, dnzu, onzu)); 2546552f7358SJed Brown } 2547aa0f6e3cSJed Brown } 25485f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetDM(*J, dm)); 2549552f7358SJed Brown PetscFunctionReturn(0); 2550552f7358SJed Brown } 2551552f7358SJed Brown 25527cd05799SMatthew G. Knepley /*@ 2553a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2554be36d101SStefano Zampini 2555be36d101SStefano Zampini Not collective 2556be36d101SStefano Zampini 2557be36d101SStefano Zampini Input Parameter: 2558be36d101SStefano Zampini . mesh - The DMPlex 2559be36d101SStefano Zampini 2560be36d101SStefano Zampini Output Parameters: 2561be36d101SStefano Zampini . subsection - The subdomain section 2562be36d101SStefano Zampini 2563be36d101SStefano Zampini Level: developer 2564be36d101SStefano Zampini 2565be36d101SStefano Zampini .seealso: 25667cd05799SMatthew G. Knepley @*/ 2567be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2568be36d101SStefano Zampini { 2569be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex*) dm->data; 2570be36d101SStefano Zampini 2571be36d101SStefano Zampini PetscFunctionBegin; 2572be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2573be36d101SStefano Zampini if (!mesh->subdomainSection) { 2574be36d101SStefano Zampini PetscSection section; 2575be36d101SStefano Zampini PetscSF sf; 2576be36d101SStefano Zampini 25775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(PETSC_COMM_SELF,&sf)); 25785f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm,§ion)); 25795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection)); 25805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sf)); 2581be36d101SStefano Zampini } 2582be36d101SStefano Zampini *subsection = mesh->subdomainSection; 2583be36d101SStefano Zampini PetscFunctionReturn(0); 2584be36d101SStefano Zampini } 2585be36d101SStefano Zampini 2586552f7358SJed Brown /*@ 2587552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2588552f7358SJed Brown 2589552f7358SJed Brown Not collective 2590552f7358SJed Brown 2591552f7358SJed Brown Input Parameter: 2592552f7358SJed Brown . mesh - The DMPlex 2593552f7358SJed Brown 2594552f7358SJed Brown Output Parameters: 2595552f7358SJed Brown + pStart - The first mesh point 2596552f7358SJed Brown - pEnd - The upper bound for mesh points 2597552f7358SJed Brown 2598552f7358SJed Brown Level: beginner 2599552f7358SJed Brown 2600552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart() 2601552f7358SJed Brown @*/ 2602552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2603552f7358SJed Brown { 2604552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2605552f7358SJed Brown 2606552f7358SJed Brown PetscFunctionBegin; 2607552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 2609552f7358SJed Brown PetscFunctionReturn(0); 2610552f7358SJed Brown } 2611552f7358SJed Brown 2612552f7358SJed Brown /*@ 2613552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2614552f7358SJed Brown 2615552f7358SJed Brown Not collective 2616552f7358SJed Brown 2617552f7358SJed Brown Input Parameters: 2618552f7358SJed Brown + mesh - The DMPlex 2619552f7358SJed Brown . pStart - The first mesh point 2620552f7358SJed Brown - pEnd - The upper bound for mesh points 2621552f7358SJed Brown 2622552f7358SJed Brown Output Parameters: 2623552f7358SJed Brown 2624552f7358SJed Brown Level: beginner 2625552f7358SJed Brown 2626552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetChart() 2627552f7358SJed Brown @*/ 2628552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2629552f7358SJed Brown { 2630552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2631552f7358SJed Brown 2632552f7358SJed Brown PetscFunctionBegin; 2633552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 26355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 2636552f7358SJed Brown PetscFunctionReturn(0); 2637552f7358SJed Brown } 2638552f7358SJed Brown 2639552f7358SJed Brown /*@ 2640eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2641552f7358SJed Brown 2642552f7358SJed Brown Not collective 2643552f7358SJed Brown 2644552f7358SJed Brown Input Parameters: 2645552f7358SJed Brown + mesh - The DMPlex 2646eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2647552f7358SJed Brown 2648552f7358SJed Brown Output Parameter: 2649552f7358SJed Brown . size - The cone size for point p 2650552f7358SJed Brown 2651552f7358SJed Brown Level: beginner 2652552f7358SJed Brown 2653552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2654552f7358SJed Brown @*/ 2655552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2656552f7358SJed Brown { 2657552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2658552f7358SJed Brown 2659552f7358SJed Brown PetscFunctionBegin; 2660552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2661*dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 26625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, size)); 2663552f7358SJed Brown PetscFunctionReturn(0); 2664552f7358SJed Brown } 2665552f7358SJed Brown 2666552f7358SJed Brown /*@ 2667eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2668552f7358SJed Brown 2669552f7358SJed Brown Not collective 2670552f7358SJed Brown 2671552f7358SJed Brown Input Parameters: 2672552f7358SJed Brown + mesh - The DMPlex 2673eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2674552f7358SJed Brown - size - The cone size for point p 2675552f7358SJed Brown 2676552f7358SJed Brown Output Parameter: 2677552f7358SJed Brown 2678552f7358SJed Brown Note: 2679552f7358SJed Brown This should be called after DMPlexSetChart(). 2680552f7358SJed Brown 2681552f7358SJed Brown Level: beginner 2682552f7358SJed Brown 2683552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2684552f7358SJed Brown @*/ 2685552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2686552f7358SJed Brown { 2687552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2688552f7358SJed Brown 2689552f7358SJed Brown PetscFunctionBegin; 2690552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(mesh->coneSection, p, size)); 26920d644c17SKarl Rupp 2693552f7358SJed Brown mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2694552f7358SJed Brown PetscFunctionReturn(0); 2695552f7358SJed Brown } 2696552f7358SJed Brown 2697f5a469b9SMatthew G. Knepley /*@ 2698eaf898f9SPatrick Sanan DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2699f5a469b9SMatthew G. Knepley 2700f5a469b9SMatthew G. Knepley Not collective 2701f5a469b9SMatthew G. Knepley 2702f5a469b9SMatthew G. Knepley Input Parameters: 2703f5a469b9SMatthew G. Knepley + mesh - The DMPlex 2704eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2705f5a469b9SMatthew G. Knepley - size - The additional cone size for point p 2706f5a469b9SMatthew G. Knepley 2707f5a469b9SMatthew G. Knepley Output Parameter: 2708f5a469b9SMatthew G. Knepley 2709f5a469b9SMatthew G. Knepley Note: 2710f5a469b9SMatthew G. Knepley This should be called after DMPlexSetChart(). 2711f5a469b9SMatthew G. Knepley 2712f5a469b9SMatthew G. Knepley Level: beginner 2713f5a469b9SMatthew G. Knepley 2714f5a469b9SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2715f5a469b9SMatthew G. Knepley @*/ 2716f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2717f5a469b9SMatthew G. Knepley { 2718f5a469b9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 2719f5a469b9SMatthew G. Knepley PetscInt csize; 2720f5a469b9SMatthew G. Knepley 2721f5a469b9SMatthew G. Knepley PetscFunctionBegin; 2722f5a469b9SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(mesh->coneSection, p, size)); 27245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &csize)); 2725f5a469b9SMatthew G. Knepley 2726f5a469b9SMatthew G. Knepley mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2727f5a469b9SMatthew G. Knepley PetscFunctionReturn(0); 2728f5a469b9SMatthew G. Knepley } 2729f5a469b9SMatthew G. Knepley 2730552f7358SJed Brown /*@C 2731eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2732552f7358SJed Brown 2733552f7358SJed Brown Not collective 2734552f7358SJed Brown 2735552f7358SJed Brown Input Parameters: 2736833c876bSVaclav Hapla + dm - The DMPlex 2737eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2738552f7358SJed Brown 2739552f7358SJed Brown Output Parameter: 2740552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 2741552f7358SJed Brown 2742552f7358SJed Brown Level: beginner 2743552f7358SJed Brown 27443813dfbdSMatthew G Knepley Fortran Notes: 27453813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 27463813dfbdSMatthew G Knepley include petsc.h90 in your code. 2747922102d1SVaclav Hapla You must also call DMPlexRestoreCone() after you finish using the returned array. 2748922102d1SVaclav Hapla DMPlexRestoreCone() is not needed/available in C. 27493813dfbdSMatthew G Knepley 2750e45f02b0SMatthew G. Knepley .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2751552f7358SJed Brown @*/ 2752552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2753552f7358SJed Brown { 2754552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2755552f7358SJed Brown PetscInt off; 2756552f7358SJed Brown 2757552f7358SJed Brown PetscFunctionBegin; 2758552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2759552f7358SJed Brown PetscValidPointer(cone, 3); 27605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 2761552f7358SJed Brown *cone = &mesh->cones[off]; 2762552f7358SJed Brown PetscFunctionReturn(0); 2763552f7358SJed Brown } 2764552f7358SJed Brown 27650ce7577fSVaclav Hapla /*@C 27660ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 27670ce7577fSVaclav Hapla 27680ce7577fSVaclav Hapla Not collective 27690ce7577fSVaclav Hapla 27700ce7577fSVaclav Hapla Input Parameters: 27710ce7577fSVaclav Hapla + dm - The DMPlex 27720ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 27730ce7577fSVaclav Hapla 2774d8d19677SJose E. Roman Output Parameters: 27750ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones 27760ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p 27770ce7577fSVaclav Hapla 27780ce7577fSVaclav Hapla Level: intermediate 27790ce7577fSVaclav Hapla 2780d4636a37SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 27810ce7577fSVaclav Hapla @*/ 27820ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 27830ce7577fSVaclav Hapla { 27840ce7577fSVaclav Hapla PetscSection cs, newcs; 27850ce7577fSVaclav Hapla PetscInt *cones; 27860ce7577fSVaclav Hapla PetscInt *newarr=NULL; 27870ce7577fSVaclav Hapla PetscInt n; 27880ce7577fSVaclav Hapla 27890ce7577fSVaclav Hapla PetscFunctionBegin; 27905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCones(dm, &cones)); 27915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSection(dm, &cs)); 27925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL)); 27930ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 27940ce7577fSVaclav Hapla if (pCones) { 27955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(newcs, &n)); 27965f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 27970ce7577fSVaclav Hapla } 27980ce7577fSVaclav Hapla PetscFunctionReturn(0); 27990ce7577fSVaclav Hapla } 28000ce7577fSVaclav Hapla 2801af9eab45SVaclav Hapla /*@ 2802af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2803d4636a37SVaclav Hapla 2804d4636a37SVaclav Hapla Not collective 2805d4636a37SVaclav Hapla 2806d4636a37SVaclav Hapla Input Parameters: 2807d4636a37SVaclav Hapla + dm - The DMPlex 2808af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2809d4636a37SVaclav Hapla 2810d4636a37SVaclav Hapla Output Parameter: 2811af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 2812d4636a37SVaclav Hapla 2813d4636a37SVaclav Hapla Level: advanced 2814d4636a37SVaclav Hapla 2815af9eab45SVaclav Hapla Notes: 2816af9eab45SVaclav Hapla Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2817af9eab45SVaclav Hapla There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2818af9eab45SVaclav Hapla 2819af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2820d4636a37SVaclav Hapla @*/ 2821af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2822d4636a37SVaclav Hapla { 2823af9eab45SVaclav Hapla IS *expandedPointsAll; 2824af9eab45SVaclav Hapla PetscInt depth; 2825d4636a37SVaclav Hapla 2826d4636a37SVaclav Hapla PetscFunctionBegin; 2827af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2828af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2829af9eab45SVaclav Hapla PetscValidPointer(expandedPoints, 3); 28305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2831af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 28325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)expandedPointsAll[0])); 28335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 2834af9eab45SVaclav Hapla PetscFunctionReturn(0); 2835af9eab45SVaclav Hapla } 2836af9eab45SVaclav Hapla 2837af9eab45SVaclav Hapla /*@ 2838af9eab45SVaclav 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). 2839af9eab45SVaclav Hapla 2840af9eab45SVaclav Hapla Not collective 2841af9eab45SVaclav Hapla 2842af9eab45SVaclav Hapla Input Parameters: 2843af9eab45SVaclav Hapla + dm - The DMPlex 2844af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2845af9eab45SVaclav Hapla 2846d8d19677SJose E. Roman Output Parameters: 2847af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2848af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 2849af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2850af9eab45SVaclav Hapla 2851af9eab45SVaclav Hapla Level: advanced 2852af9eab45SVaclav Hapla 2853af9eab45SVaclav Hapla Notes: 2854af9eab45SVaclav Hapla Like DMPlexGetConeTuple() but recursive. 2855af9eab45SVaclav Hapla 2856af9eab45SVaclav 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. 2857af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2858af9eab45SVaclav Hapla 2859af9eab45SVaclav 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: 2860af9eab45SVaclav Hapla (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2861af9eab45SVaclav Hapla (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2862af9eab45SVaclav Hapla 2863af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2864af9eab45SVaclav Hapla @*/ 2865af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2866af9eab45SVaclav Hapla { 2867af9eab45SVaclav Hapla const PetscInt *arr0=NULL, *cone=NULL; 2868af9eab45SVaclav Hapla PetscInt *arr=NULL, *newarr=NULL; 2869af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 2870af9eab45SVaclav Hapla IS *expandedPoints_; 2871af9eab45SVaclav Hapla PetscSection *sections_; 2872af9eab45SVaclav Hapla 2873af9eab45SVaclav Hapla PetscFunctionBegin; 2874af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2875af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2876af9eab45SVaclav Hapla if (depth) PetscValidIntPointer(depth, 3); 2877af9eab45SVaclav Hapla if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2878af9eab45SVaclav Hapla if (sections) PetscValidPointer(sections, 5); 28795f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(points, &n)); 28805f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(points, &arr0)); 28815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth_)); 28825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(depth_, &expandedPoints_)); 28835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(depth_, §ions_)); 2884af9eab45SVaclav Hapla arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2885af9eab45SVaclav Hapla for (d=depth_-1; d>=0; d--) { 28865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 28875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(sections_[d], 0, n)); 2888af9eab45SVaclav Hapla for (i=0; i<n; i++) { 28895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d+1, &start, &end)); 2890af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 28915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, arr[i], &cn)); 28925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(sections_[d], i, cn)); 2893af9eab45SVaclav Hapla } else { 28945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(sections_[d], i, 1)); 2895af9eab45SVaclav Hapla } 2896af9eab45SVaclav Hapla } 28975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(sections_[d])); 28985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(sections_[d], &newn)); 28995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(newn, &newarr)); 2900af9eab45SVaclav Hapla for (i=0; i<n; i++) { 29015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(sections_[d], i, &cn)); 29025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(sections_[d], i, &co)); 2903af9eab45SVaclav Hapla if (cn > 1) { 29045f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, arr[i], &cone)); 29055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt))); 2906af9eab45SVaclav Hapla } else { 2907af9eab45SVaclav Hapla newarr[co] = arr[i]; 2908af9eab45SVaclav Hapla } 2909af9eab45SVaclav Hapla } 29105f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 2911af9eab45SVaclav Hapla arr = newarr; 2912af9eab45SVaclav Hapla n = newn; 2913af9eab45SVaclav Hapla } 29145f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(points, &arr0)); 2915af9eab45SVaclav Hapla *depth = depth_; 2916af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 2917af9eab45SVaclav Hapla else { 29185f80ce2aSJacob Faibussowitsch for (d=0; d<depth_; d++) CHKERRQ(ISDestroy(&expandedPoints_[d])); 29195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(expandedPoints_)); 2920af9eab45SVaclav Hapla } 2921af9eab45SVaclav Hapla if (sections) *sections = sections_; 2922af9eab45SVaclav Hapla else { 29235f80ce2aSJacob Faibussowitsch for (d=0; d<depth_; d++) CHKERRQ(PetscSectionDestroy(§ions_[d])); 29245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(sections_)); 2925af9eab45SVaclav Hapla } 2926af9eab45SVaclav Hapla PetscFunctionReturn(0); 2927af9eab45SVaclav Hapla } 2928af9eab45SVaclav Hapla 2929af9eab45SVaclav Hapla /*@ 2930af9eab45SVaclav Hapla DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2931af9eab45SVaclav Hapla 2932af9eab45SVaclav Hapla Not collective 2933af9eab45SVaclav Hapla 2934af9eab45SVaclav Hapla Input Parameters: 2935af9eab45SVaclav Hapla + dm - The DMPlex 2936af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2937af9eab45SVaclav Hapla 2938d8d19677SJose E. Roman Output Parameters: 2939af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2940af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 2941af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 2942af9eab45SVaclav Hapla 2943af9eab45SVaclav Hapla Level: advanced 2944af9eab45SVaclav Hapla 2945af9eab45SVaclav Hapla Notes: 2946af9eab45SVaclav Hapla See DMPlexGetConeRecursive() for details. 2947af9eab45SVaclav Hapla 2948af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2949af9eab45SVaclav Hapla @*/ 2950af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2951af9eab45SVaclav Hapla { 2952af9eab45SVaclav Hapla PetscInt d, depth_; 2953af9eab45SVaclav Hapla 2954af9eab45SVaclav Hapla PetscFunctionBegin; 29555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth_)); 29562c71b3e2SJacob Faibussowitsch PetscCheckFalse(depth && *depth != depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2957af9eab45SVaclav Hapla if (depth) *depth = 0; 2958af9eab45SVaclav Hapla if (expandedPoints) { 29595f80ce2aSJacob Faibussowitsch for (d=0; d<depth_; d++) CHKERRQ(ISDestroy(&((*expandedPoints)[d]))); 29605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(*expandedPoints)); 2961af9eab45SVaclav Hapla } 2962af9eab45SVaclav Hapla if (sections) { 29635f80ce2aSJacob Faibussowitsch for (d=0; d<depth_; d++) CHKERRQ(PetscSectionDestroy(&((*sections)[d]))); 29645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(*sections)); 2965af9eab45SVaclav Hapla } 2966d4636a37SVaclav Hapla PetscFunctionReturn(0); 2967d4636a37SVaclav Hapla } 2968d4636a37SVaclav Hapla 2969552f7358SJed Brown /*@ 297092371b87SBarry 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 2971552f7358SJed Brown 2972552f7358SJed Brown Not collective 2973552f7358SJed Brown 2974552f7358SJed Brown Input Parameters: 2975552f7358SJed Brown + mesh - The DMPlex 2976eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2977552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 2978552f7358SJed Brown 2979552f7358SJed Brown Output Parameter: 2980552f7358SJed Brown 2981552f7358SJed Brown Note: 2982552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2983552f7358SJed Brown 2984552f7358SJed Brown Level: beginner 2985552f7358SJed Brown 298692371b87SBarry Smith .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2987552f7358SJed Brown @*/ 2988552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2989552f7358SJed Brown { 2990552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2991552f7358SJed Brown PetscInt pStart, pEnd; 2992552f7358SJed Brown PetscInt dof, off, c; 2993552f7358SJed Brown 2994552f7358SJed Brown PetscFunctionBegin; 2995552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 29975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof)); 2998*dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(cone, 3); 29995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30002c71b3e2SJacob Faibussowitsch PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3001552f7358SJed Brown for (c = 0; c < dof; ++c) { 30022c71b3e2SJacob Faibussowitsch PetscCheckFalse((cone[c] < pStart) || (cone[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 3003552f7358SJed Brown mesh->cones[off+c] = cone[c]; 3004552f7358SJed Brown } 3005552f7358SJed Brown PetscFunctionReturn(0); 3006552f7358SJed Brown } 3007552f7358SJed Brown 3008552f7358SJed Brown /*@C 3009eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3010552f7358SJed Brown 3011552f7358SJed Brown Not collective 3012552f7358SJed Brown 3013552f7358SJed Brown Input Parameters: 3014552f7358SJed Brown + mesh - The DMPlex 3015eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3016552f7358SJed Brown 3017552f7358SJed Brown Output Parameter: 3018552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 3019b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3020552f7358SJed Brown 3021552f7358SJed Brown Level: beginner 3022552f7358SJed Brown 3023b5a892a1SMatthew G. Knepley Notes: 3024b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3025b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3026b5a892a1SMatthew G. Knepley of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 3027b5a892a1SMatthew G. Knepley with the identity. 3028b5a892a1SMatthew G. Knepley 30293813dfbdSMatthew G Knepley Fortran Notes: 30303813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 30313813dfbdSMatthew G Knepley include petsc.h90 in your code. 30323b12b3d8SVaclav Hapla You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 3033922102d1SVaclav Hapla DMPlexRestoreConeOrientation() is not needed/available in C. 30343813dfbdSMatthew G Knepley 3035b5a892a1SMatthew G. Knepley .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 3036552f7358SJed Brown @*/ 3037552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3038552f7358SJed Brown { 3039552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3040552f7358SJed Brown PetscInt off; 3041552f7358SJed Brown 3042552f7358SJed Brown PetscFunctionBegin; 3043552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 304476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3045552f7358SJed Brown PetscInt dof; 30465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3047552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 3048552f7358SJed Brown } 30495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30500d644c17SKarl Rupp 3051552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 3052552f7358SJed Brown PetscFunctionReturn(0); 3053552f7358SJed Brown } 3054552f7358SJed Brown 3055552f7358SJed Brown /*@ 3056eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3057552f7358SJed Brown 3058552f7358SJed Brown Not collective 3059552f7358SJed Brown 3060552f7358SJed Brown Input Parameters: 3061552f7358SJed Brown + mesh - The DMPlex 3062eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3063b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3064552f7358SJed Brown Output Parameter: 3065552f7358SJed Brown 3066b5a892a1SMatthew G. Knepley Notes: 3067552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3068552f7358SJed Brown 3069b5a892a1SMatthew G. Knepley The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3070b5a892a1SMatthew G. Knepley 3071552f7358SJed Brown Level: beginner 3072552f7358SJed Brown 3073552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3074552f7358SJed Brown @*/ 3075552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3076552f7358SJed Brown { 3077552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3078552f7358SJed Brown PetscInt pStart, pEnd; 3079552f7358SJed Brown PetscInt dof, off, c; 3080552f7358SJed Brown 3081552f7358SJed Brown PetscFunctionBegin; 3082552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 30845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof)); 3085*dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(coneOrientation, 3); 30865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30872c71b3e2SJacob Faibussowitsch PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3088552f7358SJed Brown for (c = 0; c < dof; ++c) { 3089552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3090552f7358SJed Brown 30915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof)); 30922c71b3e2SJacob Faibussowitsch PetscCheckFalse(o && ((o < -(cdof+1)) || (o >= cdof)),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 3093552f7358SJed Brown mesh->coneOrientations[off+c] = o; 3094552f7358SJed Brown } 3095552f7358SJed Brown PetscFunctionReturn(0); 3096552f7358SJed Brown } 3097552f7358SJed Brown 30987cd05799SMatthew G. Knepley /*@ 3099eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 31007cd05799SMatthew G. Knepley 31017cd05799SMatthew G. Knepley Not collective 31027cd05799SMatthew G. Knepley 31037cd05799SMatthew G. Knepley Input Parameters: 31047cd05799SMatthew G. Knepley + mesh - The DMPlex 3105eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31067cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31077cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 31087cd05799SMatthew G. Knepley 31097cd05799SMatthew G. Knepley Level: beginner 31107cd05799SMatthew G. Knepley 31117cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 31127cd05799SMatthew G. Knepley @*/ 3113552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3114552f7358SJed Brown { 3115552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3116552f7358SJed Brown PetscInt pStart, pEnd; 3117552f7358SJed Brown PetscInt dof, off; 3118552f7358SJed Brown 3119552f7358SJed Brown PetscFunctionBegin; 3120552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 31222c71b3e2SJacob Faibussowitsch PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 31232c71b3e2SJacob Faibussowitsch PetscCheckFalse((conePoint < pStart) || (conePoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 31245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 31262c71b3e2SJacob Faibussowitsch PetscCheckFalse((conePos < 0) || (conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 3127552f7358SJed Brown mesh->cones[off+conePos] = conePoint; 3128552f7358SJed Brown PetscFunctionReturn(0); 3129552f7358SJed Brown } 3130552f7358SJed Brown 31317cd05799SMatthew G. Knepley /*@ 3132eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 31337cd05799SMatthew G. Knepley 31347cd05799SMatthew G. Knepley Not collective 31357cd05799SMatthew G. Knepley 31367cd05799SMatthew G. Knepley Input Parameters: 31377cd05799SMatthew G. Knepley + mesh - The DMPlex 3138eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 31397cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 31407cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 31417cd05799SMatthew G. Knepley 31427cd05799SMatthew G. Knepley Level: beginner 31437cd05799SMatthew G. Knepley 3144b5a892a1SMatthew G. Knepley Notes: 3145b5a892a1SMatthew G. Knepley The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3146b5a892a1SMatthew G. Knepley 31477cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 31487cd05799SMatthew G. Knepley @*/ 314977c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 315077c88f5bSMatthew G Knepley { 315177c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 315277c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 315377c88f5bSMatthew G Knepley PetscInt dof, off; 315477c88f5bSMatthew G Knepley 315577c88f5bSMatthew G Knepley PetscFunctionBegin; 315677c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 31582c71b3e2SJacob Faibussowitsch PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 31595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof)); 31605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 31612c71b3e2SJacob Faibussowitsch PetscCheckFalse((conePos < 0) || (conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 316277c88f5bSMatthew G Knepley mesh->coneOrientations[off+conePos] = coneOrientation; 316377c88f5bSMatthew G Knepley PetscFunctionReturn(0); 316477c88f5bSMatthew G Knepley } 316577c88f5bSMatthew G Knepley 3166552f7358SJed Brown /*@ 3167eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3168552f7358SJed Brown 3169552f7358SJed Brown Not collective 3170552f7358SJed Brown 3171552f7358SJed Brown Input Parameters: 3172552f7358SJed Brown + mesh - The DMPlex 3173eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3174552f7358SJed Brown 3175552f7358SJed Brown Output Parameter: 3176552f7358SJed Brown . size - The support size for point p 3177552f7358SJed Brown 3178552f7358SJed Brown Level: beginner 3179552f7358SJed Brown 3180552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 3181552f7358SJed Brown @*/ 3182552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3183552f7358SJed Brown { 3184552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3185552f7358SJed Brown 3186552f7358SJed Brown PetscFunctionBegin; 3187552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3188*dadcf809SJacob Faibussowitsch PetscValidIntPointer(size, 3); 31895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, size)); 3190552f7358SJed Brown PetscFunctionReturn(0); 3191552f7358SJed Brown } 3192552f7358SJed Brown 3193552f7358SJed Brown /*@ 3194eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3195552f7358SJed Brown 3196552f7358SJed Brown Not collective 3197552f7358SJed Brown 3198552f7358SJed Brown Input Parameters: 3199552f7358SJed Brown + mesh - The DMPlex 3200eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 3201552f7358SJed Brown - size - The support size for point p 3202552f7358SJed Brown 3203552f7358SJed Brown Output Parameter: 3204552f7358SJed Brown 3205552f7358SJed Brown Note: 3206552f7358SJed Brown This should be called after DMPlexSetChart(). 3207552f7358SJed Brown 3208552f7358SJed Brown Level: beginner 3209552f7358SJed Brown 3210552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3211552f7358SJed Brown @*/ 3212552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3213552f7358SJed Brown { 3214552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3215552f7358SJed Brown 3216552f7358SJed Brown PetscFunctionBegin; 3217552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(mesh->supportSection, p, size)); 32190d644c17SKarl Rupp 3220552f7358SJed Brown mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3221552f7358SJed Brown PetscFunctionReturn(0); 3222552f7358SJed Brown } 3223552f7358SJed Brown 3224552f7358SJed Brown /*@C 3225eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3226552f7358SJed Brown 3227552f7358SJed Brown Not collective 3228552f7358SJed Brown 3229552f7358SJed Brown Input Parameters: 3230552f7358SJed Brown + mesh - The DMPlex 3231eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 3232552f7358SJed Brown 3233552f7358SJed Brown Output Parameter: 3234552f7358SJed Brown . support - An array of points which are on the out-edges for point p 3235552f7358SJed Brown 3236552f7358SJed Brown Level: beginner 3237552f7358SJed Brown 32383813dfbdSMatthew G Knepley Fortran Notes: 32393813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 32403813dfbdSMatthew G Knepley include petsc.h90 in your code. 32413b12b3d8SVaclav Hapla You must also call DMPlexRestoreSupport() after you finish using the returned array. 3242922102d1SVaclav Hapla DMPlexRestoreSupport() is not needed/available in C. 32433813dfbdSMatthew G Knepley 3244e45f02b0SMatthew G. Knepley .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3245552f7358SJed Brown @*/ 3246552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3247552f7358SJed Brown { 3248552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3249552f7358SJed Brown PetscInt off; 3250552f7358SJed Brown 3251552f7358SJed Brown PetscFunctionBegin; 3252552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3253552f7358SJed Brown PetscValidPointer(support, 3); 32545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3255552f7358SJed Brown *support = &mesh->supports[off]; 3256552f7358SJed Brown PetscFunctionReturn(0); 3257552f7358SJed Brown } 3258552f7358SJed Brown 3259552f7358SJed Brown /*@ 326092371b87SBarry 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 3261552f7358SJed Brown 3262552f7358SJed Brown Not collective 3263552f7358SJed Brown 3264552f7358SJed Brown Input Parameters: 3265552f7358SJed Brown + mesh - The DMPlex 3266eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 326792371b87SBarry Smith - support - An array of points which are on the out-edges for point p 3268552f7358SJed Brown 3269552f7358SJed Brown Output Parameter: 3270552f7358SJed Brown 3271552f7358SJed Brown Note: 3272552f7358SJed Brown This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3273552f7358SJed Brown 3274552f7358SJed Brown Level: beginner 3275552f7358SJed Brown 327692371b87SBarry Smith .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3277552f7358SJed Brown @*/ 3278552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3279552f7358SJed Brown { 3280552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3281552f7358SJed Brown PetscInt pStart, pEnd; 3282552f7358SJed Brown PetscInt dof, off, c; 3283552f7358SJed Brown 3284552f7358SJed Brown PetscFunctionBegin; 3285552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 32875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof)); 3288*dadcf809SJacob Faibussowitsch if (dof) PetscValidIntPointer(support, 3); 32895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off)); 32902c71b3e2SJacob Faibussowitsch PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3291552f7358SJed Brown for (c = 0; c < dof; ++c) { 32922c71b3e2SJacob Faibussowitsch PetscCheckFalse((support[c] < pStart) || (support[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 3293552f7358SJed Brown mesh->supports[off+c] = support[c]; 3294552f7358SJed Brown } 3295552f7358SJed Brown PetscFunctionReturn(0); 3296552f7358SJed Brown } 3297552f7358SJed Brown 32987cd05799SMatthew G. Knepley /*@ 3299eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 33007cd05799SMatthew G. Knepley 33017cd05799SMatthew G. Knepley Not collective 33027cd05799SMatthew G. Knepley 33037cd05799SMatthew G. Knepley Input Parameters: 33047cd05799SMatthew G. Knepley + mesh - The DMPlex 3305eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 33067cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 33077cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 33087cd05799SMatthew G. Knepley 33097cd05799SMatthew G. Knepley Level: beginner 33107cd05799SMatthew G. Knepley 33117cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 33127cd05799SMatthew G. Knepley @*/ 3313552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3314552f7358SJed Brown { 3315552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3316552f7358SJed Brown PetscInt pStart, pEnd; 3317552f7358SJed Brown PetscInt dof, off; 3318552f7358SJed Brown 3319552f7358SJed Brown PetscFunctionBegin; 3320552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 33225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof)); 33235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off)); 33242c71b3e2SJacob Faibussowitsch PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 33252c71b3e2SJacob Faibussowitsch PetscCheckFalse((supportPoint < pStart) || (supportPoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 33262c71b3e2SJacob Faibussowitsch PetscCheckFalse(supportPos >= dof,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 3327552f7358SJed Brown mesh->supports[off+supportPos] = supportPoint; 3328552f7358SJed Brown PetscFunctionReturn(0); 3329552f7358SJed Brown } 3330552f7358SJed Brown 3331b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3332b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3333b5a892a1SMatthew G. Knepley { 3334b5a892a1SMatthew G. Knepley switch (ct) { 3335b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3336b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3337b5a892a1SMatthew G. Knepley break; 3338b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3339b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3340b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3341b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3342b5a892a1SMatthew G. Knepley break; 3343b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3344b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3345b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3346b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3347b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3348b5a892a1SMatthew G. Knepley break; 3349b5a892a1SMatthew G. Knepley default: return o; 3350b5a892a1SMatthew G. Knepley } 3351b5a892a1SMatthew G. Knepley return o; 3352b5a892a1SMatthew G. Knepley } 3353b5a892a1SMatthew G. Knepley 3354b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3355b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3356b5a892a1SMatthew G. Knepley { 3357b5a892a1SMatthew G. Knepley switch (ct) { 3358b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3359b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3360b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3361b5a892a1SMatthew G. Knepley break; 3362b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3363b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3364b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3365b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3366b5a892a1SMatthew G. Knepley break; 3367b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3368b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3369b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3370b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3371b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3372b5a892a1SMatthew G. Knepley break; 3373b5a892a1SMatthew G. Knepley default: return o; 3374b5a892a1SMatthew G. Knepley } 3375b5a892a1SMatthew G. Knepley return o; 3376b5a892a1SMatthew G. Knepley } 3377b5a892a1SMatthew G. Knepley 3378b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3379b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3380b5a892a1SMatthew G. Knepley { 3381b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3382b5a892a1SMatthew G. Knepley 3383b5a892a1SMatthew G. Knepley PetscFunctionBegin; 33845f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 3385b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3386b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3387b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3388b5a892a1SMatthew G. Knepley 33895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 33905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 33915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, p, &ornt)); 3392b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3393b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3394b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3395b5a892a1SMatthew G. Knepley 33965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cone[c], &ct)); 3397b5a892a1SMatthew G. Knepley switch (ct) { 3398b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 33995f80ce2aSJacob Faibussowitsch if ((o == -2) || (o == 1)) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -1)); 34005f80ce2aSJacob Faibussowitsch if (o == -1) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, 0)); 3401b5a892a1SMatthew G. Knepley break; 3402b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 34035f80ce2aSJacob Faibussowitsch if (o == -3) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -2)); 34045f80ce2aSJacob Faibussowitsch if (o == -2) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -1)); 34055f80ce2aSJacob Faibussowitsch if (o == -1) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -3)); 3406b5a892a1SMatthew G. Knepley break; 3407b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 34085f80ce2aSJacob Faibussowitsch if (o == -4) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -2)); 34095f80ce2aSJacob Faibussowitsch if (o == -3) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -1)); 34105f80ce2aSJacob Faibussowitsch if (o == -2) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -4)); 34115f80ce2aSJacob Faibussowitsch if (o == -1) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -3)); 3412b5a892a1SMatthew G. Knepley break; 3413b5a892a1SMatthew G. Knepley default: break; 3414b5a892a1SMatthew G. Knepley } 3415b5a892a1SMatthew G. Knepley } 3416b5a892a1SMatthew G. Knepley } 3417b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3418b5a892a1SMatthew G. Knepley } 3419b5a892a1SMatthew G. Knepley 3420012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3421b5a892a1SMatthew G. Knepley { 3422b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3423b5a892a1SMatthew G. Knepley PetscInt *closure; 3424b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3425b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3426b5a892a1SMatthew G. Knepley 3427b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3428b5a892a1SMatthew G. Knepley if (ornt) { 34295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, p, &ct)); 3430b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3431b5a892a1SMatthew G. Knepley } 3432b5a892a1SMatthew G. Knepley if (*points) { 3433b5a892a1SMatthew G. Knepley closure = *points; 3434b5a892a1SMatthew G. Knepley } else { 3435b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 34365f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 34375f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure)); 3438b5a892a1SMatthew G. Knepley } 3439b5a892a1SMatthew G. Knepley if (useCone) { 34405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &tmpSize)); 34415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &tmp)); 34425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, p, &tmpO)); 3443b5a892a1SMatthew G. Knepley } else { 34445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, p, &tmpSize)); 34455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, p, &tmp)); 3446b5a892a1SMatthew G. Knepley } 3447b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3448b5a892a1SMatthew G. Knepley closure[off++] = p; 3449b5a892a1SMatthew G. Knepley closure[off++] = 0; 3450b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3451b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3452b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3453b5a892a1SMatthew G. Knepley } 3454b5a892a1SMatthew G. Knepley } else { 34555f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3456b5a892a1SMatthew G. Knepley 3457b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3458b5a892a1SMatthew G. Knepley closure[off++] = p; 3459b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3460b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3461b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3462b5a892a1SMatthew G. Knepley 34635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, tmp[t], &ft)); 3464b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3465b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3466b5a892a1SMatthew G. Knepley } 3467b5a892a1SMatthew G. Knepley } 3468b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize+1; 3469b5a892a1SMatthew G. Knepley if (points) *points = closure; 3470b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3471b5a892a1SMatthew G. Knepley } 3472b5a892a1SMatthew G. Knepley 3473b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3474b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3475b5a892a1SMatthew G. Knepley { 3476b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3477b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3478b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3479b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3480b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3481b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3482b5a892a1SMatthew G. Knepley 3483b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 34845f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 34855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, point, &coneSize)); 34865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, point, &cone)); 34875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, point, &ornt)); 34885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3489b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3490b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3491b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 3492b5a892a1SMatthew G. Knepley if (*points) {pts = *points;} 34935f80ce2aSJacob Faibussowitsch else CHKERRQ(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts)); 3494b5a892a1SMatthew G. Knepley c = 0; 3495b5a892a1SMatthew G. Knepley pts[c++] = point; 3496b5a892a1SMatthew G. Knepley pts[c++] = o; 34975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft)); 34985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure)); 3499b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 35005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure)); 3501b5a892a1SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 35025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3503b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 35045f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft)); 3505b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d*2+0]]; 3506b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3507b5a892a1SMatthew G. Knepley } 3508b5a892a1SMatthew G. Knepley if (dim >= 3) { 3509b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3510b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d*2+0]]; 3511b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3512b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3513b5a892a1SMatthew G. Knepley 35145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, fpoint, &ft)); 3515b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 35165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, fpoint, &fconeSize)); 35175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, fpoint, &fcone)); 35185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, fpoint, &fornt)); 3519b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3520b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc*2+0]]; 3521b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc*2+1]; 3522b5a892a1SMatthew G. Knepley 3523b5a892a1SMatthew G. Knepley for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3524b5a892a1SMatthew G. Knepley if (i == c) { 35255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cp, &ft)); 3526b5a892a1SMatthew G. Knepley pts[c++] = cp; 3527b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3528b5a892a1SMatthew G. Knepley } 3529b5a892a1SMatthew G. Knepley } 3530b5a892a1SMatthew G. Knepley } 3531b5a892a1SMatthew G. Knepley } 3532b5a892a1SMatthew G. Knepley *numPoints = c/2; 3533b5a892a1SMatthew G. Knepley *points = pts; 3534b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3535b5a892a1SMatthew G. Knepley } 3536b5a892a1SMatthew G. Knepley 3537b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3538b5a892a1SMatthew G. Knepley { 3539b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3540b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3541b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3542b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3543b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3544b5a892a1SMatthew G. Knepley 3545b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 35465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 3547b5a892a1SMatthew G. Knepley if (depth == 1) { 35485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 3549b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3550b5a892a1SMatthew G. Knepley } 35515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, p, &ct)); 3552b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3553b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 35545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 3555b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3556b5a892a1SMatthew G. Knepley } 35575f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3558b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3559b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3560b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 35615f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3562b5a892a1SMatthew G. Knepley if (*points) {closure = *points;} 35635f80ce2aSJacob Faibussowitsch else CHKERRQ(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure)); 3564b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3565b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3566b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3567b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3568b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3569b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3570b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3571b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3572b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3573b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3574b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3575b5a892a1SMatthew G. Knepley const PetscInt *tmp, *tmpO; 3576b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3577b5a892a1SMatthew G. Knepley 3578b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3579b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 35802c71b3e2SJacob Faibussowitsch PetscCheckFalse(o && (o >= nO || o < -nO),PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %D not in [%D,%D) for %s %D", o, -nO, nO, DMPolytopeTypes[qt], q); 3581b5a892a1SMatthew G. Knepley } 3582b5a892a1SMatthew G. Knepley if (useCone) { 35835f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, q, &tmpSize)); 35845f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, q, &tmp)); 35855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, q, &tmpO)); 3586b5a892a1SMatthew G. Knepley } else { 35875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, q, &tmpSize)); 35885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, q, &tmp)); 3589b5a892a1SMatthew G. Knepley tmpO = NULL; 3590b5a892a1SMatthew G. Knepley } 3591b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3592b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3593b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3594b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 35955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cp, &ct)); 3596b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3597b5a892a1SMatthew G. Knepley PetscInt c; 3598b5a892a1SMatthew G. Knepley 3599b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3600b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3601b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3602b5a892a1SMatthew G. Knepley } 3603b5a892a1SMatthew G. Knepley if (c == closureSize) { 3604b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3605b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3606b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3607b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3608b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3609b5a892a1SMatthew G. Knepley } 3610b5a892a1SMatthew G. Knepley } 3611b5a892a1SMatthew G. Knepley } 36125f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo)); 3613b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize/2; 3614b5a892a1SMatthew G. Knepley if (points) *points = closure; 3615b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 3616b5a892a1SMatthew G. Knepley } 3617b5a892a1SMatthew G. Knepley 3618552f7358SJed Brown /*@C 3619eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3620552f7358SJed Brown 3621552f7358SJed Brown Not collective 3622552f7358SJed Brown 3623552f7358SJed Brown Input Parameters: 3624b5a892a1SMatthew G. Knepley + dm - The DMPlex 3625b5a892a1SMatthew G. Knepley . p - The mesh point 36266b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star 3627552f7358SJed Brown 36286b867d5aSJose E. Roman Input/Output Parameter: 36296b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 36306b867d5aSJose E. Roman if NULL on input, internal storage will be returned, otherwise the provided array is used 36316b867d5aSJose E. Roman 36326b867d5aSJose E. Roman Output Parameter: 36336b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3634552f7358SJed Brown 3635552f7358SJed Brown Note: 36360298fd71SBarry Smith If using internal storage (points is NULL on input), each call overwrites the last output. 3637552f7358SJed Brown 36383813dfbdSMatthew G Knepley Fortran Notes: 3639b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36403813dfbdSMatthew G Knepley 36413813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36423813dfbdSMatthew G Knepley 3643552f7358SJed Brown Level: beginner 3644552f7358SJed Brown 3645552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3646552f7358SJed Brown @*/ 3647552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3648552f7358SJed Brown { 3649b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3650552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3651b5a892a1SMatthew G. Knepley if (numPoints) PetscValidIntPointer(numPoints, 4); 3652b5a892a1SMatthew G. Knepley if (points) PetscValidPointer(points, 5); 36535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 36549bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 36559bf0dad6SMatthew G. Knepley } 36569bf0dad6SMatthew G. Knepley 3657552f7358SJed Brown /*@C 3658eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3659552f7358SJed Brown 3660552f7358SJed Brown Not collective 3661552f7358SJed Brown 3662552f7358SJed Brown Input Parameters: 3663b5a892a1SMatthew G. Knepley + dm - The DMPlex 3664b5a892a1SMatthew G. Knepley . p - The mesh point 3665b5a892a1SMatthew G. Knepley . useCone - PETSC_TRUE for the closure, otherwise return the star 3666b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3667b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3668552f7358SJed Brown 3669552f7358SJed Brown Note: 36700298fd71SBarry Smith If not using internal storage (points is not NULL on input), this call is unnecessary 3671552f7358SJed Brown 36723813dfbdSMatthew G Knepley Fortran Notes: 3673b5a892a1SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 36743813dfbdSMatthew G Knepley 36753813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 36763813dfbdSMatthew G Knepley 3677552f7358SJed Brown Level: beginner 3678552f7358SJed Brown 3679552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3680552f7358SJed Brown @*/ 3681552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3682552f7358SJed Brown { 3683b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3684552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36854ff43b2cSJed Brown if (numPoints) *numPoints = 0; 36865f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 3687552f7358SJed Brown PetscFunctionReturn(0); 3688552f7358SJed Brown } 3689552f7358SJed Brown 3690552f7358SJed Brown /*@ 3691eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3692552f7358SJed Brown 3693552f7358SJed Brown Not collective 3694552f7358SJed Brown 3695552f7358SJed Brown Input Parameter: 3696552f7358SJed Brown . mesh - The DMPlex 3697552f7358SJed Brown 3698552f7358SJed Brown Output Parameters: 3699552f7358SJed Brown + maxConeSize - The maximum number of in-edges 3700552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 3701552f7358SJed Brown 3702552f7358SJed Brown Level: beginner 3703552f7358SJed Brown 3704552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3705552f7358SJed Brown @*/ 3706552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3707552f7358SJed Brown { 3708552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3709552f7358SJed Brown 3710552f7358SJed Brown PetscFunctionBegin; 3711552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3712552f7358SJed Brown if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3713552f7358SJed Brown if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3714552f7358SJed Brown PetscFunctionReturn(0); 3715552f7358SJed Brown } 3716552f7358SJed Brown 3717552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm) 3718552f7358SJed Brown { 3719552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3720552f7358SJed Brown PetscInt size; 3721552f7358SJed Brown 3722552f7358SJed Brown PetscFunctionBegin; 3723552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(mesh->coneSection)); 37255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(mesh->coneSection, &size)); 37265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size, &mesh->cones)); 37275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(size, &mesh->coneOrientations)); 37285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt))); 3729552f7358SJed Brown if (mesh->maxSupportSize) { 37305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(mesh->supportSection)); 37315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(mesh->supportSection, &size)); 37325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size, &mesh->supports)); 37335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt))); 3734552f7358SJed Brown } 3735552f7358SJed Brown PetscFunctionReturn(0); 3736552f7358SJed Brown } 3737552f7358SJed Brown 3738276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3739552f7358SJed Brown { 3740552f7358SJed Brown PetscFunctionBegin; 37415f80ce2aSJacob Faibussowitsch if (subdm) CHKERRQ(DMClone(dm, subdm)); 37425f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 3743c2939958SSatish Balay if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3744736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 3745f94b4a02SBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 3746f94b4a02SBlaise Bourdin PetscSection section, sectionSeq; 3747f94b4a02SBlaise Bourdin 37483dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 37495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dm->sfMigration)); 37505f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection((*subdm), §ion)); 37515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv)); 37525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq)); 37535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 3754f94b4a02SBlaise Bourdin 37555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural)); 3756c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 37575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(§ionSeq)); 37585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfMigrationInv)); 3759f94b4a02SBlaise Bourdin } 3760552f7358SJed Brown PetscFunctionReturn(0); 3761552f7358SJed Brown } 3762552f7358SJed Brown 37632adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 37642adcc780SMatthew G. Knepley { 37653dcd263cSBlaise Bourdin PetscInt i = 0; 37662adcc780SMatthew G. Knepley 37672adcc780SMatthew G. Knepley PetscFunctionBegin; 37685f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dms[0], superdm)); 37695f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateSectionSuperDM(dms, len, is, superdm)); 3770c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 37713dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 37723dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 37733dcd263cSBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 37743dcd263cSBlaise Bourdin PetscSection section, sectionSeq; 37753dcd263cSBlaise Bourdin 37763dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 37775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dms[i]->sfMigration)); 3778c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 37795f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection((*superdm), §ion)); 37805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv)); 37815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq)); 37825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq)); 37833dcd263cSBlaise Bourdin 37845f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural)); 3785c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 37865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(§ionSeq)); 37875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfMigrationInv)); 37883dcd263cSBlaise Bourdin break; 37893dcd263cSBlaise Bourdin } 37903dcd263cSBlaise Bourdin } 37912adcc780SMatthew G. Knepley PetscFunctionReturn(0); 37922adcc780SMatthew G. Knepley } 37932adcc780SMatthew G. Knepley 3794552f7358SJed Brown /*@ 3795eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3796552f7358SJed Brown 3797552f7358SJed Brown Not collective 3798552f7358SJed Brown 3799552f7358SJed Brown Input Parameter: 3800552f7358SJed Brown . mesh - The DMPlex 3801552f7358SJed Brown 3802552f7358SJed Brown Output Parameter: 3803552f7358SJed Brown 3804552f7358SJed Brown Note: 3805552f7358SJed Brown This should be called after all calls to DMPlexSetCone() 3806552f7358SJed Brown 3807552f7358SJed Brown Level: beginner 3808552f7358SJed Brown 3809552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3810552f7358SJed Brown @*/ 3811552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm) 3812552f7358SJed Brown { 3813552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3814552f7358SJed Brown PetscInt *offsets; 3815552f7358SJed Brown PetscInt supportSize; 3816552f7358SJed Brown PetscInt pStart, pEnd, p; 3817552f7358SJed Brown 3818552f7358SJed Brown PetscFunctionBegin; 3819552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 382028b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 38215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0)); 3822552f7358SJed Brown /* Calculate support sizes */ 38235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 3824552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3825552f7358SJed Brown PetscInt dof, off, c; 3826552f7358SJed Brown 38275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3829552f7358SJed Brown for (c = off; c < off+dof; ++c) { 38305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 3831552f7358SJed Brown } 3832552f7358SJed Brown } 3833552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3834552f7358SJed Brown PetscInt dof; 3835552f7358SJed Brown 38365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof)); 38370d644c17SKarl Rupp 3838552f7358SJed Brown mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3839552f7358SJed Brown } 38405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(mesh->supportSection)); 3841552f7358SJed Brown /* Calculate supports */ 38425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 38435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(supportSize, &mesh->supports)); 38445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(pEnd - pStart, &offsets)); 3845552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3846552f7358SJed Brown PetscInt dof, off, c; 3847552f7358SJed Brown 38485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof)); 38495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3850552f7358SJed Brown for (c = off; c < off+dof; ++c) { 3851552f7358SJed Brown const PetscInt q = mesh->cones[c]; 3852552f7358SJed Brown PetscInt offS; 3853552f7358SJed Brown 38545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 38550d644c17SKarl Rupp 3856552f7358SJed Brown mesh->supports[offS+offsets[q]] = p; 3857552f7358SJed Brown ++offsets[q]; 3858552f7358SJed Brown } 3859552f7358SJed Brown } 38605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(offsets)); 38615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0)); 3862552f7358SJed Brown PetscFunctionReturn(0); 3863552f7358SJed Brown } 3864552f7358SJed Brown 3865277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3866277ea44aSLisandro Dalcin { 3867277ea44aSLisandro Dalcin IS stratumIS; 3868277ea44aSLisandro Dalcin 3869277ea44aSLisandro Dalcin PetscFunctionBegin; 3870277ea44aSLisandro Dalcin if (pStart >= pEnd) PetscFunctionReturn(0); 387176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3872277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 3873277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 38745f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetNumValues(label, &numLevels)); 3875277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 38765f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3877277ea44aSLisandro Dalcin if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3878277ea44aSLisandro Dalcin } 387928b400f6SJacob Faibussowitsch PetscCheck(!overlap,PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %D range [%D,%D) overlaps with depth %D range [%D,%D)", depth, pStart, pEnd, level, qStart, qEnd); 3880277ea44aSLisandro Dalcin } 38815f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS)); 38825f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetStratumIS(label, depth, stratumIS)); 38835f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&stratumIS)); 3884277ea44aSLisandro Dalcin PetscFunctionReturn(0); 3885277ea44aSLisandro Dalcin } 3886277ea44aSLisandro Dalcin 3887552f7358SJed Brown /*@ 3888a8d69d7bSBarry Smith DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 38896dd80730SBarry Smith can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3890552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3891552f7358SJed Brown the DAG. 3892552f7358SJed Brown 3893bf4602e4SToby Isaac Collective on dm 3894552f7358SJed Brown 3895552f7358SJed Brown Input Parameter: 3896552f7358SJed Brown . mesh - The DMPlex 3897552f7358SJed Brown 3898552f7358SJed Brown Output Parameter: 3899552f7358SJed Brown 3900552f7358SJed Brown Notes: 3901b1bb481bSMatthew Knepley Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3902b1bb481bSMatthew 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 3903b1bb481bSMatthew Knepley until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3904c58f1c22SToby Isaac manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3905150b719bSJed Brown via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3906552f7358SJed Brown 3907b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3908b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3909b1bb481bSMatthew 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 3910b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 3911b1bb481bSMatthew Knepley $ cone(c0) = {e0, v2} 3912b1bb481bSMatthew Knepley $ cone(e0) = {v0, v1} 3913b1bb481bSMatthew Knepley If DMPlexStratify() is run on this mesh, it will give depths 3914b1bb481bSMatthew Knepley $ depth 0 = {v0, v1, v2} 3915b1bb481bSMatthew Knepley $ depth 1 = {e0, c0} 3916b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3917b1bb481bSMatthew Knepley 3918150b719bSJed Brown DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3919552f7358SJed Brown 3920552f7358SJed Brown Level: beginner 3921552f7358SJed Brown 3922ba2698f1SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3923552f7358SJed Brown @*/ 3924552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm) 3925552f7358SJed Brown { 3926df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 3927aa50250dSMatthew G. Knepley DMLabel label; 3928552f7358SJed Brown PetscInt pStart, pEnd, p; 3929552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 3930552f7358SJed Brown 3931552f7358SJed Brown PetscFunctionBegin; 3932552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0)); 3934277ea44aSLisandro Dalcin 3935277ea44aSLisandro Dalcin /* Create depth label */ 39365f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 39375f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "depth")); 39385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm, &label)); 3939277ea44aSLisandro Dalcin 3940277ea44aSLisandro Dalcin { 3941552f7358SJed Brown /* Initialize roots and count leaves */ 3942277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3943277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3944552f7358SJed Brown PetscInt coneSize, supportSize; 3945552f7358SJed Brown 3946277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 39485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize)); 3949552f7358SJed Brown if (!coneSize && supportSize) { 3950277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3951277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3952552f7358SJed Brown ++numRoots; 3953552f7358SJed Brown } else if (!supportSize && coneSize) { 3954552f7358SJed Brown ++numLeaves; 3955552f7358SJed Brown } else if (!supportSize && !coneSize) { 3956552f7358SJed Brown /* Isolated points */ 3957277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3958277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3959552f7358SJed Brown } 3960552f7358SJed Brown } 39615f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1)); 3962277ea44aSLisandro Dalcin } 3963277ea44aSLisandro Dalcin 3964552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 3965277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3966277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 3967552f7358SJed Brown PetscInt coneSize, supportSize; 3968552f7358SJed Brown 3969277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 39705f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 39715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize)); 3972552f7358SJed Brown if (!supportSize && coneSize) { 3973277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 3974277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 3975552f7358SJed Brown } 3976552f7358SJed Brown } 39775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1)); 3978552f7358SJed Brown } else { 3979277ea44aSLisandro Dalcin PetscInt level = 0; 3980277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 3981552f7358SJed Brown 39825f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 3983277ea44aSLisandro Dalcin while (qEnd > qStart) { 3984277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 3985277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 398674ef644bSMatthew G. Knepley 3987277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 398874ef644bSMatthew G. Knepley const PetscInt *support; 398974ef644bSMatthew G. Knepley PetscInt supportSize, s; 399074ef644bSMatthew G. Knepley 39915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, q, &supportSize)); 39925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, q, &support)); 399374ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 3994277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 3995277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 3996552f7358SJed Brown } 3997552f7358SJed Brown } 39985f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetNumValues(label, &level)); 39995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1)); 40005f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 400174ef644bSMatthew G. Knepley } 400274ef644bSMatthew G. Knepley } 4003bf4602e4SToby Isaac { /* just in case there is an empty process */ 4004bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4005bf4602e4SToby Isaac 40065f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetNumValues(label, &numValues)); 40075f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 4008bf4602e4SToby Isaac for (v = numValues; v < maxValues; v++) { 40095f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelAddStratum(label, v)); 4010bf4602e4SToby Isaac } 4011bf4602e4SToby Isaac } 40125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectStateGet((PetscObject) label, &mesh->depthState)); 40135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0)); 4014552f7358SJed Brown PetscFunctionReturn(0); 4015552f7358SJed Brown } 4016552f7358SJed Brown 4017412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4018ba2698f1SMatthew G. Knepley { 4019412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4020412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4021ba2698f1SMatthew G. Knepley 4022412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 40235f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 40245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 40255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 4026ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4027ba2698f1SMatthew G. Knepley if (depth <= 1) { 4028ba2698f1SMatthew G. Knepley switch (pdepth) { 4029ba2698f1SMatthew G. Knepley case 0: ct = DM_POLYTOPE_POINT;break; 4030ba2698f1SMatthew G. Knepley case 1: 4031ba2698f1SMatthew G. Knepley switch (coneSize) { 4032ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4033ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4034ba2698f1SMatthew G. Knepley case 4: 4035ba2698f1SMatthew G. Knepley switch (dim) { 4036ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 4037ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 4038ba2698f1SMatthew G. Knepley default: break; 4039ba2698f1SMatthew G. Knepley } 4040ba2698f1SMatthew G. Knepley break; 4041da9060c4SMatthew G. Knepley case 5: ct = DM_POLYTOPE_PYRAMID;break; 4042ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4043ba2698f1SMatthew G. Knepley case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 4044ba2698f1SMatthew G. Knepley default: break; 4045ba2698f1SMatthew G. Knepley } 4046ba2698f1SMatthew G. Knepley } 4047ba2698f1SMatthew G. Knepley } else { 4048ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4049ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4050ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4051ba2698f1SMatthew G. Knepley switch (dim) { 4052ba2698f1SMatthew G. Knepley case 1: 4053ba2698f1SMatthew G. Knepley switch (coneSize) { 4054ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4055ba2698f1SMatthew G. Knepley default: break; 4056ba2698f1SMatthew G. Knepley } 4057ba2698f1SMatthew G. Knepley break; 4058ba2698f1SMatthew G. Knepley case 2: 4059ba2698f1SMatthew G. Knepley switch (coneSize) { 4060ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4061ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4062ba2698f1SMatthew G. Knepley default: break; 4063ba2698f1SMatthew G. Knepley } 4064ba2698f1SMatthew G. Knepley break; 4065ba2698f1SMatthew G. Knepley case 3: 4066ba2698f1SMatthew G. Knepley switch (coneSize) { 4067ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4068da9060c4SMatthew G. Knepley case 5: 4069da9060c4SMatthew G. Knepley { 4070da9060c4SMatthew G. Knepley const PetscInt *cone; 4071da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4072da9060c4SMatthew G. Knepley 40735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 40745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4075da9060c4SMatthew G. Knepley switch (faceConeSize) { 4076da9060c4SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4077da9060c4SMatthew G. Knepley case 4: ct = DM_POLYTOPE_PYRAMID;break; 4078da9060c4SMatthew G. Knepley } 4079da9060c4SMatthew G. Knepley } 4080da9060c4SMatthew G. Knepley break; 4081ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4082ba2698f1SMatthew G. Knepley default: break; 4083ba2698f1SMatthew G. Knepley } 4084ba2698f1SMatthew G. Knepley break; 4085ba2698f1SMatthew G. Knepley default: break; 4086ba2698f1SMatthew G. Knepley } 4087ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4088ba2698f1SMatthew G. Knepley switch (coneSize) { 4089ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 4090ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4091ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4092ba2698f1SMatthew G. Knepley default: break; 4093ba2698f1SMatthew G. Knepley } 4094ba2698f1SMatthew G. Knepley } 4095ba2698f1SMatthew G. Knepley } 4096412e9a14SMatthew G. Knepley *pt = ct; 4097412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 4098ba2698f1SMatthew G. Knepley } 4099412e9a14SMatthew G. Knepley 4100412e9a14SMatthew G. Knepley /*@ 4101412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4102412e9a14SMatthew G. Knepley 4103412e9a14SMatthew G. Knepley Collective on dm 4104412e9a14SMatthew G. Knepley 4105412e9a14SMatthew G. Knepley Input Parameter: 4106412e9a14SMatthew G. Knepley . mesh - The DMPlex 4107412e9a14SMatthew G. Knepley 4108412e9a14SMatthew G. Knepley DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4109412e9a14SMatthew G. Knepley 4110412e9a14SMatthew G. Knepley Level: developer 4111412e9a14SMatthew G. Knepley 4112412e9a14SMatthew G. Knepley Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4113412e9a14SMatthew G. Knepley internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4114412e9a14SMatthew G. Knepley automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4115412e9a14SMatthew G. Knepley 4116412e9a14SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 4117412e9a14SMatthew G. Knepley @*/ 4118412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm) 4119412e9a14SMatthew G. Knepley { 4120412e9a14SMatthew G. Knepley DM_Plex *mesh; 4121412e9a14SMatthew G. Knepley DMLabel ctLabel; 4122412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4123412e9a14SMatthew G. Knepley 4124412e9a14SMatthew G. Knepley PetscFunctionBegin; 4125412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4126412e9a14SMatthew G. Knepley mesh = (DM_Plex *) dm->data; 41275f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "celltype")); 41285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellTypeLabel(dm, &ctLabel)); 41295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 4130412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4131327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4132412e9a14SMatthew G. Knepley PetscInt pdepth; 4133412e9a14SMatthew G. Knepley 41345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPointDepth(dm, p, &pdepth)); 41355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 41362c71b3e2SJacob Faibussowitsch PetscCheckFalse(ct == DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 41375f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(ctLabel, p, ct)); 4138412e9a14SMatthew G. Knepley } 41395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState)); 41405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view")); 4141ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4142ba2698f1SMatthew G. Knepley } 4143ba2698f1SMatthew G. Knepley 4144552f7358SJed Brown /*@C 4145552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4146552f7358SJed Brown 4147552f7358SJed Brown Not Collective 4148552f7358SJed Brown 4149552f7358SJed Brown Input Parameters: 4150552f7358SJed Brown + dm - The DMPlex object 4151552f7358SJed Brown . numPoints - The number of input points for the join 4152552f7358SJed Brown - points - The input points 4153552f7358SJed Brown 4154552f7358SJed Brown Output Parameters: 4155552f7358SJed Brown + numCoveredPoints - The number of points in the join 4156552f7358SJed Brown - coveredPoints - The points in the join 4157552f7358SJed Brown 4158552f7358SJed Brown Level: intermediate 4159552f7358SJed Brown 4160552f7358SJed Brown Note: Currently, this is restricted to a single level join 4161552f7358SJed Brown 41623813dfbdSMatthew G Knepley Fortran Notes: 41633813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 41643813dfbdSMatthew G Knepley include petsc.h90 in your code. 41653813dfbdSMatthew G Knepley 41663813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 41673813dfbdSMatthew G Knepley 4168552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 4169552f7358SJed Brown @*/ 4170552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4171552f7358SJed Brown { 4172552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4173552f7358SJed Brown PetscInt *join[2]; 4174552f7358SJed Brown PetscInt joinSize, i = 0; 4175552f7358SJed Brown PetscInt dof, off, p, c, m; 4176552f7358SJed Brown 4177552f7358SJed Brown PetscFunctionBegin; 4178552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 417948bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 418048bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 418148bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 41825f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0])); 41835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1])); 4184552f7358SJed Brown /* Copy in support of first point */ 41855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 41865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4187552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4188552f7358SJed Brown join[i][joinSize] = mesh->supports[off+joinSize]; 4189552f7358SJed Brown } 4190552f7358SJed Brown /* Check each successive support */ 4191552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4192552f7358SJed Brown PetscInt newJoinSize = 0; 4193552f7358SJed Brown 41945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 41955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4196552f7358SJed Brown for (c = 0; c < dof; ++c) { 4197552f7358SJed Brown const PetscInt point = mesh->supports[off+c]; 4198552f7358SJed Brown 4199552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4200552f7358SJed Brown if (point == join[i][m]) { 4201552f7358SJed Brown join[1-i][newJoinSize++] = point; 4202552f7358SJed Brown break; 4203552f7358SJed Brown } 4204552f7358SJed Brown } 4205552f7358SJed Brown } 4206552f7358SJed Brown joinSize = newJoinSize; 4207552f7358SJed Brown i = 1-i; 4208552f7358SJed Brown } 4209552f7358SJed Brown *numCoveredPoints = joinSize; 4210552f7358SJed Brown *coveredPoints = join[i]; 42115f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i])); 4212552f7358SJed Brown PetscFunctionReturn(0); 4213552f7358SJed Brown } 4214552f7358SJed Brown 4215552f7358SJed Brown /*@C 4216552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4217552f7358SJed Brown 4218552f7358SJed Brown Not Collective 4219552f7358SJed Brown 4220552f7358SJed Brown Input Parameters: 4221552f7358SJed Brown + dm - The DMPlex object 4222552f7358SJed Brown . numPoints - The number of input points for the join 4223552f7358SJed Brown - points - The input points 4224552f7358SJed Brown 4225552f7358SJed Brown Output Parameters: 4226552f7358SJed Brown + numCoveredPoints - The number of points in the join 4227552f7358SJed Brown - coveredPoints - The points in the join 4228552f7358SJed Brown 42293813dfbdSMatthew G Knepley Fortran Notes: 42303813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42313813dfbdSMatthew G Knepley include petsc.h90 in your code. 42323813dfbdSMatthew G Knepley 42333813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42343813dfbdSMatthew G Knepley 4235552f7358SJed Brown Level: intermediate 4236552f7358SJed Brown 4237552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4238552f7358SJed Brown @*/ 4239552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4240552f7358SJed Brown { 4241552f7358SJed Brown PetscFunctionBegin; 4242552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4243d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4244d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4245d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 42465f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4247d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4248552f7358SJed Brown PetscFunctionReturn(0); 4249552f7358SJed Brown } 4250552f7358SJed Brown 4251552f7358SJed Brown /*@C 4252552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4253552f7358SJed Brown 4254552f7358SJed Brown Not Collective 4255552f7358SJed Brown 4256552f7358SJed Brown Input Parameters: 4257552f7358SJed Brown + dm - The DMPlex object 4258552f7358SJed Brown . numPoints - The number of input points for the join 4259552f7358SJed Brown - points - The input points 4260552f7358SJed Brown 4261552f7358SJed Brown Output Parameters: 4262552f7358SJed Brown + numCoveredPoints - The number of points in the join 4263552f7358SJed Brown - coveredPoints - The points in the join 4264552f7358SJed Brown 42653813dfbdSMatthew G Knepley Fortran Notes: 42663813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 42673813dfbdSMatthew G Knepley include petsc.h90 in your code. 42683813dfbdSMatthew G Knepley 42693813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 42703813dfbdSMatthew G Knepley 4271552f7358SJed Brown Level: intermediate 4272552f7358SJed Brown 4273552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4274552f7358SJed Brown @*/ 4275552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4276552f7358SJed Brown { 4277552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4278552f7358SJed Brown PetscInt *offsets, **closures; 4279552f7358SJed Brown PetscInt *join[2]; 4280552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 428124c766afSToby Isaac PetscInt p, d, c, m, ms; 4282552f7358SJed Brown 4283552f7358SJed Brown PetscFunctionBegin; 4284552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 428548bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 428648bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 428748bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 4288552f7358SJed Brown 42895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 42905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numPoints, &closures)); 42915f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 429224c766afSToby Isaac ms = mesh->maxSupportSize; 429324c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 42945f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 42955f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4296552f7358SJed Brown 4297552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4298552f7358SJed Brown PetscInt closureSize; 4299552f7358SJed Brown 43005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 43010d644c17SKarl Rupp 4302552f7358SJed Brown offsets[p*(depth+2)+0] = 0; 4303552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4304552f7358SJed Brown PetscInt pStart, pEnd, i; 4305552f7358SJed Brown 43065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4307552f7358SJed Brown for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4308552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4309552f7358SJed Brown offsets[p*(depth+2)+d+1] = i; 4310552f7358SJed Brown break; 4311552f7358SJed Brown } 4312552f7358SJed Brown } 4313552f7358SJed Brown if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4314552f7358SJed Brown } 43152c71b3e2SJacob Faibussowitsch PetscCheckFalse(offsets[p*(depth+2)+depth+1] != closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 4316552f7358SJed Brown } 4317552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 4318552f7358SJed Brown PetscInt dof; 4319552f7358SJed Brown 4320552f7358SJed Brown /* Copy in support of first point */ 4321552f7358SJed Brown dof = offsets[d+1] - offsets[d]; 4322552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 4323552f7358SJed Brown join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4324552f7358SJed Brown } 4325552f7358SJed Brown /* Check each successive cone */ 4326552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4327552f7358SJed Brown PetscInt newJoinSize = 0; 4328552f7358SJed Brown 4329552f7358SJed Brown dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4330552f7358SJed Brown for (c = 0; c < dof; ++c) { 4331552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4332552f7358SJed Brown 4333552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4334552f7358SJed Brown if (point == join[i][m]) { 4335552f7358SJed Brown join[1-i][newJoinSize++] = point; 4336552f7358SJed Brown break; 4337552f7358SJed Brown } 4338552f7358SJed Brown } 4339552f7358SJed Brown } 4340552f7358SJed Brown joinSize = newJoinSize; 4341552f7358SJed Brown i = 1-i; 4342552f7358SJed Brown } 4343552f7358SJed Brown if (joinSize) break; 4344552f7358SJed Brown } 4345552f7358SJed Brown *numCoveredPoints = joinSize; 4346552f7358SJed Brown *coveredPoints = join[i]; 4347552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 43485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 4349552f7358SJed Brown } 43505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(closures)); 43515f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets)); 43525f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i])); 4353552f7358SJed Brown PetscFunctionReturn(0); 4354552f7358SJed Brown } 4355552f7358SJed Brown 4356552f7358SJed Brown /*@C 4357552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4358552f7358SJed Brown 4359552f7358SJed Brown Not Collective 4360552f7358SJed Brown 4361552f7358SJed Brown Input Parameters: 4362552f7358SJed Brown + dm - The DMPlex object 4363552f7358SJed Brown . numPoints - The number of input points for the meet 4364552f7358SJed Brown - points - The input points 4365552f7358SJed Brown 4366552f7358SJed Brown Output Parameters: 4367552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4368552f7358SJed Brown - coveredPoints - The points in the meet 4369552f7358SJed Brown 4370552f7358SJed Brown Level: intermediate 4371552f7358SJed Brown 4372552f7358SJed Brown Note: Currently, this is restricted to a single level meet 4373552f7358SJed Brown 43743813dfbdSMatthew G Knepley Fortran Notes: 43753813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 43763813dfbdSMatthew G Knepley include petsc.h90 in your code. 43773813dfbdSMatthew G Knepley 43783813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 43793813dfbdSMatthew G Knepley 4380552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4381552f7358SJed Brown @*/ 4382552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4383552f7358SJed Brown { 4384552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4385552f7358SJed Brown PetscInt *meet[2]; 4386552f7358SJed Brown PetscInt meetSize, i = 0; 4387552f7358SJed Brown PetscInt dof, off, p, c, m; 4388552f7358SJed Brown 4389552f7358SJed Brown PetscFunctionBegin; 4390552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4391*dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4392*dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveringPoints, 4); 4393064a246eSJacob Faibussowitsch PetscValidPointer(coveringPoints, 5); 43945f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0])); 43955f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1])); 4396552f7358SJed Brown /* Copy in cone of first point */ 43975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 43985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4399552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4400552f7358SJed Brown meet[i][meetSize] = mesh->cones[off+meetSize]; 4401552f7358SJed Brown } 4402552f7358SJed Brown /* Check each successive cone */ 4403552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4404552f7358SJed Brown PetscInt newMeetSize = 0; 4405552f7358SJed Brown 44065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 44075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4408552f7358SJed Brown for (c = 0; c < dof; ++c) { 4409552f7358SJed Brown const PetscInt point = mesh->cones[off+c]; 4410552f7358SJed Brown 4411552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4412552f7358SJed Brown if (point == meet[i][m]) { 4413552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4414552f7358SJed Brown break; 4415552f7358SJed Brown } 4416552f7358SJed Brown } 4417552f7358SJed Brown } 4418552f7358SJed Brown meetSize = newMeetSize; 4419552f7358SJed Brown i = 1-i; 4420552f7358SJed Brown } 4421552f7358SJed Brown *numCoveringPoints = meetSize; 4422552f7358SJed Brown *coveringPoints = meet[i]; 44235f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i])); 4424552f7358SJed Brown PetscFunctionReturn(0); 4425552f7358SJed Brown } 4426552f7358SJed Brown 4427552f7358SJed Brown /*@C 4428552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4429552f7358SJed Brown 4430552f7358SJed Brown Not Collective 4431552f7358SJed Brown 4432552f7358SJed Brown Input Parameters: 4433552f7358SJed Brown + dm - The DMPlex object 4434552f7358SJed Brown . numPoints - The number of input points for the meet 4435552f7358SJed Brown - points - The input points 4436552f7358SJed Brown 4437552f7358SJed Brown Output Parameters: 4438552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4439552f7358SJed Brown - coveredPoints - The points in the meet 4440552f7358SJed Brown 4441552f7358SJed Brown Level: intermediate 4442552f7358SJed Brown 44433813dfbdSMatthew G Knepley Fortran Notes: 44443813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44453813dfbdSMatthew G Knepley include petsc.h90 in your code. 44463813dfbdSMatthew G Knepley 44473813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44483813dfbdSMatthew G Knepley 4449552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4450552f7358SJed Brown @*/ 4451552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4452552f7358SJed Brown { 4453552f7358SJed Brown PetscFunctionBegin; 4454552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4455d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 4456d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4457d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints,5); 44585f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints)); 4459d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 4460552f7358SJed Brown PetscFunctionReturn(0); 4461552f7358SJed Brown } 4462552f7358SJed Brown 4463552f7358SJed Brown /*@C 4464552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4465552f7358SJed Brown 4466552f7358SJed Brown Not Collective 4467552f7358SJed Brown 4468552f7358SJed Brown Input Parameters: 4469552f7358SJed Brown + dm - The DMPlex object 4470552f7358SJed Brown . numPoints - The number of input points for the meet 4471552f7358SJed Brown - points - The input points 4472552f7358SJed Brown 4473552f7358SJed Brown Output Parameters: 4474552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4475552f7358SJed Brown - coveredPoints - The points in the meet 4476552f7358SJed Brown 4477552f7358SJed Brown Level: intermediate 4478552f7358SJed Brown 44793813dfbdSMatthew G Knepley Fortran Notes: 44803813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 44813813dfbdSMatthew G Knepley include petsc.h90 in your code. 44823813dfbdSMatthew G Knepley 44833813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 44843813dfbdSMatthew G Knepley 4485552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4486552f7358SJed Brown @*/ 4487552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4488552f7358SJed Brown { 4489552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4490552f7358SJed Brown PetscInt *offsets, **closures; 4491552f7358SJed Brown PetscInt *meet[2]; 4492552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 449324c766afSToby Isaac PetscInt p, h, c, m, mc; 4494552f7358SJed Brown 4495552f7358SJed Brown PetscFunctionBegin; 4496552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4497*dadcf809SJacob Faibussowitsch PetscValidIntPointer(points, 3); 4498*dadcf809SJacob Faibussowitsch PetscValidIntPointer(numCoveredPoints, 4); 4499064a246eSJacob Faibussowitsch PetscValidPointer(coveredPoints, 5); 4500552f7358SJed Brown 45015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &height)); 45025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numPoints, &closures)); 45035f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 450424c766afSToby Isaac mc = mesh->maxConeSize; 450524c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 45065f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 45075f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4508552f7358SJed Brown 4509552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4510552f7358SJed Brown PetscInt closureSize; 4511552f7358SJed Brown 45125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 45130d644c17SKarl Rupp 4514552f7358SJed Brown offsets[p*(height+2)+0] = 0; 4515552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4516552f7358SJed Brown PetscInt pStart, pEnd, i; 4517552f7358SJed Brown 45185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4519552f7358SJed Brown for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4520552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4521552f7358SJed Brown offsets[p*(height+2)+h+1] = i; 4522552f7358SJed Brown break; 4523552f7358SJed Brown } 4524552f7358SJed Brown } 4525552f7358SJed Brown if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4526552f7358SJed Brown } 45272c71b3e2SJacob Faibussowitsch PetscCheckFalse(offsets[p*(height+2)+height+1] != closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 4528552f7358SJed Brown } 4529552f7358SJed Brown for (h = 0; h < height+1; ++h) { 4530552f7358SJed Brown PetscInt dof; 4531552f7358SJed Brown 4532552f7358SJed Brown /* Copy in cone of first point */ 4533552f7358SJed Brown dof = offsets[h+1] - offsets[h]; 4534552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 4535552f7358SJed Brown meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4536552f7358SJed Brown } 4537552f7358SJed Brown /* Check each successive cone */ 4538552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4539552f7358SJed Brown PetscInt newMeetSize = 0; 4540552f7358SJed Brown 4541552f7358SJed Brown dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4542552f7358SJed Brown for (c = 0; c < dof; ++c) { 4543552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4544552f7358SJed Brown 4545552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4546552f7358SJed Brown if (point == meet[i][m]) { 4547552f7358SJed Brown meet[1-i][newMeetSize++] = point; 4548552f7358SJed Brown break; 4549552f7358SJed Brown } 4550552f7358SJed Brown } 4551552f7358SJed Brown } 4552552f7358SJed Brown meetSize = newMeetSize; 4553552f7358SJed Brown i = 1-i; 4554552f7358SJed Brown } 4555552f7358SJed Brown if (meetSize) break; 4556552f7358SJed Brown } 4557552f7358SJed Brown *numCoveredPoints = meetSize; 4558552f7358SJed Brown *coveredPoints = meet[i]; 4559552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 45605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 4561552f7358SJed Brown } 45625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(closures)); 45635f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets)); 45645f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i])); 4565552f7358SJed Brown PetscFunctionReturn(0); 4566552f7358SJed Brown } 4567552f7358SJed Brown 45684e3744c5SMatthew G. Knepley /*@C 45694e3744c5SMatthew G. Knepley DMPlexEqual - Determine if two DMs have the same topology 45704e3744c5SMatthew G. Knepley 45714e3744c5SMatthew G. Knepley Not Collective 45724e3744c5SMatthew G. Knepley 45734e3744c5SMatthew G. Knepley Input Parameters: 45744e3744c5SMatthew G. Knepley + dmA - A DMPlex object 45754e3744c5SMatthew G. Knepley - dmB - A DMPlex object 45764e3744c5SMatthew G. Knepley 45774e3744c5SMatthew G. Knepley Output Parameters: 45784e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical 45794e3744c5SMatthew G. Knepley 45804e3744c5SMatthew G. Knepley Level: intermediate 45814e3744c5SMatthew G. Knepley 45824e3744c5SMatthew G. Knepley Notes: 45834e3744c5SMatthew G. Knepley We are not solving graph isomorphism, so we do not permutation. 45844e3744c5SMatthew G. Knepley 45854e3744c5SMatthew G. Knepley .seealso: DMPlexGetCone() 45864e3744c5SMatthew G. Knepley @*/ 45874e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 45884e3744c5SMatthew G. Knepley { 45894e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 45904e3744c5SMatthew G. Knepley 45914e3744c5SMatthew G. Knepley PetscFunctionBegin; 45924e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 45934e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4594*dadcf809SJacob Faibussowitsch PetscValidBoolPointer(equal, 3); 45954e3744c5SMatthew G. Knepley 45964e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 45975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dmA, &depth)); 45985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dmB, &depthB)); 45994e3744c5SMatthew G. Knepley if (depth != depthB) PetscFunctionReturn(0); 46005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dmA, &pStart, &pEnd)); 46015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dmB, &pStartB, &pEndB)); 46024e3744c5SMatthew G. Knepley if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 46034e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 46044e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 46054e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 46064e3744c5SMatthew G. Knepley 46075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dmA, p, &coneSize)); 46085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dmA, p, &cone)); 46095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dmA, p, &ornt)); 46105f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dmB, p, &coneSizeB)); 46115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dmB, p, &coneB)); 46125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dmB, p, &orntB)); 46134e3744c5SMatthew G. Knepley if (coneSize != coneSizeB) PetscFunctionReturn(0); 46144e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 46154e3744c5SMatthew G. Knepley if (cone[c] != coneB[c]) PetscFunctionReturn(0); 46164e3744c5SMatthew G. Knepley if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 46174e3744c5SMatthew G. Knepley } 46185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dmA, p, &supportSize)); 46195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dmA, p, &support)); 46205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 46215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dmB, p, &supportB)); 46224e3744c5SMatthew G. Knepley if (supportSize != supportSizeB) PetscFunctionReturn(0); 46234e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 46244e3744c5SMatthew G. Knepley if (support[s] != supportB[s]) PetscFunctionReturn(0); 46254e3744c5SMatthew G. Knepley } 46264e3744c5SMatthew G. Knepley } 46274e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 46284e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 46294e3744c5SMatthew G. Knepley } 46304e3744c5SMatthew G. Knepley 46317cd05799SMatthew G. Knepley /*@C 46327cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 46337cd05799SMatthew G. Knepley 46347cd05799SMatthew G. Knepley Not Collective 46357cd05799SMatthew G. Knepley 46367cd05799SMatthew G. Knepley Input Parameters: 46377cd05799SMatthew G. Knepley + dm - The DMPlex 46387cd05799SMatthew G. Knepley . cellDim - The cell dimension 46397cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 46407cd05799SMatthew G. Knepley 46417cd05799SMatthew G. Knepley Output Parameters: 46427cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 46437cd05799SMatthew G. Knepley 46447cd05799SMatthew G. Knepley Level: developer 46457cd05799SMatthew G. Knepley 46467cd05799SMatthew G. Knepley Notes: 46477cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 46487cd05799SMatthew G. Knepley 46497cd05799SMatthew G. Knepley .seealso: DMPlexGetCone() 46507cd05799SMatthew G. Knepley @*/ 465118ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4652a6dfd86eSKarl Rupp { 465382f516ccSBarry Smith MPI_Comm comm; 4654552f7358SJed Brown 4655552f7358SJed Brown PetscFunctionBegin; 46565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm)); 4657*dadcf809SJacob Faibussowitsch PetscValidIntPointer(numFaceVertices,4); 4658552f7358SJed Brown switch (cellDim) { 4659552f7358SJed Brown case 0: 4660552f7358SJed Brown *numFaceVertices = 0; 4661552f7358SJed Brown break; 4662552f7358SJed Brown case 1: 4663552f7358SJed Brown *numFaceVertices = 1; 4664552f7358SJed Brown break; 4665552f7358SJed Brown case 2: 4666552f7358SJed Brown switch (numCorners) { 466719436ca2SJed Brown case 3: /* triangle */ 466819436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4669552f7358SJed Brown break; 467019436ca2SJed Brown case 4: /* quadrilateral */ 467119436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 4672552f7358SJed Brown break; 467319436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 467419436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4675552f7358SJed Brown break; 467619436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 467719436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 4678552f7358SJed Brown break; 4679552f7358SJed Brown default: 468098921bdaSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4681552f7358SJed Brown } 4682552f7358SJed Brown break; 4683552f7358SJed Brown case 3: 4684552f7358SJed Brown switch (numCorners) { 468519436ca2SJed Brown case 4: /* tetradehdron */ 468619436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 4687552f7358SJed Brown break; 468819436ca2SJed Brown case 6: /* tet cohesive cells */ 468919436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4690552f7358SJed Brown break; 469119436ca2SJed Brown case 8: /* hexahedron */ 469219436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 4693552f7358SJed Brown break; 469419436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 469519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4696552f7358SJed Brown break; 469719436ca2SJed Brown case 10: /* quadratic tetrahedron */ 469819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4699552f7358SJed Brown break; 470019436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 470119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4702552f7358SJed Brown break; 470319436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 470419436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 4705552f7358SJed Brown break; 470619436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 470719436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 4708552f7358SJed Brown break; 4709552f7358SJed Brown default: 471098921bdaSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4711552f7358SJed Brown } 4712552f7358SJed Brown break; 4713552f7358SJed Brown default: 471498921bdaSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4715552f7358SJed Brown } 4716552f7358SJed Brown PetscFunctionReturn(0); 4717552f7358SJed Brown } 4718552f7358SJed Brown 4719552f7358SJed Brown /*@ 4720aa50250dSMatthew G. Knepley DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4721552f7358SJed Brown 4722552f7358SJed Brown Not Collective 4723552f7358SJed Brown 4724aa50250dSMatthew G. Knepley Input Parameter: 4725552f7358SJed Brown . dm - The DMPlex object 4726552f7358SJed Brown 4727aa50250dSMatthew G. Knepley Output Parameter: 4728aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth 4729552f7358SJed Brown 4730552f7358SJed Brown Level: developer 4731552f7358SJed Brown 4732dc287ab2SVaclav Hapla .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4733aa50250dSMatthew G. Knepley @*/ 4734aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4735aa50250dSMatthew G. Knepley { 4736aa50250dSMatthew G. Knepley PetscFunctionBegin; 4737aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4738aa50250dSMatthew G. Knepley PetscValidPointer(depthLabel, 2); 4739c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 4740aa50250dSMatthew G. Knepley PetscFunctionReturn(0); 4741aa50250dSMatthew G. Knepley } 4742aa50250dSMatthew G. Knepley 4743aa50250dSMatthew G. Knepley /*@ 4744aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 4745aa50250dSMatthew G. Knepley 4746aa50250dSMatthew G. Knepley Not Collective 4747aa50250dSMatthew G. Knepley 4748aa50250dSMatthew G. Knepley Input Parameter: 4749aa50250dSMatthew G. Knepley . dm - The DMPlex object 4750aa50250dSMatthew G. Knepley 4751aa50250dSMatthew G. Knepley Output Parameter: 4752aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 4753aa50250dSMatthew G. Knepley 4754aa50250dSMatthew G. Knepley Level: developer 4755552f7358SJed Brown 4756b1bb481bSMatthew Knepley Notes: 4757b1bb481bSMatthew Knepley This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4758dc287ab2SVaclav Hapla The point depth is described more in detail in DMPlexGetDepthStratum(). 4759dc287ab2SVaclav Hapla An empty mesh gives -1. 4760b1bb481bSMatthew Knepley 4761dc287ab2SVaclav Hapla .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4762552f7358SJed Brown @*/ 4763552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4764552f7358SJed Brown { 4765aa50250dSMatthew G. Knepley DMLabel label; 4766aa50250dSMatthew G. Knepley PetscInt d = 0; 4767552f7358SJed Brown 4768552f7358SJed Brown PetscFunctionBegin; 4769552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4770*dadcf809SJacob Faibussowitsch PetscValidIntPointer(depth, 2); 47715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm, &label)); 47725f80ce2aSJacob Faibussowitsch if (label) CHKERRQ(DMLabelGetNumValues(label, &d)); 4773552f7358SJed Brown *depth = d-1; 4774552f7358SJed Brown PetscFunctionReturn(0); 4775552f7358SJed Brown } 4776552f7358SJed Brown 4777552f7358SJed Brown /*@ 4778552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4779552f7358SJed Brown 4780552f7358SJed Brown Not Collective 4781552f7358SJed Brown 4782552f7358SJed Brown Input Parameters: 4783552f7358SJed Brown + dm - The DMPlex object 4784552f7358SJed Brown - stratumValue - The requested depth 4785552f7358SJed Brown 4786552f7358SJed Brown Output Parameters: 4787552f7358SJed Brown + start - The first point at this depth 4788552f7358SJed Brown - end - One beyond the last point at this depth 4789552f7358SJed Brown 4790647867b2SJed Brown Notes: 4791647867b2SJed Brown Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4792647867b2SJed Brown often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4793647867b2SJed Brown higher dimension, e.g., "edges". 4794647867b2SJed Brown 4795552f7358SJed Brown Level: developer 4796552f7358SJed Brown 4797dc287ab2SVaclav Hapla .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4798552f7358SJed Brown @*/ 47990adebc6cSBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 48000adebc6cSBarry Smith { 4801aa50250dSMatthew G. Knepley DMLabel label; 480263d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 4803552f7358SJed Brown 4804552f7358SJed Brown PetscFunctionBegin; 4805552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4806*dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4807*dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 48090d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 481063d1a920SMatthew G. Knepley if (stratumValue < 0) { 481163d1a920SMatthew G. Knepley if (start) *start = pStart; 481263d1a920SMatthew G. Knepley if (end) *end = pEnd; 481363d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4814552f7358SJed Brown } 48155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm, &label)); 481628b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 48175f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumBounds(label, stratumValue, start, end)); 4818552f7358SJed Brown PetscFunctionReturn(0); 4819552f7358SJed Brown } 4820552f7358SJed Brown 4821552f7358SJed Brown /*@ 4822552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4823552f7358SJed Brown 4824552f7358SJed Brown Not Collective 4825552f7358SJed Brown 4826552f7358SJed Brown Input Parameters: 4827552f7358SJed Brown + dm - The DMPlex object 4828552f7358SJed Brown - stratumValue - The requested height 4829552f7358SJed Brown 4830552f7358SJed Brown Output Parameters: 4831552f7358SJed Brown + start - The first point at this height 4832552f7358SJed Brown - end - One beyond the last point at this height 4833552f7358SJed Brown 4834647867b2SJed Brown Notes: 4835647867b2SJed Brown Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4836647867b2SJed Brown points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4837647867b2SJed Brown stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4838647867b2SJed Brown 4839552f7358SJed Brown Level: developer 4840552f7358SJed Brown 48413dc9a465SVaclav Hapla .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4842552f7358SJed Brown @*/ 48430adebc6cSBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 48440adebc6cSBarry Smith { 4845aa50250dSMatthew G. Knepley DMLabel label; 484663d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 4847552f7358SJed Brown 4848552f7358SJed Brown PetscFunctionBegin; 4849552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4850*dadcf809SJacob Faibussowitsch if (start) {PetscValidIntPointer(start, 3); *start = 0;} 4851*dadcf809SJacob Faibussowitsch if (end) {PetscValidIntPointer(end, 4); *end = 0;} 48525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 48530d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 485463d1a920SMatthew G. Knepley if (stratumValue < 0) { 485563d1a920SMatthew G. Knepley if (start) *start = pStart; 485663d1a920SMatthew G. Knepley if (end) *end = pEnd; 485763d1a920SMatthew G. Knepley PetscFunctionReturn(0); 4858552f7358SJed Brown } 48595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm, &label)); 486028b400f6SJacob Faibussowitsch PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 48615f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetNumValues(label, &depth)); 48625f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end)); 4863552f7358SJed Brown PetscFunctionReturn(0); 4864552f7358SJed Brown } 4865552f7358SJed Brown 4866ba2698f1SMatthew G. Knepley /*@ 4867ba2698f1SMatthew G. Knepley DMPlexGetPointDepth - Get the depth of a given point 4868ba2698f1SMatthew G. Knepley 4869ba2698f1SMatthew G. Knepley Not Collective 4870ba2698f1SMatthew G. Knepley 4871d8d19677SJose E. Roman Input Parameters: 4872ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4873ba2698f1SMatthew G. Knepley - point - The point 4874ba2698f1SMatthew G. Knepley 4875ba2698f1SMatthew G. Knepley Output Parameter: 4876ba2698f1SMatthew G. Knepley . depth - The depth of the point 4877ba2698f1SMatthew G. Knepley 4878ba2698f1SMatthew G. Knepley Level: intermediate 4879ba2698f1SMatthew G. Knepley 48803dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4881ba2698f1SMatthew G. Knepley @*/ 4882ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4883ba2698f1SMatthew G. Knepley { 4884ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4885ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 488640a2aa30SMatthew G. Knepley PetscValidIntPointer(depth, 3); 48875f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(dm->depthLabel, point, depth)); 4888ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4889ba2698f1SMatthew G. Knepley } 4890ba2698f1SMatthew G. Knepley 4891ba2698f1SMatthew G. Knepley /*@ 48920c0a32dcSVaclav Hapla DMPlexGetPointHeight - Get the height of a given point 48930c0a32dcSVaclav Hapla 48940c0a32dcSVaclav Hapla Not Collective 48950c0a32dcSVaclav Hapla 4896d8d19677SJose E. Roman Input Parameters: 48970c0a32dcSVaclav Hapla + dm - The DMPlex object 48980c0a32dcSVaclav Hapla - point - The point 48990c0a32dcSVaclav Hapla 49000c0a32dcSVaclav Hapla Output Parameter: 49010c0a32dcSVaclav Hapla . height - The height of the point 49020c0a32dcSVaclav Hapla 49030c0a32dcSVaclav Hapla Level: intermediate 49040c0a32dcSVaclav Hapla 49053dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 49060c0a32dcSVaclav Hapla @*/ 49070c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 49080c0a32dcSVaclav Hapla { 49090c0a32dcSVaclav Hapla PetscInt n, pDepth; 49100c0a32dcSVaclav Hapla 49110c0a32dcSVaclav Hapla PetscFunctionBegin; 49120c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49130c0a32dcSVaclav Hapla PetscValidIntPointer(height, 3); 49145f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetNumValues(dm->depthLabel, &n)); 49155f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 49160c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 49170c0a32dcSVaclav Hapla PetscFunctionReturn(0); 49180c0a32dcSVaclav Hapla } 49190c0a32dcSVaclav Hapla 49200c0a32dcSVaclav Hapla /*@ 4921ba2698f1SMatthew G. Knepley DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4922ba2698f1SMatthew G. Knepley 4923ba2698f1SMatthew G. Knepley Not Collective 4924ba2698f1SMatthew G. Knepley 4925ba2698f1SMatthew G. Knepley Input Parameter: 4926ba2698f1SMatthew G. Knepley . dm - The DMPlex object 4927ba2698f1SMatthew G. Knepley 4928ba2698f1SMatthew G. Knepley Output Parameter: 4929ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type 4930ba2698f1SMatthew G. Knepley 4931412e9a14SMatthew G. Knepley Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4932412e9a14SMatthew G. Knepley DMCreateLabel(dm, "celltype") beforehand. 4933412e9a14SMatthew G. Knepley 4934ba2698f1SMatthew G. Knepley Level: developer 4935ba2698f1SMatthew G. Knepley 4936dc287ab2SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4937ba2698f1SMatthew G. Knepley @*/ 4938ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4939ba2698f1SMatthew G. Knepley { 4940ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4941ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4942ba2698f1SMatthew G. Knepley PetscValidPointer(celltypeLabel, 2); 49435f80ce2aSJacob Faibussowitsch if (!dm->celltypeLabel) CHKERRQ(DMPlexComputeCellTypes(dm)); 4944ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 4945ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4946ba2698f1SMatthew G. Knepley } 4947ba2698f1SMatthew G. Knepley 4948ba2698f1SMatthew G. Knepley /*@ 4949ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 4950ba2698f1SMatthew G. Knepley 4951ba2698f1SMatthew G. Knepley Not Collective 4952ba2698f1SMatthew G. Knepley 4953d8d19677SJose E. Roman Input Parameters: 4954ba2698f1SMatthew G. Knepley + dm - The DMPlex object 4955ba2698f1SMatthew G. Knepley - cell - The cell 4956ba2698f1SMatthew G. Knepley 4957ba2698f1SMatthew G. Knepley Output Parameter: 4958ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 4959ba2698f1SMatthew G. Knepley 4960ba2698f1SMatthew G. Knepley Level: intermediate 4961ba2698f1SMatthew G. Knepley 4962ba2698f1SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4963ba2698f1SMatthew G. Knepley @*/ 4964ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4965ba2698f1SMatthew G. Knepley { 4966ba2698f1SMatthew G. Knepley DMLabel label; 4967ba2698f1SMatthew G. Knepley PetscInt ct; 4968ba2698f1SMatthew G. Knepley 4969ba2698f1SMatthew G. Knepley PetscFunctionBegin; 4970ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4971ba2698f1SMatthew G. Knepley PetscValidPointer(celltype, 3); 49725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellTypeLabel(dm, &label)); 49735f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(label, cell, &ct)); 49742c71b3e2SJacob Faibussowitsch PetscCheckFalse(ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4975ba2698f1SMatthew G. Knepley *celltype = (DMPolytopeType) ct; 4976ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 4977ba2698f1SMatthew G. Knepley } 4978ba2698f1SMatthew G. Knepley 4979412e9a14SMatthew G. Knepley /*@ 4980412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 4981412e9a14SMatthew G. Knepley 4982412e9a14SMatthew G. Knepley Not Collective 4983412e9a14SMatthew G. Knepley 4984412e9a14SMatthew G. Knepley Input Parameters: 4985412e9a14SMatthew G. Knepley + dm - The DMPlex object 4986412e9a14SMatthew G. Knepley . cell - The cell 4987412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 4988412e9a14SMatthew G. Knepley 4989412e9a14SMatthew G. Knepley Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4990412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 4991412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 4992412e9a14SMatthew G. Knepley DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4993412e9a14SMatthew G. Knepley 4994412e9a14SMatthew G. Knepley Level: advanced 4995412e9a14SMatthew G. Knepley 4996412e9a14SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4997412e9a14SMatthew G. Knepley @*/ 4998412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4999412e9a14SMatthew G. Knepley { 5000412e9a14SMatthew G. Knepley DMLabel label; 5001412e9a14SMatthew G. Knepley 5002412e9a14SMatthew G. Knepley PetscFunctionBegin; 5003412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50045f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellTypeLabel(dm, &label)); 50055f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(label, cell, celltype)); 5006412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 5007412e9a14SMatthew G. Knepley } 5008412e9a14SMatthew G. Knepley 50090adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 50100adebc6cSBarry Smith { 5011efe440bfSMatthew G. Knepley PetscSection section, s; 5012efe440bfSMatthew G. Knepley Mat m; 50133e922f36SToby Isaac PetscInt maxHeight; 5014552f7358SJed Brown 5015552f7358SJed Brown PetscFunctionBegin; 50165f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dm, cdm)); 50175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 50185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 50195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 50205f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLocalSection(*cdm, section)); 50215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(§ion)); 50225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF, &s)); 50235f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF, &m)); 50245f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDefaultConstraints(*cdm, s, m, NULL)); 50255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&s)); 50265f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&m)); 50278f4c458bSMatthew G. Knepley 50285f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetNumFields(*cdm, 1)); 50295f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(*cdm)); 5030552f7358SJed Brown PetscFunctionReturn(0); 5031552f7358SJed Brown } 5032552f7358SJed Brown 5033f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5034f19dbd58SToby Isaac { 5035f19dbd58SToby Isaac Vec coordsLocal; 5036f19dbd58SToby Isaac DM coordsDM; 5037f19dbd58SToby Isaac 5038f19dbd58SToby Isaac PetscFunctionBegin; 5039f19dbd58SToby Isaac *field = NULL; 50405f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm,&coordsLocal)); 50415f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm,&coordsDM)); 5042f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 50435f80ce2aSJacob Faibussowitsch CHKERRQ(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5044f19dbd58SToby Isaac } 5045f19dbd58SToby Isaac PetscFunctionReturn(0); 5046f19dbd58SToby Isaac } 5047f19dbd58SToby Isaac 50487cd05799SMatthew G. Knepley /*@C 50497cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 50507cd05799SMatthew G. Knepley 50517cd05799SMatthew G. Knepley Not Collective 50527cd05799SMatthew G. Knepley 50537cd05799SMatthew G. Knepley Input Parameters: 50547cd05799SMatthew G. Knepley . dm - The DMPlex object 50557cd05799SMatthew G. Knepley 50567cd05799SMatthew G. Knepley Output Parameter: 50577cd05799SMatthew G. Knepley . section - The PetscSection object 50587cd05799SMatthew G. Knepley 50597cd05799SMatthew G. Knepley Level: developer 50607cd05799SMatthew G. Knepley 50617cd05799SMatthew G. Knepley .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 50627cd05799SMatthew G. Knepley @*/ 50630adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 50640adebc6cSBarry Smith { 5065552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5066552f7358SJed Brown 5067552f7358SJed Brown PetscFunctionBegin; 5068552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5069552f7358SJed Brown if (section) *section = mesh->coneSection; 5070552f7358SJed Brown PetscFunctionReturn(0); 5071552f7358SJed Brown } 5072552f7358SJed Brown 50737cd05799SMatthew G. Knepley /*@C 50747cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 50757cd05799SMatthew G. Knepley 50767cd05799SMatthew G. Knepley Not Collective 50777cd05799SMatthew G. Knepley 50787cd05799SMatthew G. Knepley Input Parameters: 50797cd05799SMatthew G. Knepley . dm - The DMPlex object 50807cd05799SMatthew G. Knepley 50817cd05799SMatthew G. Knepley Output Parameter: 50827cd05799SMatthew G. Knepley . section - The PetscSection object 50837cd05799SMatthew G. Knepley 50847cd05799SMatthew G. Knepley Level: developer 50857cd05799SMatthew G. Knepley 50867cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection() 50877cd05799SMatthew G. Knepley @*/ 50888cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 50898cb4d582SMatthew G. Knepley { 50908cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 50918cb4d582SMatthew G. Knepley 50928cb4d582SMatthew G. Knepley PetscFunctionBegin; 50938cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50948cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 50958cb4d582SMatthew G. Knepley PetscFunctionReturn(0); 50968cb4d582SMatthew G. Knepley } 50978cb4d582SMatthew G. Knepley 50987cd05799SMatthew G. Knepley /*@C 50997cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 51007cd05799SMatthew G. Knepley 51017cd05799SMatthew G. Knepley Not Collective 51027cd05799SMatthew G. Knepley 51037cd05799SMatthew G. Knepley Input Parameters: 51047cd05799SMatthew G. Knepley . dm - The DMPlex object 51057cd05799SMatthew G. Knepley 51067cd05799SMatthew G. Knepley Output Parameter: 51077cd05799SMatthew G. Knepley . cones - The cone for each point 51087cd05799SMatthew G. Knepley 51097cd05799SMatthew G. Knepley Level: developer 51107cd05799SMatthew G. Knepley 51117cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection() 51127cd05799SMatthew G. Knepley @*/ 5113a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5114a6dfd86eSKarl Rupp { 5115552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5116552f7358SJed Brown 5117552f7358SJed Brown PetscFunctionBegin; 5118552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5119552f7358SJed Brown if (cones) *cones = mesh->cones; 5120552f7358SJed Brown PetscFunctionReturn(0); 5121552f7358SJed Brown } 5122552f7358SJed Brown 51237cd05799SMatthew G. Knepley /*@C 51247cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 51257cd05799SMatthew G. Knepley 51267cd05799SMatthew G. Knepley Not Collective 51277cd05799SMatthew G. Knepley 51287cd05799SMatthew G. Knepley Input Parameters: 51297cd05799SMatthew G. Knepley . dm - The DMPlex object 51307cd05799SMatthew G. Knepley 51317cd05799SMatthew G. Knepley Output Parameter: 5132b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 51337cd05799SMatthew G. Knepley 51347cd05799SMatthew G. Knepley Level: developer 51357cd05799SMatthew G. Knepley 5136b5a892a1SMatthew G. Knepley Notes: 5137b5a892a1SMatthew G. Knepley The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5138b5a892a1SMatthew G. Knepley 5139b5a892a1SMatthew G. Knepley The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5140b5a892a1SMatthew G. Knepley 5141b5a892a1SMatthew G. Knepley .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation() 51427cd05799SMatthew G. Knepley @*/ 5143a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5144a6dfd86eSKarl Rupp { 5145552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 5146552f7358SJed Brown 5147552f7358SJed Brown PetscFunctionBegin; 5148552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5149552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5150552f7358SJed Brown PetscFunctionReturn(0); 5151552f7358SJed Brown } 5152552f7358SJed Brown 5153552f7358SJed Brown /******************************** FEM Support **********************************/ 5154552f7358SJed Brown 51559e8305c2SJed Brown /* 51569e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 51579e8305c2SJed Brown representing a line in the section. 51589e8305c2SJed Brown */ 51599e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 51609e8305c2SJed Brown { 51619e8305c2SJed Brown PetscFunctionBeginHot; 51625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldComponents(section, field, Nc)); 5163a433471fSStefano Zampini if (line < 0) { 5164a433471fSStefano Zampini *k = 0; 5165a433471fSStefano Zampini *Nc = 0; 5166a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 51679e8305c2SJed Brown *k = 1; 51689e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 51699e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 51705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, line, field, k)); 51719e8305c2SJed Brown *k = *k / *Nc + 1; 51729e8305c2SJed Brown } 51739e8305c2SJed Brown PetscFunctionReturn(0); 51749e8305c2SJed Brown } 51759e8305c2SJed Brown 5176a4355906SMatthew Knepley /*@ 5177bc1eb3faSJed Brown 5178bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5179bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 51801bb6d2a8SBarry Smith section provided (or the section of the DM). 5181a4355906SMatthew Knepley 5182a4355906SMatthew Knepley Input Parameters: 5183a4355906SMatthew Knepley + dm - The DM 5184a4355906SMatthew Knepley . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5185a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section 5186a4355906SMatthew Knepley 5187a4355906SMatthew Knepley Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5188a4355906SMatthew Knepley degree of the basis. 5189a4355906SMatthew Knepley 5190bc1eb3faSJed Brown Example: 5191bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5192bc1eb3faSJed Brown .vb 5193bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5194bc1eb3faSJed Brown 5195bc1eb3faSJed Brown v4 -- e6 -- v3 5196bc1eb3faSJed Brown | | 5197bc1eb3faSJed Brown e7 c0 e8 5198bc1eb3faSJed Brown | | 5199bc1eb3faSJed Brown v1 -- e5 -- v2 5200bc1eb3faSJed Brown .ve 5201bc1eb3faSJed Brown 5202bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5203bc1eb3faSJed Brown dofs in the order of points, e.g., 5204bc1eb3faSJed Brown .vb 5205bc1eb3faSJed Brown c0 -> [0,1,2,3] 5206bc1eb3faSJed Brown v1 -> [4] 5207bc1eb3faSJed Brown ... 5208bc1eb3faSJed Brown e5 -> [8, 9] 5209bc1eb3faSJed Brown .ve 5210bc1eb3faSJed Brown 5211bc1eb3faSJed Brown which corresponds to the dofs 5212bc1eb3faSJed Brown .vb 5213bc1eb3faSJed Brown 6 10 11 7 5214bc1eb3faSJed Brown 13 2 3 15 5215bc1eb3faSJed Brown 12 0 1 14 5216bc1eb3faSJed Brown 4 8 9 5 5217bc1eb3faSJed Brown .ve 5218bc1eb3faSJed Brown 5219bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5220bc1eb3faSJed Brown .vb 5221bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5222bc1eb3faSJed Brown .ve 5223bc1eb3faSJed Brown 5224bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5225bc1eb3faSJed Brown .vb 5226bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5227bc1eb3faSJed Brown .ve 5228bc1eb3faSJed Brown 5229a4355906SMatthew Knepley Level: developer 5230a4355906SMatthew Knepley 52319df75925SJed Brown .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5232a4355906SMatthew Knepley @*/ 5233bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 52343194fc30SMatthew G. Knepley { 52357391a63aSMatthew G. Knepley DMLabel label; 5236bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 52379e8305c2SJed Brown PetscBool vertexchart; 52383194fc30SMatthew G. Knepley 52393194fc30SMatthew G. Knepley PetscFunctionBegin; 52405f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 5241a433471fSStefano Zampini if (dim < 1) PetscFunctionReturn(0); 5242a433471fSStefano Zampini if (point < 0) { 5243a433471fSStefano Zampini PetscInt sStart,sEnd; 5244a433471fSStefano Zampini 52455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5246a433471fSStefano Zampini point = sEnd-sStart ? sStart : point; 5247a433471fSStefano Zampini } 52485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm, &label)); 52495f80ce2aSJacob Faibussowitsch if (point >= 0) CHKERRQ(DMLabelGetValue(label, point, &depth)); 52505f80ce2aSJacob Faibussowitsch if (!section) CHKERRQ(DMGetLocalSection(dm, §ion)); 52517391a63aSMatthew G. Knepley if (depth == 1) {eStart = point;} 52527391a63aSMatthew G. Knepley else if (depth == dim) { 52537391a63aSMatthew G. Knepley const PetscInt *cone; 52547391a63aSMatthew G. Knepley 52555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, point, &cone)); 5256d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5257d4e6627bSStefano Zampini else if (dim == 3) { 5258d4e6627bSStefano Zampini const PetscInt *cone2; 52595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, cone[0], &cone2)); 5260d4e6627bSStefano Zampini eStart = cone2[0]; 526198921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim); 52622c71b3e2SJacob Faibussowitsch } else PetscCheckFalse(depth >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim); 52639e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 52649e8305c2SJed Brown PetscInt pStart,pEnd,cStart,cEnd; 52655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd)); 52665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section,&cStart,&cEnd)); 5267796d0a68SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5268796d0a68SJed Brown else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5269796d0a68SJed Brown else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 52709e8305c2SJed Brown } 52715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &Nf)); 5272bb197d40SJed Brown for (PetscInt d=1; d<=dim; d++) { 5273bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5274bb197d40SJed Brown PetscInt *perm; 5275bb197d40SJed Brown 52763194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 52775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5278bb197d40SJed Brown size += PetscPowInt(k+1, d)*Nc; 52793194fc30SMatthew G. Knepley } 52805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size, &perm)); 52813194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5282bb197d40SJed Brown switch (d) { 5283babf31e0SJed Brown case 1: 52845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 5285babf31e0SJed Brown /* 5286babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5287babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5288babf31e0SJed Brown */ 5289babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5290babf31e0SJed Brown for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5291babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5292babf31e0SJed Brown foffset = offset; 5293babf31e0SJed Brown break; 529489eabcffSMatthew G. Knepley case 2: 52953194fc30SMatthew 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} */ 52965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 52973194fc30SMatthew G. Knepley /* The SEM order is 52983194fc30SMatthew G. Knepley 52993194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 530089eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 53013194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 53023194fc30SMatthew G. Knepley */ 53033194fc30SMatthew G. Knepley { 53043194fc30SMatthew G. Knepley const PetscInt of = 0; 53053194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k-1); 53063194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k-1); 53073194fc30SMatthew G. Knepley const PetscInt oet = oer + (k-1); 53083194fc30SMatthew G. Knepley const PetscInt oel = oet + (k-1); 53093194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k-1); 53103194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 53113194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 53123194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 53133194fc30SMatthew G. Knepley PetscInt o; 53143194fc30SMatthew G. Knepley 53153194fc30SMatthew G. Knepley /* bottom */ 53163194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 53173194fc30SMatthew G. Knepley for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53183194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 53193194fc30SMatthew G. Knepley /* middle */ 53203194fc30SMatthew G. Knepley for (i = 0; i < k-1; ++i) { 53213194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 53223194fc30SMatthew 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; 53233194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 53243194fc30SMatthew G. Knepley } 53253194fc30SMatthew G. Knepley /* top */ 53263194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 53273194fc30SMatthew G. Knepley for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 53283194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 53293194fc30SMatthew G. Knepley foffset = offset; 53303194fc30SMatthew G. Knepley } 533189eabcffSMatthew G. Knepley break; 533289eabcffSMatthew G. Knepley case 3: 533389eabcffSMatthew G. Knepley /* The original hex closure is 533489eabcffSMatthew G. Knepley 533589eabcffSMatthew G. Knepley {c, 533689eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 533789eabcffSMatthew 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, 533889eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 533989eabcffSMatthew G. Knepley */ 53405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k)); 534189eabcffSMatthew G. Knepley /* The SEM order is 534289eabcffSMatthew G. Knepley Bottom Slice 534389eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 534489eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 534589eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 534689eabcffSMatthew G. Knepley 534789eabcffSMatthew G. Knepley Middle Slice (j) 534889eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 534989eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 535089eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 535189eabcffSMatthew G. Knepley 535289eabcffSMatthew G. Knepley Top Slice 535389eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 535489eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 535589eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 535689eabcffSMatthew G. Knepley */ 535789eabcffSMatthew G. Knepley { 535889eabcffSMatthew G. Knepley const PetscInt oc = 0; 535989eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 536089eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k-1); 536189eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k-1); 536289eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k-1); 536389eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k-1); 536489eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k-1); 536589eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k-1); 536689eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k-1); 536789eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k-1); 536889eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k-1); 536989eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k-1); 537089eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k-1); 537189eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k-1); 537289eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k-1); 537389eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k-1); 537489eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k-1); 537589eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k-1); 537689eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k-1); 537789eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k-1); 537889eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 537989eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 538089eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 538189eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 538289eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 538389eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 538489eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 538589eabcffSMatthew G. Knepley PetscInt o, n; 538689eabcffSMatthew G. Knepley 538789eabcffSMatthew G. Knepley /* Bottom Slice */ 538889eabcffSMatthew G. Knepley /* bottom */ 538989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 539089eabcffSMatthew G. Knepley for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 539189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 539289eabcffSMatthew G. Knepley /* middle */ 539389eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 539489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5395316b7f87SMax 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;} 539689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 53973194fc30SMatthew G. Knepley } 539889eabcffSMatthew G. Knepley /* top */ 539989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 540089eabcffSMatthew G. Knepley for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 540189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 540289eabcffSMatthew G. Knepley 540389eabcffSMatthew G. Knepley /* Middle Slice */ 540489eabcffSMatthew G. Knepley for (j = 0; j < k-1; ++j) { 540589eabcffSMatthew G. Knepley /* bottom */ 540689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 540789eabcffSMatthew 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; 540889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 540989eabcffSMatthew G. Knepley /* middle */ 541089eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 541189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 541289eabcffSMatthew 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; 541389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 541489eabcffSMatthew G. Knepley } 541589eabcffSMatthew G. Knepley /* top */ 541689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 541789eabcffSMatthew 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; 541889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 541989eabcffSMatthew G. Knepley } 542089eabcffSMatthew G. Knepley 542189eabcffSMatthew G. Knepley /* Top Slice */ 542289eabcffSMatthew G. Knepley /* bottom */ 542389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 542489eabcffSMatthew G. Knepley for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 542589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 542689eabcffSMatthew G. Knepley /* middle */ 542789eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 542889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 542989eabcffSMatthew 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; 543089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 543189eabcffSMatthew G. Knepley } 543289eabcffSMatthew G. Knepley /* top */ 543389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 543489eabcffSMatthew G. Knepley for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 543589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 543689eabcffSMatthew G. Knepley 543789eabcffSMatthew G. Knepley foffset = offset; 543889eabcffSMatthew G. Knepley } 543989eabcffSMatthew G. Knepley break; 544098921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 544189eabcffSMatthew G. Knepley } 544289eabcffSMatthew G. Knepley } 54432c71b3e2SJacob Faibussowitsch PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 54443194fc30SMatthew G. Knepley /* Check permutation */ 54453194fc30SMatthew G. Knepley { 54463194fc30SMatthew G. Knepley PetscInt *check; 54473194fc30SMatthew G. Knepley 54485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size, &check)); 54492c71b3e2SJacob Faibussowitsch for (i = 0; i < size; ++i) {check[i] = -1; PetscCheckFalse(perm[i] < 0 || perm[i] >= size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);} 54503194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 54512c71b3e2SJacob Faibussowitsch for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 54525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(check)); 54533194fc30SMatthew G. Knepley } 54545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm)); 5455a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5456a05c9aa3SJed Brown PetscInt *loc_perm; 54575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size*2, &loc_perm)); 5458a05c9aa3SJed Brown for (PetscInt i=0; i<size; i++) { 5459a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5460a05c9aa3SJed Brown loc_perm[size+i] = size + perm[i]; 5461a05c9aa3SJed Brown } 54625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm)); 5463a05c9aa3SJed Brown } 5464bb197d40SJed Brown } 54653194fc30SMatthew G. Knepley PetscFunctionReturn(0); 54663194fc30SMatthew G. Knepley } 54673194fc30SMatthew G. Knepley 5468e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5469e071409bSToby Isaac { 5470e071409bSToby Isaac PetscDS prob; 5471e071409bSToby Isaac PetscInt depth, Nf, h; 5472e071409bSToby Isaac DMLabel label; 5473e071409bSToby Isaac 5474e071409bSToby Isaac PetscFunctionBeginHot; 54755f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm, &prob)); 5476e071409bSToby Isaac Nf = prob->Nf; 5477e071409bSToby Isaac label = dm->depthLabel; 5478e071409bSToby Isaac *dspace = NULL; 5479e071409bSToby Isaac if (field < Nf) { 5480e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5481e071409bSToby Isaac 5482e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5483e071409bSToby Isaac PetscDualSpace dsp; 5484e071409bSToby Isaac 54855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetDualSpace((PetscFE)disc,&dsp)); 54865f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetNumValues(label,&depth)); 54875f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(label,point,&h)); 5488e071409bSToby Isaac h = depth - 1 - h; 5489e071409bSToby Isaac if (h) { 54905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetHeightSubspace(dsp,h,dspace)); 5491e071409bSToby Isaac } else { 5492e071409bSToby Isaac *dspace = dsp; 5493e071409bSToby Isaac } 5494e071409bSToby Isaac } 5495e071409bSToby Isaac } 5496e071409bSToby Isaac PetscFunctionReturn(0); 5497e071409bSToby Isaac } 5498e071409bSToby Isaac 54999fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5500a6dfd86eSKarl Rupp { 5501552f7358SJed Brown PetscScalar *array, *vArray; 5502d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 55031a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5504552f7358SJed Brown 55051b406b76SMatthew G. Knepley PetscFunctionBeginHot; 55065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd)); 55075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, point, &numPoints)); 55085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, point, &cone)); 55095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, point, &coneO)); 55103f7cbbe7SMatthew G. Knepley if (!values || !*values) { 55119df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55129df71ca4SMatthew G. Knepley PetscInt dof; 5513d9917b9dSMatthew G. Knepley 55145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 55159df71ca4SMatthew G. Knepley size += dof; 55169df71ca4SMatthew G. Knepley } 55179df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55189df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55192a3aaacfSMatthew G. Knepley PetscInt dof; 55205a1bb5cfSMatthew G. Knepley 55215a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, cp, &dof)); 55235a1bb5cfSMatthew G. Knepley size += dof; 55245a1bb5cfSMatthew G. Knepley } 55253f7cbbe7SMatthew G. Knepley if (!values) { 55263f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 55273f7cbbe7SMatthew G. Knepley PetscFunctionReturn(0); 55283f7cbbe7SMatthew G. Knepley } 55295f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 5530982e9ed1SMatthew G. Knepley } else { 5531982e9ed1SMatthew G. Knepley array = *values; 5532982e9ed1SMatthew G. Knepley } 55339df71ca4SMatthew G. Knepley size = 0; 55345f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &vArray)); 55359df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 55369df71ca4SMatthew G. Knepley PetscInt dof, off, d; 55379df71ca4SMatthew G. Knepley PetscScalar *varr; 5538d9917b9dSMatthew G. Knepley 55395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 55405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, point, &off)); 55419df71ca4SMatthew G. Knepley varr = &vArray[off]; 55421a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55431a271a75SMatthew G. Knepley array[offset] = varr[d]; 55449df71ca4SMatthew G. Knepley } 55459df71ca4SMatthew G. Knepley size += dof; 55469df71ca4SMatthew G. Knepley } 55479df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 55489df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 55499df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 55505a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 55515a1bb5cfSMatthew G. Knepley PetscScalar *varr; 55525a1bb5cfSMatthew G. Knepley 555352ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 55545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, cp, &dof)); 55555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, cp, &off)); 55565a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 55575a1bb5cfSMatthew G. Knepley if (o >= 0) { 55581a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 55591a271a75SMatthew G. Knepley array[offset] = varr[d]; 55605a1bb5cfSMatthew G. Knepley } 55615a1bb5cfSMatthew G. Knepley } else { 55621a271a75SMatthew G. Knepley for (d = dof-1; d >= 0; --d, ++offset) { 55631a271a75SMatthew G. Knepley array[offset] = varr[d]; 55645a1bb5cfSMatthew G. Knepley } 55655a1bb5cfSMatthew G. Knepley } 55669df71ca4SMatthew G. Knepley size += dof; 55675a1bb5cfSMatthew G. Knepley } 55685f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &vArray)); 55699df71ca4SMatthew G. Knepley if (!*values) { 55705a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 55715a1bb5cfSMatthew G. Knepley *values = array; 55729df71ca4SMatthew G. Knepley } else { 55732c71b3e2SJacob Faibussowitsch PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 55748c312ff3SMatthew G. Knepley *csize = size; 55759df71ca4SMatthew G. Knepley } 55765a1bb5cfSMatthew G. Knepley PetscFunctionReturn(0); 55775a1bb5cfSMatthew G. Knepley } 5578d9917b9dSMatthew G. Knepley 557927f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 55809fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 558127f02ce8SMatthew G. Knepley { 558227f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 558327f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 558427f02ce8SMatthew G. Knepley 55855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd)); 558627f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 558727f02ce8SMatthew G. Knepley const PetscInt r = points[p*2]; 558827f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 558927f02ce8SMatthew G. Knepley points[q*2] = r; 559027f02ce8SMatthew G. Knepley points[q*2+1] = points[p*2+1]; 559127f02ce8SMatthew G. Knepley ++q; 559227f02ce8SMatthew G. Knepley } 559327f02ce8SMatthew G. Knepley } 559427f02ce8SMatthew G. Knepley *numPoints = q; 559527f02ce8SMatthew G. Knepley return 0; 559627f02ce8SMatthew G. Knepley } 559727f02ce8SMatthew G. Knepley 559897529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 55991dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5600923c78e0SToby Isaac { 560127f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 5602923c78e0SToby Isaac PetscInt np, *pts = NULL; 5603923c78e0SToby Isaac 5604923c78e0SToby Isaac PetscFunctionBeginHot; 56055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints)); 560627f02ce8SMatthew G. Knepley if (*clPoints) { 5607923c78e0SToby Isaac PetscInt dof, off; 5608923c78e0SToby Isaac 56095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(*clSec, point, &dof)); 56105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(*clSec, point, &off)); 56115f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(*clPoints, &cla)); 5612923c78e0SToby Isaac np = dof/2; 5613923c78e0SToby Isaac pts = (PetscInt *) &cla[off]; 561427f02ce8SMatthew G. Knepley } else { 56155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts)); 56165f80ce2aSJacob Faibussowitsch CHKERRQ(CompressPoints_Private(section, &np, pts)); 5617923c78e0SToby Isaac } 5618923c78e0SToby Isaac *numPoints = np; 5619923c78e0SToby Isaac *points = pts; 5620923c78e0SToby Isaac *clp = cla; 5621923c78e0SToby Isaac PetscFunctionReturn(0); 5622923c78e0SToby Isaac } 5623923c78e0SToby Isaac 56241dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5625923c78e0SToby Isaac { 5626923c78e0SToby Isaac PetscFunctionBeginHot; 5627923c78e0SToby Isaac if (!*clPoints) { 56285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 5629923c78e0SToby Isaac } else { 56305f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(*clPoints, clp)); 5631923c78e0SToby Isaac } 5632923c78e0SToby Isaac *numPoints = 0; 5633923c78e0SToby Isaac *points = NULL; 5634923c78e0SToby Isaac *clSec = NULL; 5635923c78e0SToby Isaac *clPoints = NULL; 5636923c78e0SToby Isaac *clp = NULL; 5637923c78e0SToby Isaac PetscFunctionReturn(0); 5638923c78e0SToby Isaac } 5639923c78e0SToby Isaac 56409fbee547SJacob 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[]) 56411a271a75SMatthew G. Knepley { 56421a271a75SMatthew G. Knepley PetscInt offset = 0, p; 564397e99dd9SToby Isaac const PetscInt **perms = NULL; 564497e99dd9SToby Isaac const PetscScalar **flips = NULL; 56451a271a75SMatthew G. Knepley 56461a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5647fe02ba77SJed Brown *size = 0; 56485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 564997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 565097e99dd9SToby Isaac const PetscInt point = points[2*p]; 565197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 565297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 56531a271a75SMatthew G. Knepley PetscInt dof, off, d; 56541a271a75SMatthew G. Knepley const PetscScalar *varr; 56551a271a75SMatthew G. Knepley 56565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 56575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, point, &off)); 56581a271a75SMatthew G. Knepley varr = &vArray[off]; 565997e99dd9SToby Isaac if (clperm) { 566097e99dd9SToby Isaac if (perm) { 566197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 56621a271a75SMatthew G. Knepley } else { 566397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 566497e99dd9SToby Isaac } 566597e99dd9SToby Isaac if (flip) { 566697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 566797e99dd9SToby Isaac } 566897e99dd9SToby Isaac } else { 566997e99dd9SToby Isaac if (perm) { 567097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 567197e99dd9SToby Isaac } else { 567297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 567397e99dd9SToby Isaac } 567497e99dd9SToby Isaac if (flip) { 567597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 56761a271a75SMatthew G. Knepley } 56771a271a75SMatthew G. Knepley } 567897e99dd9SToby Isaac offset += dof; 567997e99dd9SToby Isaac } 56805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 56811a271a75SMatthew G. Knepley *size = offset; 56821a271a75SMatthew G. Knepley PetscFunctionReturn(0); 56831a271a75SMatthew G. Knepley } 56841a271a75SMatthew G. Knepley 56859fbee547SJacob 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[]) 56861a271a75SMatthew G. Knepley { 56871a271a75SMatthew G. Knepley PetscInt offset = 0, f; 56881a271a75SMatthew G. Knepley 56891a271a75SMatthew G. Knepley PetscFunctionBeginHot; 5690fe02ba77SJed Brown *size = 0; 56911a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 569297e99dd9SToby Isaac PetscInt p; 569397e99dd9SToby Isaac const PetscInt **perms = NULL; 569497e99dd9SToby Isaac const PetscScalar **flips = NULL; 56951a271a75SMatthew G. Knepley 56965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 569797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 569897e99dd9SToby Isaac const PetscInt point = points[2*p]; 569997e99dd9SToby Isaac PetscInt fdof, foff, b; 57001a271a75SMatthew G. Knepley const PetscScalar *varr; 570197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 570297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 57031a271a75SMatthew G. Knepley 57045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof)); 57055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(section, point, f, &foff)); 57061a271a75SMatthew G. Knepley varr = &vArray[foff]; 570797e99dd9SToby Isaac if (clperm) { 570897e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 570997e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 571097e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 57111a271a75SMatthew G. Knepley } else { 571297e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 571397e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 571497e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 57151a271a75SMatthew G. Knepley } 571697e99dd9SToby Isaac offset += fdof; 57171a271a75SMatthew G. Knepley } 57185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 57191a271a75SMatthew G. Knepley } 57201a271a75SMatthew G. Knepley *size = offset; 57211a271a75SMatthew G. Knepley PetscFunctionReturn(0); 57221a271a75SMatthew G. Knepley } 57231a271a75SMatthew G. Knepley 5724552f7358SJed Brown /*@C 5725552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5726552f7358SJed Brown 5727552f7358SJed Brown Not collective 5728552f7358SJed Brown 5729552f7358SJed Brown Input Parameters: 5730552f7358SJed Brown + dm - The DM 5731552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section 5732552f7358SJed Brown . v - The local vector 57336b867d5aSJose E. Roman - point - The point in the DM 5734552f7358SJed Brown 57356b867d5aSJose E. Roman Input/Output Parameters: 57366b867d5aSJose E. Roman + csize - The size of the input values array, or NULL; on output the number of values in the closure 57376b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically; 57386b867d5aSJose E. Roman if the user provided NULL, it is a borrowed array and should not be freed 573922c1ee49SMatthew G. Knepley 574022c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 574122c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 574222c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation. 574322c1ee49SMatthew G. Knepley $ 574422c1ee49SMatthew G. Knepley $ A typical use could be 574522c1ee49SMatthew G. Knepley $ 574622c1ee49SMatthew G. Knepley $ values = NULL; 57475f80ce2aSJacob Faibussowitsch $ CHKERRQ(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 574822c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 574922c1ee49SMatthew G. Knepley $ <Compute on closure> 575022c1ee49SMatthew G. Knepley $ } 57515f80ce2aSJacob Faibussowitsch $ CHKERRQ(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 575222c1ee49SMatthew G. Knepley $ 575322c1ee49SMatthew G. Knepley $ or 575422c1ee49SMatthew G. Knepley $ 575522c1ee49SMatthew G. Knepley $ PetscMalloc1(clMaxSize, &values); 575622c1ee49SMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) { 575722c1ee49SMatthew G. Knepley $ clSize = clMaxSize; 57585f80ce2aSJacob Faibussowitsch $ CHKERRQ(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 575922c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 576022c1ee49SMatthew G. Knepley $ <Compute on closure> 576122c1ee49SMatthew G. Knepley $ } 576222c1ee49SMatthew G. Knepley $ } 576322c1ee49SMatthew G. Knepley $ PetscFree(values); 5764552f7358SJed Brown 5765552f7358SJed Brown Fortran Notes: 5766552f7358SJed Brown Since it returns an array, this routine is only available in Fortran 90, and you must 5767552f7358SJed Brown include petsc.h90 in your code. 5768552f7358SJed Brown 5769552f7358SJed Brown The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5770552f7358SJed Brown 5771552f7358SJed Brown Level: intermediate 5772552f7358SJed Brown 5773552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5774552f7358SJed Brown @*/ 5775552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5776552f7358SJed Brown { 5777552f7358SJed Brown PetscSection clSection; 5778d9917b9dSMatthew G. Knepley IS clPoints; 5779552f7358SJed Brown PetscInt *points = NULL; 5780c459fbc1SJed Brown const PetscInt *clp, *perm; 5781c459fbc1SJed Brown PetscInt depth, numFields, numPoints, asize; 5782552f7358SJed Brown 5783d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 5784552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 57855f80ce2aSJacob Faibussowitsch if (!section) CHKERRQ(DMGetLocalSection(dm, §ion)); 57861a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 57871a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 57885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 57895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &numFields)); 5790552f7358SJed Brown if (depth == 1 && numFields < 2) { 57915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5792552f7358SJed Brown PetscFunctionReturn(0); 5793552f7358SJed Brown } 57941a271a75SMatthew G. Knepley /* Get points */ 57955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5796c459fbc1SJed Brown /* Get sizes */ 5797c459fbc1SJed Brown asize = 0; 5798c459fbc1SJed Brown for (PetscInt p = 0; p < numPoints*2; p += 2) { 5799c459fbc1SJed Brown PetscInt dof; 58005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, points[p], &dof)); 58011a271a75SMatthew G. Knepley asize += dof; 5802552f7358SJed Brown } 5803c459fbc1SJed Brown if (values) { 5804c459fbc1SJed Brown const PetscScalar *vArray; 5805c459fbc1SJed Brown PetscInt size; 5806c459fbc1SJed Brown 5807c459fbc1SJed Brown if (*values) { 58082c71b3e2SJacob Faibussowitsch PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize); 58095f80ce2aSJacob Faibussowitsch } else CHKERRQ(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 58105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm)); 58115f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(v, &vArray)); 58121a271a75SMatthew G. Knepley /* Get values */ 58135f80ce2aSJacob Faibussowitsch if (numFields > 0) CHKERRQ(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 58145f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 58152c71b3e2SJacob Faibussowitsch PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 58161a271a75SMatthew G. Knepley /* Cleanup array */ 58175f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(v, &vArray)); 5818d0f6b257SMatthew G. Knepley } 5819c459fbc1SJed Brown if (csize) *csize = asize; 5820c459fbc1SJed Brown /* Cleanup points */ 58215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5822552f7358SJed Brown PetscFunctionReturn(0); 5823552f7358SJed Brown } 5824552f7358SJed Brown 5825e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5826e5c487bfSMatthew G. Knepley { 5827e5c487bfSMatthew G. Knepley DMLabel depthLabel; 5828e5c487bfSMatthew G. Knepley PetscSection clSection; 5829e5c487bfSMatthew G. Knepley IS clPoints; 5830e5c487bfSMatthew G. Knepley PetscScalar *array; 5831e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 5832e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 5833c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 5834c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5835e5c487bfSMatthew G. Knepley 5836e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 5837e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58385f80ce2aSJacob Faibussowitsch if (!section) CHKERRQ(DMGetLocalSection(dm, §ion)); 5839e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5840e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 58415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &mdepth)); 58425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm, &depthLabel)); 58435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &numFields)); 5844e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 58455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 5846e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5847e5c487bfSMatthew G. Knepley } 5848e5c487bfSMatthew G. Knepley /* Get points */ 58495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5850c459fbc1SJed Brown for (clsize=0,p=0; p<Np; p++) { 5851c459fbc1SJed Brown PetscInt dof; 58525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, points[2*p], &dof)); 5853c459fbc1SJed Brown clsize += dof; 5854c459fbc1SJed Brown } 58555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm)); 5856e5c487bfSMatthew G. Knepley /* Filter points */ 5857e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 5858e5c487bfSMatthew G. Knepley PetscInt dep; 5859e5c487bfSMatthew G. Knepley 58605f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(depthLabel, points[p], &dep)); 5861e5c487bfSMatthew G. Knepley if (dep != depth) continue; 5862e5c487bfSMatthew G. Knepley points[Np*2+0] = points[p]; 5863e5c487bfSMatthew G. Knepley points[Np*2+1] = points[p+1]; 5864e5c487bfSMatthew G. Knepley ++Np; 5865e5c487bfSMatthew G. Knepley } 5866e5c487bfSMatthew G. Knepley /* Get array */ 5867e5c487bfSMatthew G. Knepley if (!values || !*values) { 5868e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 5869e5c487bfSMatthew G. Knepley 5870e5c487bfSMatthew G. Knepley for (p = 0; p < Np*2; p += 2) { 58715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, points[p], &dof)); 5872e5c487bfSMatthew G. Knepley asize += dof; 5873e5c487bfSMatthew G. Knepley } 5874e5c487bfSMatthew G. Knepley if (!values) { 58755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5876e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 5877e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5878e5c487bfSMatthew G. Knepley } 58795f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 5880e5c487bfSMatthew G. Knepley } else { 5881e5c487bfSMatthew G. Knepley array = *values; 5882e5c487bfSMatthew G. Knepley } 58835f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(v, &vArray)); 5884e5c487bfSMatthew G. Knepley /* Get values */ 58855f80ce2aSJacob Faibussowitsch if (numFields > 0) CHKERRQ(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 58865f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 5887e5c487bfSMatthew G. Knepley /* Cleanup points */ 58885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 5889e5c487bfSMatthew G. Knepley /* Cleanup array */ 58905f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(v, &vArray)); 5891e5c487bfSMatthew G. Knepley if (!*values) { 5892e5c487bfSMatthew G. Knepley if (csize) *csize = size; 5893e5c487bfSMatthew G. Knepley *values = array; 5894e5c487bfSMatthew G. Knepley } else { 58952c71b3e2SJacob Faibussowitsch PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5896e5c487bfSMatthew G. Knepley *csize = size; 5897e5c487bfSMatthew G. Knepley } 5898e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 5899e5c487bfSMatthew G. Knepley } 5900e5c487bfSMatthew G. Knepley 5901552f7358SJed Brown /*@C 5902552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5903552f7358SJed Brown 5904552f7358SJed Brown Not collective 5905552f7358SJed Brown 5906552f7358SJed Brown Input Parameters: 5907552f7358SJed Brown + dm - The DM 59080298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section 5909552f7358SJed Brown . v - The local vector 5910eaf898f9SPatrick Sanan . point - The point in the DM 59110298fd71SBarry Smith . csize - The number of values in the closure, or NULL 5912552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 5913552f7358SJed Brown 591422c1ee49SMatthew 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() 591522c1ee49SMatthew G. Knepley 59163813dfbdSMatthew G Knepley Fortran Notes: 59173813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 59183813dfbdSMatthew G Knepley include petsc.h90 in your code. 59193813dfbdSMatthew G Knepley 59203813dfbdSMatthew G Knepley The csize argument is not present in the Fortran 90 binding since it is internal to the array. 59213813dfbdSMatthew G Knepley 5922552f7358SJed Brown Level: intermediate 5923552f7358SJed Brown 5924552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5925552f7358SJed Brown @*/ 59267c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5927a6dfd86eSKarl Rupp { 5928552f7358SJed Brown PetscInt size = 0; 5929552f7358SJed Brown 5930552f7358SJed Brown PetscFunctionBegin; 5931552f7358SJed Brown /* Should work without recalculating size */ 59325f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values)); 5933c9fdaa05SMatthew G. Knepley *values = NULL; 5934552f7358SJed Brown PetscFunctionReturn(0); 5935552f7358SJed Brown } 5936552f7358SJed Brown 59379fbee547SJacob Faibussowitsch static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 59389fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5939552f7358SJed Brown 59409fbee547SJacob 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[]) 5941552f7358SJed Brown { 5942552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 5943552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5944552f7358SJed Brown PetscScalar *a; 5945552f7358SJed Brown PetscInt off, cind = 0, k; 5946552f7358SJed Brown 5947552f7358SJed Brown PetscFunctionBegin; 59485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(section, point, &cdof)); 59495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, point, &off)); 5950552f7358SJed Brown a = &array[off]; 5951552f7358SJed Brown if (!cdof || setBC) { 595297e99dd9SToby Isaac if (clperm) { 595397e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 595497e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5955552f7358SJed Brown } else { 595697e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 595797e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5958552f7358SJed Brown } 5959552f7358SJed Brown } else { 59605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintIndices(section, point, &cdofs)); 596197e99dd9SToby Isaac if (clperm) { 596297e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) { 5963552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 596497e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5965552f7358SJed Brown } 5966552f7358SJed Brown } else { 5967552f7358SJed Brown for (k = 0; k < dof; ++k) { 5968552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 596997e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 597097e99dd9SToby Isaac } 597197e99dd9SToby Isaac } 597297e99dd9SToby Isaac } else { 597397e99dd9SToby Isaac if (perm) { 597497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 597597e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 597697e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 597797e99dd9SToby Isaac } 597897e99dd9SToby Isaac } else { 597997e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 598097e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 598197e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 598297e99dd9SToby Isaac } 5983552f7358SJed Brown } 5984552f7358SJed Brown } 5985552f7358SJed Brown } 5986552f7358SJed Brown PetscFunctionReturn(0); 5987552f7358SJed Brown } 5988552f7358SJed Brown 59899fbee547SJacob 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[]) 5990a5e93ea8SMatthew G. Knepley { 5991a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 5992a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5993a5e93ea8SMatthew G. Knepley PetscScalar *a; 5994a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 5995a5e93ea8SMatthew G. Knepley 5996a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 59975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(section, point, &cdof)); 59985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, point, &off)); 5999a5e93ea8SMatthew G. Knepley a = &array[off]; 6000a5e93ea8SMatthew G. Knepley if (cdof) { 60015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintIndices(section, point, &cdofs)); 600297e99dd9SToby Isaac if (clperm) { 600397e99dd9SToby Isaac if (perm) { 6004a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6005a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 600697e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 600797e99dd9SToby Isaac cind++; 6008a5e93ea8SMatthew G. Knepley } 6009a5e93ea8SMatthew G. Knepley } 6010a5e93ea8SMatthew G. Knepley } else { 6011a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6012a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 601397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 601497e99dd9SToby Isaac cind++; 601597e99dd9SToby Isaac } 601697e99dd9SToby Isaac } 601797e99dd9SToby Isaac } 601897e99dd9SToby Isaac } else { 601997e99dd9SToby Isaac if (perm) { 602097e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 602197e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 602297e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 602397e99dd9SToby Isaac cind++; 602497e99dd9SToby Isaac } 602597e99dd9SToby Isaac } 602697e99dd9SToby Isaac } else { 602797e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 602897e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 602997e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 603097e99dd9SToby Isaac cind++; 603197e99dd9SToby Isaac } 6032a5e93ea8SMatthew G. Knepley } 6033a5e93ea8SMatthew G. Knepley } 6034a5e93ea8SMatthew G. Knepley } 6035a5e93ea8SMatthew G. Knepley } 6036a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6037a5e93ea8SMatthew G. Knepley } 6038a5e93ea8SMatthew G. Knepley 60399fbee547SJacob 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[]) 6040a6dfd86eSKarl Rupp { 6041552f7358SJed Brown PetscScalar *a; 60421a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60431a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 604497e99dd9SToby Isaac PetscInt cind = 0, b; 6045552f7358SJed Brown 6046552f7358SJed Brown PetscFunctionBegin; 60475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof)); 60485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 60495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(section, point, f, &foff)); 60501a271a75SMatthew G. Knepley a = &array[foff]; 6051552f7358SJed Brown if (!fcdof || setBC) { 605297e99dd9SToby Isaac if (clperm) { 605397e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 605497e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6055552f7358SJed Brown } else { 605697e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 605797e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6058552f7358SJed Brown } 6059552f7358SJed Brown } else { 60605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 606197e99dd9SToby Isaac if (clperm) { 606297e99dd9SToby Isaac if (perm) { 606397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 606497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 606597e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6066552f7358SJed Brown } 6067552f7358SJed Brown } else { 606897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 606997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 607097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 607197e99dd9SToby Isaac } 607297e99dd9SToby Isaac } 607397e99dd9SToby Isaac } else { 607497e99dd9SToby Isaac if (perm) { 607597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 607697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 607797e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 607897e99dd9SToby Isaac } 607997e99dd9SToby Isaac } else { 608097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 608197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 608297e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6083552f7358SJed Brown } 6084552f7358SJed Brown } 6085552f7358SJed Brown } 6086552f7358SJed Brown } 60871a271a75SMatthew G. Knepley *offset += fdof; 6088552f7358SJed Brown PetscFunctionReturn(0); 6089552f7358SJed Brown } 6090552f7358SJed Brown 60919fbee547SJacob 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[]) 6092a5e93ea8SMatthew G. Knepley { 6093a5e93ea8SMatthew G. Knepley PetscScalar *a; 60941a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 60951a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 60965da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6097ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6098a5e93ea8SMatthew G. Knepley 6099a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 61005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldComponents(section, f, &Nc)); 61015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof)); 61025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 61035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(section, point, f, &foff)); 61041a271a75SMatthew G. Knepley a = &array[foff]; 6105a5e93ea8SMatthew G. Knepley if (fcdof) { 6106ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 61075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 610897e99dd9SToby Isaac if (clperm) { 610997e99dd9SToby Isaac if (perm) { 6110ba322698SMatthew G. Knepley if (comps) { 6111ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6112ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61135da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6114ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6115ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6116ba322698SMatthew G. Knepley } 6117ba322698SMatthew G. Knepley } else { 611897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 611997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 612097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6121a5e93ea8SMatthew G. Knepley ++cind; 6122a5e93ea8SMatthew G. Knepley } 6123a5e93ea8SMatthew G. Knepley } 6124ba322698SMatthew G. Knepley } 6125ba322698SMatthew G. Knepley } else { 6126ba322698SMatthew G. Knepley if (comps) { 6127ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6128ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61295da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6130ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6131ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6132ba322698SMatthew G. Knepley } 6133a5e93ea8SMatthew G. Knepley } else { 613497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 613597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 613697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 613797e99dd9SToby Isaac ++cind; 613897e99dd9SToby Isaac } 613997e99dd9SToby Isaac } 614097e99dd9SToby Isaac } 6141ba322698SMatthew G. Knepley } 614297e99dd9SToby Isaac } else { 614397e99dd9SToby Isaac if (perm) { 6144ba322698SMatthew G. Knepley if (comps) { 6145ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6146ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61475da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6148ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6149ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6150ba322698SMatthew G. Knepley } 6151ba322698SMatthew G. Knepley } else { 615297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 615397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 615497e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 615597e99dd9SToby Isaac ++cind; 615697e99dd9SToby Isaac } 615797e99dd9SToby Isaac } 6158ba322698SMatthew G. Knepley } 6159ba322698SMatthew G. Knepley } else { 6160ba322698SMatthew G. Knepley if (comps) { 6161ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6162ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 61635da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6164ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6165ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6166ba322698SMatthew G. Knepley } 616797e99dd9SToby Isaac } else { 616897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 616997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 617097e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6171a5e93ea8SMatthew G. Knepley ++cind; 6172a5e93ea8SMatthew G. Knepley } 6173a5e93ea8SMatthew G. Knepley } 6174a5e93ea8SMatthew G. Knepley } 6175a5e93ea8SMatthew G. Knepley } 6176a5e93ea8SMatthew G. Knepley } 6177ba322698SMatthew G. Knepley } 61781a271a75SMatthew G. Knepley *offset += fdof; 6179a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 6180a5e93ea8SMatthew G. Knepley } 6181a5e93ea8SMatthew G. Knepley 61829fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6183a6dfd86eSKarl Rupp { 6184552f7358SJed Brown PetscScalar *array; 61851b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 61861b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6187552f7358SJed Brown 61881b406b76SMatthew G. Knepley PetscFunctionBeginHot; 61895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd)); 61905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, point, &numPoints)); 61915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, point, &cone)); 61925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, point, &coneO)); 61935f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &array)); 6194b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6195b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p-1]; 6196b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p-1]; 6197b6ebb6e6SMatthew G. Knepley 6198b6ebb6e6SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 61995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, cp, &dof)); 6200b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6201b6ebb6e6SMatthew G. Knepley { 6202b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6203b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6204b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6205b6ebb6e6SMatthew G. Knepley 62065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(section, cp, &cdof)); 62075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, cp, &coff)); 6208b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6209b6ebb6e6SMatthew G. Knepley if (!cdof) { 6210b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6211b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6212b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6213b6ebb6e6SMatthew G. Knepley } 6214b6ebb6e6SMatthew G. Knepley } else { 6215b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6216b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6217b6ebb6e6SMatthew G. Knepley } 6218b6ebb6e6SMatthew G. Knepley } 6219b6ebb6e6SMatthew G. Knepley } else { 62205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6221b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6222b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6223b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6224b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 6225b6ebb6e6SMatthew G. Knepley } 6226b6ebb6e6SMatthew G. Knepley } else { 6227b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6228b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6229b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 6230b6ebb6e6SMatthew G. Knepley } 6231b6ebb6e6SMatthew G. Knepley } 6232b6ebb6e6SMatthew G. Knepley } 6233b6ebb6e6SMatthew G. Knepley } 6234b6ebb6e6SMatthew G. Knepley } 62355f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &array)); 6236b6ebb6e6SMatthew G. Knepley PetscFunctionReturn(0); 6237b6ebb6e6SMatthew G. Knepley } 62381b406b76SMatthew G. Knepley 62391b406b76SMatthew G. Knepley /*@C 62401b406b76SMatthew G. Knepley DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 62411b406b76SMatthew G. Knepley 62421b406b76SMatthew G. Knepley Not collective 62431b406b76SMatthew G. Knepley 62441b406b76SMatthew G. Knepley Input Parameters: 62451b406b76SMatthew G. Knepley + dm - The DM 62461b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 62471b406b76SMatthew G. Knepley . v - The local vector 6248eaf898f9SPatrick Sanan . point - The point in the DM 62491b406b76SMatthew G. Knepley . values - The array of values 625022c1ee49SMatthew 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, 625122c1ee49SMatthew G. Knepley where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 62521b406b76SMatthew G. Knepley 62531b406b76SMatthew G. Knepley Fortran Notes: 62541b406b76SMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 62551b406b76SMatthew G. Knepley 62561b406b76SMatthew G. Knepley Level: intermediate 62571b406b76SMatthew G. Knepley 62581b406b76SMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 62591b406b76SMatthew G. Knepley @*/ 62601b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 62611b406b76SMatthew G. Knepley { 62621b406b76SMatthew G. Knepley PetscSection clSection; 62631b406b76SMatthew G. Knepley IS clPoints; 62641b406b76SMatthew G. Knepley PetscScalar *array; 62651b406b76SMatthew G. Knepley PetscInt *points = NULL; 626627f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6267c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 62681b406b76SMatthew G. Knepley 62691a271a75SMatthew G. Knepley PetscFunctionBeginHot; 62701b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62715f80ce2aSJacob Faibussowitsch if (!section) CHKERRQ(DMGetLocalSection(dm, §ion)); 62721a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 62731a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 62745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 62755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &numFields)); 62761b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 62775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 62781b406b76SMatthew G. Knepley PetscFunctionReturn(0); 62791b406b76SMatthew G. Knepley } 62801a271a75SMatthew G. Knepley /* Get points */ 62815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6282c459fbc1SJed Brown for (clsize=0,p=0; p<numPoints; p++) { 6283c459fbc1SJed Brown PetscInt dof; 62845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, points[2*p], &dof)); 6285c459fbc1SJed Brown clsize += dof; 6286c459fbc1SJed Brown } 62875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 62881a271a75SMatthew G. Knepley /* Get array */ 62895f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &array)); 62901a271a75SMatthew G. Knepley /* Get values */ 6291ef90cfe2SMatthew G. Knepley if (numFields > 0) { 629297e99dd9SToby Isaac PetscInt offset = 0, f; 6293552f7358SJed Brown for (f = 0; f < numFields; ++f) { 629497e99dd9SToby Isaac const PetscInt **perms = NULL; 629597e99dd9SToby Isaac const PetscScalar **flips = NULL; 629697e99dd9SToby Isaac 62975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6298552f7358SJed Brown switch (mode) { 6299552f7358SJed Brown case INSERT_VALUES: 630097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 630197e99dd9SToby Isaac const PetscInt point = points[2*p]; 630297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 630397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 630497e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6305552f7358SJed Brown } break; 6306552f7358SJed Brown case INSERT_ALL_VALUES: 630797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 630897e99dd9SToby Isaac const PetscInt point = points[2*p]; 630997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 631097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 631197e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6312552f7358SJed Brown } break; 6313a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 631497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 631597e99dd9SToby Isaac const PetscInt point = points[2*p]; 631697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 631797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6318ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6319a5e93ea8SMatthew G. Knepley } break; 6320552f7358SJed Brown case ADD_VALUES: 632197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632297e99dd9SToby Isaac const PetscInt point = points[2*p]; 632397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 632597e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6326552f7358SJed Brown } break; 6327552f7358SJed Brown case ADD_ALL_VALUES: 632897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632997e99dd9SToby Isaac const PetscInt point = points[2*p]; 633097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 633197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 633297e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6333552f7358SJed Brown } break; 6334304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 633597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 633697e99dd9SToby Isaac const PetscInt point = points[2*p]; 633797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 633897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 6339ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6340304ab55fSMatthew G. Knepley } break; 6341552f7358SJed Brown default: 634298921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6343552f7358SJed Brown } 63445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 63451a271a75SMatthew G. Knepley } 6346552f7358SJed Brown } else { 63471a271a75SMatthew G. Knepley PetscInt dof, off; 634897e99dd9SToby Isaac const PetscInt **perms = NULL; 634997e99dd9SToby Isaac const PetscScalar **flips = NULL; 63501a271a75SMatthew G. Knepley 63515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips)); 6352552f7358SJed Brown switch (mode) { 6353552f7358SJed Brown case INSERT_VALUES: 635497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 635597e99dd9SToby Isaac const PetscInt point = points[2*p]; 635697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 635797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 635997e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6360552f7358SJed Brown } break; 6361552f7358SJed Brown case INSERT_ALL_VALUES: 636297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 636397e99dd9SToby Isaac const PetscInt point = points[2*p]; 636497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 636597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 636797e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6368552f7358SJed Brown } break; 6369a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 637097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 637197e99dd9SToby Isaac const PetscInt point = points[2*p]; 637297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 637397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 637597e99dd9SToby Isaac updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6376a5e93ea8SMatthew G. Knepley } break; 6377552f7358SJed Brown case ADD_VALUES: 637897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 637997e99dd9SToby Isaac const PetscInt point = points[2*p]; 638097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 638197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 638397e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6384552f7358SJed Brown } break; 6385552f7358SJed Brown case ADD_ALL_VALUES: 638697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 638797e99dd9SToby Isaac const PetscInt point = points[2*p]; 638897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 638997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 639197e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6392552f7358SJed Brown } break; 6393304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 639497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 639597e99dd9SToby Isaac const PetscInt point = points[2*p]; 639697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 639797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 639997e99dd9SToby Isaac updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6400304ab55fSMatthew G. Knepley } break; 6401552f7358SJed Brown default: 640298921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6403552f7358SJed Brown } 64045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips)); 6405552f7358SJed Brown } 64061a271a75SMatthew G. Knepley /* Cleanup points */ 64075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 64081a271a75SMatthew G. Knepley /* Cleanup array */ 64095f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &array)); 6410552f7358SJed Brown PetscFunctionReturn(0); 6411552f7358SJed Brown } 6412552f7358SJed Brown 64135f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 64149fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 64155f790a90SMatthew G. Knepley { 64165f790a90SMatthew G. Knepley PetscFunctionBegin; 64175f790a90SMatthew G. Knepley if (label) { 64185f790a90SMatthew G. Knepley PetscInt val, fdof; 64195f790a90SMatthew G. Knepley 64205f790a90SMatthew G. Knepley /* There is a problem with this: 64215f790a90SMatthew 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 64225f790a90SMatthew 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. 64235f790a90SMatthew G. Knepley Thus I am only going to check val != -1, not val != labelId 64245f790a90SMatthew G. Knepley */ 64255f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(label, point, &val)); 64265f790a90SMatthew G. Knepley if (val < 0) { 64275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof)); 64285f790a90SMatthew G. Knepley *offset += fdof; 64295f790a90SMatthew G. Knepley PetscFunctionReturn(1); 64305f790a90SMatthew G. Knepley } 64315f790a90SMatthew G. Knepley } 64325f790a90SMatthew G. Knepley PetscFunctionReturn(0); 64335f790a90SMatthew G. Knepley } 64345f790a90SMatthew G. Knepley 643597529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 64365f790a90SMatthew 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) 6437e07394fbSMatthew G. Knepley { 6438e07394fbSMatthew G. Knepley PetscSection clSection; 6439e07394fbSMatthew G. Knepley IS clPoints; 6440e07394fbSMatthew G. Knepley PetscScalar *array; 6441e07394fbSMatthew G. Knepley PetscInt *points = NULL; 644297529cf3SJed Brown const PetscInt *clp; 6443e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 644497e99dd9SToby Isaac PetscInt offset = 0, f; 6445e07394fbSMatthew G. Knepley 6446e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 6447e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64485f80ce2aSJacob Faibussowitsch if (!section) CHKERRQ(DMGetLocalSection(dm, §ion)); 6449e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6450e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &numFields)); 6452e07394fbSMatthew G. Knepley /* Get points */ 64535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6454e07394fbSMatthew G. Knepley /* Get array */ 64555f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &array)); 6456e07394fbSMatthew G. Knepley /* Get values */ 6457e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 645897e99dd9SToby Isaac const PetscInt **perms = NULL; 645997e99dd9SToby Isaac const PetscScalar **flips = NULL; 646097e99dd9SToby Isaac 6461e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 6462e07394fbSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 6463e07394fbSMatthew G. Knepley PetscInt fdof; 64645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 6465e07394fbSMatthew G. Knepley offset += fdof; 6466e07394fbSMatthew G. Knepley } 6467e07394fbSMatthew G. Knepley continue; 6468e07394fbSMatthew G. Knepley } 64695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6470e07394fbSMatthew G. Knepley switch (mode) { 6471e07394fbSMatthew G. Knepley case INSERT_VALUES: 647297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 647397e99dd9SToby Isaac const PetscInt point = points[2*p]; 647497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 647597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64765f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64775f80ce2aSJacob Faibussowitsch CHKERRQ(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 6478e07394fbSMatthew G. Knepley } break; 6479e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 648097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 648197e99dd9SToby Isaac const PetscInt point = points[2*p]; 648297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 648397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64845f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64855f80ce2aSJacob Faibussowitsch CHKERRQ(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 6486e07394fbSMatthew G. Knepley } break; 6487e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 648897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 648997e99dd9SToby Isaac const PetscInt point = points[2*p]; 649097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64925f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 64935f80ce2aSJacob Faibussowitsch CHKERRQ(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 6494e07394fbSMatthew G. Knepley } break; 6495e07394fbSMatthew G. Knepley case ADD_VALUES: 649697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649797e99dd9SToby Isaac const PetscInt point = points[2*p]; 649897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65005f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65015f80ce2aSJacob Faibussowitsch CHKERRQ(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 6502e07394fbSMatthew G. Knepley } break; 6503e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 650497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 650597e99dd9SToby Isaac const PetscInt point = points[2*p]; 650697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 650797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65085f80ce2aSJacob Faibussowitsch if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue; 65095f80ce2aSJacob Faibussowitsch CHKERRQ(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 6510e07394fbSMatthew G. Knepley } break; 6511e07394fbSMatthew G. Knepley default: 651298921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6513e07394fbSMatthew G. Knepley } 65145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips)); 6515e07394fbSMatthew G. Knepley } 6516e07394fbSMatthew G. Knepley /* Cleanup points */ 65175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp)); 6518e07394fbSMatthew G. Knepley /* Cleanup array */ 65195f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &array)); 6520e07394fbSMatthew G. Knepley PetscFunctionReturn(0); 6521e07394fbSMatthew G. Knepley } 6522e07394fbSMatthew G. Knepley 65237cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6524552f7358SJed Brown { 6525552f7358SJed Brown PetscMPIInt rank; 6526552f7358SJed Brown PetscInt i, j; 6527552f7358SJed Brown 6528552f7358SJed Brown PetscFunctionBegin; 65295f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 65305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point)); 65315f80ce2aSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) CHKERRQ(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i])); 65325f80ce2aSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) CHKERRQ(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i])); 6533b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 6534557cf195SMatthew G. Knepley if (!values) PetscFunctionReturn(0); 6535b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 65365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 6537b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 6538519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 65395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]))); 6540552f7358SJed Brown #else 65415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j])); 6542552f7358SJed Brown #endif 6543552f7358SJed Brown } 65445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "\n")); 6545552f7358SJed Brown } 6546552f7358SJed Brown PetscFunctionReturn(0); 6547552f7358SJed Brown } 6548552f7358SJed Brown 654905586334SMatthew G. Knepley /* 655005586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 655105586334SMatthew G. Knepley 655205586334SMatthew G. Knepley Input Parameters: 655305586334SMatthew G. Knepley + section - The section for this data layout 655436fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 655505586334SMatthew G. Knepley . point - The point contributing dofs with these indices 655605586334SMatthew G. Knepley . off - The global offset of this point 655705586334SMatthew G. Knepley . loff - The local offset of each field 6558a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 655905586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 656005586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 656105586334SMatthew G. Knepley 656205586334SMatthew G. Knepley Output Parameter: 656305586334SMatthew G. Knepley . indices - Indices for dofs on this point 656405586334SMatthew G. Knepley 656505586334SMatthew G. Knepley Level: developer 656605586334SMatthew G. Knepley 656705586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 656805586334SMatthew G. Knepley */ 656936fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6570a6dfd86eSKarl Rupp { 6571e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 6572552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6573552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6574552f7358SJed Brown PetscInt cind = 0, k; 6575552f7358SJed Brown 6576552f7358SJed Brown PetscFunctionBegin; 65772c71b3e2SJacob Faibussowitsch PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 65785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, point, &dof)); 65795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(section, point, &cdof)); 6580552f7358SJed Brown if (!cdof || setBC) { 658105586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 658205586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 658305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 658405586334SMatthew G. Knepley 658505586334SMatthew G. Knepley indices[ind] = off + k; 6586552f7358SJed Brown } 6587552f7358SJed Brown } else { 65885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintIndices(section, point, &cdofs)); 65894acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 659005586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 659105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 659205586334SMatthew G. Knepley 65934acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 65944acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 659505586334SMatthew G. Knepley indices[ind] = -(off+k+1); 65964acb8e1eSToby Isaac ++cind; 65974acb8e1eSToby Isaac } else { 659836fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 6599552f7358SJed Brown } 6600552f7358SJed Brown } 6601552f7358SJed Brown } 6602e6ccafaeSMatthew G Knepley *loff += dof; 6603552f7358SJed Brown PetscFunctionReturn(0); 6604552f7358SJed Brown } 6605552f7358SJed Brown 66067e29afd2SMatthew G. Knepley /* 660736fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 66087e29afd2SMatthew G. Knepley 660936fa2b79SJed Brown Input Parameters: 661036fa2b79SJed Brown + section - a section (global or local) 661136fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 661236fa2b79SJed Brown . point - point within section 661336fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 661436fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 661536fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 661636fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 661736fa2b79SJed Brown . permsoff - offset 661836fa2b79SJed Brown - indperm - index permutation 661936fa2b79SJed Brown 662036fa2b79SJed Brown Output Parameter: 662136fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 662236fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 662336fa2b79SJed Brown 662436fa2b79SJed Brown Notes: 662536fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 662636fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 662736fa2b79SJed Brown in the local vector. 662836fa2b79SJed Brown 662936fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 663036fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 663136fa2b79SJed Brown 663236fa2b79SJed Brown Developer Note: 663336fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 663436fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 663536fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 663636fa2b79SJed Brown 663736fa2b79SJed Brown Example: 663836fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 663936fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 664036fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 664136fa2b79SJed 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. 664236fa2b79SJed Brown 664336fa2b79SJed Brown Level: developer 66447e29afd2SMatthew G. Knepley */ 664536fa2b79SJed 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[]) 6646a6dfd86eSKarl Rupp { 6647552f7358SJed Brown PetscInt numFields, foff, f; 6648552f7358SJed Brown 6649552f7358SJed Brown PetscFunctionBegin; 66502c71b3e2SJacob Faibussowitsch PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 66515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &numFields)); 6652552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 66534acb8e1eSToby Isaac PetscInt fdof, cfdof; 6654552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 66554acb8e1eSToby Isaac PetscInt cind = 0, b; 66564acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6657552f7358SJed Brown 66585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof)); 66595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 6660552f7358SJed Brown if (!cfdof || setBC) { 666105586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 666205586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 666305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 666405586334SMatthew G. Knepley 666505586334SMatthew G. Knepley indices[ind] = off+foff+b; 666605586334SMatthew G. Knepley } 6667552f7358SJed Brown } else { 66685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 666905586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 667005586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 667105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 667205586334SMatthew G. Knepley 66734acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 667405586334SMatthew G. Knepley indices[ind] = -(off+foff+b+1); 6675552f7358SJed Brown ++cind; 6676552f7358SJed Brown } else { 667736fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 6678552f7358SJed Brown } 6679552f7358SJed Brown } 6680552f7358SJed Brown } 668136fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6682552f7358SJed Brown foffs[f] += fdof; 6683552f7358SJed Brown } 6684552f7358SJed Brown PetscFunctionReturn(0); 6685552f7358SJed Brown } 6686552f7358SJed Brown 66877e29afd2SMatthew G. Knepley /* 66887e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 66897e29afd2SMatthew G. Knepley 66907e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 6691645102dcSJed Brown 6692645102dcSJed Brown Notes: 6693645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6694645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 66957e29afd2SMatthew G. Knepley */ 6696645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 66977e29afd2SMatthew G. Knepley { 66987e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 66997e29afd2SMatthew G. Knepley 67007e29afd2SMatthew G. Knepley PetscFunctionBegin; 67015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &numFields)); 67027e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 67037e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 67047e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67057e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 67067e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 67077e29afd2SMatthew G. Knepley 67085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof)); 67095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 67105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 6711645102dcSJed Brown if (!cfdof) { 671205586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 671305586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 671405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 671505586334SMatthew G. Knepley 671605586334SMatthew G. Knepley indices[ind] = foff+b; 671705586334SMatthew G. Knepley } 67187e29afd2SMatthew G. Knepley } else { 67195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 672005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 672105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 672205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 672305586334SMatthew G. Knepley 67247e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 672505586334SMatthew G. Knepley indices[ind] = -(foff+b+1); 67267e29afd2SMatthew G. Knepley ++cind; 67277e29afd2SMatthew G. Knepley } else { 672805586334SMatthew G. Knepley indices[ind] = foff+b-cind; 67297e29afd2SMatthew G. Knepley } 67307e29afd2SMatthew G. Knepley } 67317e29afd2SMatthew G. Knepley } 67327e29afd2SMatthew G. Knepley foffs[f] += fdof; 67337e29afd2SMatthew G. Knepley } 67347e29afd2SMatthew G. Knepley PetscFunctionReturn(0); 67357e29afd2SMatthew G. Knepley } 67367e29afd2SMatthew G. Knepley 67374acb8e1eSToby 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) 6738d3d1a6afSToby Isaac { 6739d3d1a6afSToby Isaac Mat cMat; 6740d3d1a6afSToby Isaac PetscSection aSec, cSec; 6741d3d1a6afSToby Isaac IS aIS; 6742d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 6743d3d1a6afSToby Isaac const PetscInt *anchors; 6744e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 6745d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 6746d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 6747d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 6748d3d1a6afSToby Isaac PetscInt newOffsets[32]; 6749d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 6750d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 6751d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 67526ecaa68aSToby Isaac PetscScalar *newValues=NULL,*tmpValues; 6753d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 6754d3d1a6afSToby Isaac 6755d3d1a6afSToby Isaac PetscFunctionBegin; 6756d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6757d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 67585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &numFields)); 6759d3d1a6afSToby Isaac 67605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(dm,&aSec,&aIS)); 6761d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 6762d3d1a6afSToby Isaac if (aSec) { 67635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(newOffsets, 32)); 67645f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(aIS,&anchors)); 67655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(aSec,&aStart,&aEnd)); 6766d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 6767d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 6768d3d1a6afSToby Isaac * into the global matrix anyway) */ 6769d3d1a6afSToby Isaac for (p = 0; p < 2*numPoints; p+=2) { 6770d3d1a6afSToby Isaac PetscInt b = points[p]; 67714b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6772d3d1a6afSToby Isaac 67735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,b,&bSecDof)); 67744b2f2278SToby Isaac if (!bSecDof) { 67754b2f2278SToby Isaac continue; 67764b2f2278SToby Isaac } 6777d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 67785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec,b,&bDof)); 6779d3d1a6afSToby Isaac } 6780d3d1a6afSToby Isaac if (bDof) { 6781d3d1a6afSToby Isaac /* this point is constrained */ 6782d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 6783d3d1a6afSToby Isaac PetscInt bOff, q; 6784d3d1a6afSToby Isaac 6785d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 6786d3d1a6afSToby Isaac newNumPoints += bDof; 67875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,b,&bOff)); 6788d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6789d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6790d3d1a6afSToby Isaac PetscInt aDof; 6791d3d1a6afSToby Isaac 67925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,a,&aDof)); 6793d3d1a6afSToby Isaac newNumIndices += aDof; 6794d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6795d3d1a6afSToby Isaac PetscInt fDof; 6796d3d1a6afSToby Isaac 67975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, a, f, &fDof)); 6798d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6799d3d1a6afSToby Isaac } 6800d3d1a6afSToby Isaac } 6801d3d1a6afSToby Isaac } 6802d3d1a6afSToby Isaac else { 6803d3d1a6afSToby Isaac /* this point is not constrained */ 6804d3d1a6afSToby Isaac newNumPoints++; 68054b2f2278SToby Isaac newNumIndices += bSecDof; 6806d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 6807d3d1a6afSToby Isaac PetscInt fDof; 6808d3d1a6afSToby Isaac 68095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, b, f, &fDof)); 6810d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 6811d3d1a6afSToby Isaac } 6812d3d1a6afSToby Isaac } 6813d3d1a6afSToby Isaac } 6814d3d1a6afSToby Isaac } 6815d3d1a6afSToby Isaac if (!anyConstrained) { 681672b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 681772b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 681872b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 681972b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 68205f80ce2aSJacob Faibussowitsch if (aSec) CHKERRQ(ISRestoreIndices(aIS,&anchors)); 6821d3d1a6afSToby Isaac PetscFunctionReturn(0); 6822d3d1a6afSToby Isaac } 6823d3d1a6afSToby Isaac 68246ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 68256ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 68266ecaa68aSToby Isaac 6827f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6828d3d1a6afSToby Isaac 68296ecaa68aSToby Isaac if (!outPoints && !outValues) { 68306ecaa68aSToby Isaac if (offsets) { 68316ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 68326ecaa68aSToby Isaac offsets[f] = newOffsets[f]; 68336ecaa68aSToby Isaac } 68346ecaa68aSToby Isaac } 68355f80ce2aSJacob Faibussowitsch if (aSec) CHKERRQ(ISRestoreIndices(aIS,&anchors)); 68366ecaa68aSToby Isaac PetscFunctionReturn(0); 68376ecaa68aSToby Isaac } 68386ecaa68aSToby Isaac 68392c71b3e2SJacob Faibussowitsch PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6840d3d1a6afSToby Isaac 68415f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 6842d3d1a6afSToby Isaac 6843d3d1a6afSToby Isaac /* workspaces */ 6844d3d1a6afSToby Isaac if (numFields) { 6845d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 68465f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 68475f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 6848d3d1a6afSToby Isaac } 6849d3d1a6afSToby Isaac } 6850d3d1a6afSToby Isaac else { 68515f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 68525f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0])); 6853d3d1a6afSToby Isaac } 6854d3d1a6afSToby Isaac 6855d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 6856d3d1a6afSToby Isaac if (numFields) { 68574b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 68584b2f2278SToby Isaac 6859d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6860d3d1a6afSToby Isaac PetscInt b = points[2*p]; 68614b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6862d3d1a6afSToby Isaac 68635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,b,&bSecDof)); 68644b2f2278SToby Isaac if (!bSecDof) { 68654b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 68664b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 68674b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 68684b2f2278SToby Isaac } 68694b2f2278SToby Isaac continue; 68704b2f2278SToby Isaac } 6871d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 68725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec, b, &bDof)); 6873d3d1a6afSToby Isaac } 6874d3d1a6afSToby Isaac if (bDof) { 6875d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6876d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 6877d3d1a6afSToby Isaac 68785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, b, f, &fDof)); 68795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec, b, &bOff)); 6880d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6881d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 6882d3d1a6afSToby Isaac PetscInt aFDof; 6883d3d1a6afSToby Isaac 68845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, a, f, &aFDof)); 6885d3d1a6afSToby Isaac allFDof += aFDof; 6886d3d1a6afSToby Isaac } 6887d3d1a6afSToby Isaac newPointOffsets[f][p+1] = allFDof; 6888d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = fDof * allFDof; 6889d3d1a6afSToby Isaac } 6890d3d1a6afSToby Isaac } 6891d3d1a6afSToby Isaac else { 6892d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6893d3d1a6afSToby Isaac PetscInt fDof; 6894d3d1a6afSToby Isaac 68955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, b, f, &fDof)); 6896d3d1a6afSToby Isaac newPointOffsets[f][p+1] = fDof; 6897d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = 0; 6898d3d1a6afSToby Isaac } 6899d3d1a6afSToby Isaac } 6900d3d1a6afSToby Isaac } 69014b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 69024b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 69034b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 6904d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6905d3d1a6afSToby Isaac newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6906d3d1a6afSToby Isaac pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6907d3d1a6afSToby Isaac } 690819f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 690919f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 69105f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 6911d3d1a6afSToby Isaac } 6912d3d1a6afSToby Isaac } 6913d3d1a6afSToby Isaac else { 6914d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6915d3d1a6afSToby Isaac PetscInt b = points[2*p]; 69164b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6917d3d1a6afSToby Isaac 69185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,b,&bSecDof)); 69194b2f2278SToby Isaac if (!bSecDof) { 69204b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 69214b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 69224b2f2278SToby Isaac continue; 69234b2f2278SToby Isaac } 6924d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec, b, &bDof)); 6926d3d1a6afSToby Isaac } 6927d3d1a6afSToby Isaac if (bDof) { 69284b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 6929d3d1a6afSToby Isaac 69305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec, b, &bOff)); 6931d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6932d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 6933d3d1a6afSToby Isaac 69345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, a, &aDof)); 6935d3d1a6afSToby Isaac allDof += aDof; 6936d3d1a6afSToby Isaac } 6937d3d1a6afSToby Isaac newPointOffsets[0][p+1] = allDof; 69384b2f2278SToby Isaac pointMatOffsets[0][p+1] = bSecDof * allDof; 6939d3d1a6afSToby Isaac } 6940d3d1a6afSToby Isaac else { 69414b2f2278SToby Isaac newPointOffsets[0][p+1] = bSecDof; 6942d3d1a6afSToby Isaac pointMatOffsets[0][p+1] = 0; 6943d3d1a6afSToby Isaac } 6944d3d1a6afSToby Isaac } 6945d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 6946d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 6947d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6948d3d1a6afSToby Isaac newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6949d3d1a6afSToby Isaac pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6950d3d1a6afSToby Isaac } 69515f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 6952d3d1a6afSToby Isaac } 6953d3d1a6afSToby Isaac 69546ecaa68aSToby Isaac /* output arrays */ 69555f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 69566ecaa68aSToby Isaac 6957d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 69585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(aSec, &maxAnchor)); 69595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(section, &maxDof)); 69605f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices)); 69615f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 6962d3d1a6afSToby Isaac if (numFields) { 6963d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 6964d3d1a6afSToby Isaac PetscInt b = points[2*p]; 6965d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 69664b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 6967d3d1a6afSToby Isaac 69685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, b, &bSecDof)); 69694b2f2278SToby Isaac if (!bSecDof) { 69704b2f2278SToby Isaac continue; 69714b2f2278SToby Isaac } 6972d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 69735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec, b, &bDof)); 6974d3d1a6afSToby Isaac } 6975d3d1a6afSToby Isaac if (bDof) { 6976d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6977d3d1a6afSToby Isaac 6978d3d1a6afSToby Isaac fStart[0] = 0; 6979d3d1a6afSToby Isaac fEnd[0] = 0; 6980d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6981d3d1a6afSToby Isaac PetscInt fDof; 6982d3d1a6afSToby Isaac 69835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 6984d3d1a6afSToby Isaac fStart[f+1] = fStart[f] + fDof; 6985d3d1a6afSToby Isaac fEnd[f+1] = fStart[f+1]; 6986d3d1a6afSToby Isaac } 69875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(cSec, b, &bOff)); 69885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 6989d3d1a6afSToby Isaac 6990d3d1a6afSToby Isaac fAnchorStart[0] = 0; 6991d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 6992d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6993d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6994d3d1a6afSToby Isaac 6995d3d1a6afSToby Isaac fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6996d3d1a6afSToby Isaac fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6997d3d1a6afSToby Isaac } 69985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec, b, &bOff)); 6999d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7000d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7001d3d1a6afSToby Isaac 7002d3d1a6afSToby 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 */ 7003d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7004d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, a, &aOff)); 70065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7007d3d1a6afSToby Isaac } 7008d3d1a6afSToby Isaac newP += bDof; 7009d3d1a6afSToby Isaac 70106ecaa68aSToby Isaac if (outValues) { 7011d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 7012d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 70135f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p])); 7014d3d1a6afSToby Isaac } 7015d3d1a6afSToby Isaac } 70166ecaa68aSToby Isaac } 7017d3d1a6afSToby Isaac else { 7018d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7019d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7020d3d1a6afSToby Isaac newP++; 7021d3d1a6afSToby Isaac } 7022d3d1a6afSToby Isaac } 7023d3d1a6afSToby Isaac } else { 7024d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7025d3d1a6afSToby Isaac PetscInt b = points[2*p]; 7026d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 70274b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7028d3d1a6afSToby Isaac 70295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, b, &bSecDof)); 70304b2f2278SToby Isaac if (!bSecDof) { 70314b2f2278SToby Isaac continue; 70324b2f2278SToby Isaac } 7033d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 70345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec, b, &bDof)); 7035d3d1a6afSToby Isaac } 7036d3d1a6afSToby Isaac if (bDof) { 7037d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7038d3d1a6afSToby Isaac 70395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(cSec, b, &bOff)); 70405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7041d3d1a6afSToby Isaac 70425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset (aSec, b, &bOff)); 7043d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7044d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7045d3d1a6afSToby Isaac 7046d3d1a6afSToby 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 */ 7047d3d1a6afSToby Isaac 7048d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 7049d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 70505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, a, &aOff)); 70515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7052d3d1a6afSToby Isaac } 7053d3d1a6afSToby Isaac newP += bDof; 7054d3d1a6afSToby Isaac 7055d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 70566ecaa68aSToby Isaac if (outValues) { 70575f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p])); 7058d3d1a6afSToby Isaac } 70596ecaa68aSToby Isaac } 7060d3d1a6afSToby Isaac else { 7061d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7062d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7063d3d1a6afSToby Isaac newP++; 7064d3d1a6afSToby Isaac } 7065d3d1a6afSToby Isaac } 7066d3d1a6afSToby Isaac } 7067d3d1a6afSToby Isaac 70686ecaa68aSToby Isaac if (outValues) { 70695f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 70705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(tmpValues,newNumIndices*numIndices)); 7071d3d1a6afSToby Isaac /* multiply constraints on the right */ 7072d3d1a6afSToby Isaac if (numFields) { 7073d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7074d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7075d3d1a6afSToby Isaac 7076d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7077d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7078d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7079d3d1a6afSToby Isaac PetscInt c, r, k; 7080d3d1a6afSToby Isaac PetscInt dof; 7081d3d1a6afSToby Isaac 70825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,b,f,&dof)); 70834b2f2278SToby Isaac if (!dof) { 70844b2f2278SToby Isaac continue; 70854b2f2278SToby Isaac } 7086d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7087d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7088d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7089d3d1a6afSToby Isaac 7090d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7091d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7092d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 70934acb8e1eSToby Isaac tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7094d3d1a6afSToby Isaac } 7095d3d1a6afSToby Isaac } 7096d3d1a6afSToby Isaac } 7097d3d1a6afSToby Isaac } 7098d3d1a6afSToby Isaac else { 7099d3d1a6afSToby Isaac /* copy this column as is */ 7100d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7101d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7102d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7103d3d1a6afSToby Isaac } 7104d3d1a6afSToby Isaac } 7105d3d1a6afSToby Isaac } 7106d3d1a6afSToby Isaac oldOff += dof; 7107d3d1a6afSToby Isaac } 7108d3d1a6afSToby Isaac } 7109d3d1a6afSToby Isaac } 7110d3d1a6afSToby Isaac else { 7111d3d1a6afSToby Isaac PetscInt oldOff = 0; 7112d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7113d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7114d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7115d3d1a6afSToby Isaac PetscInt c, r, k; 7116d3d1a6afSToby Isaac PetscInt dof; 7117d3d1a6afSToby Isaac 71185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,b,&dof)); 71194b2f2278SToby Isaac if (!dof) { 71204b2f2278SToby Isaac continue; 71214b2f2278SToby Isaac } 7122d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7123d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7124d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7125d3d1a6afSToby Isaac 7126d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7127d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7128d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7129d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7130d3d1a6afSToby Isaac } 7131d3d1a6afSToby Isaac } 7132d3d1a6afSToby Isaac } 7133d3d1a6afSToby Isaac } 7134d3d1a6afSToby Isaac else { 7135d3d1a6afSToby Isaac /* copy this column as is */ 7136d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7137d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 7138d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7139d3d1a6afSToby Isaac } 7140d3d1a6afSToby Isaac } 7141d3d1a6afSToby Isaac } 7142d3d1a6afSToby Isaac oldOff += dof; 7143d3d1a6afSToby Isaac } 7144d3d1a6afSToby Isaac } 7145d3d1a6afSToby Isaac 71466ecaa68aSToby Isaac if (multiplyLeft) { 71475f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues)); 71485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(newValues,newNumIndices*newNumIndices)); 7149d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7150d3d1a6afSToby Isaac if (numFields) { 7151d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7152d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7153d3d1a6afSToby Isaac 7154d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7155d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7156d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7157d3d1a6afSToby Isaac PetscInt c, r, k; 7158d3d1a6afSToby Isaac PetscInt dof; 7159d3d1a6afSToby Isaac 71605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,b,f,&dof)); 7161d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7162d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7163d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7164d3d1a6afSToby Isaac 7165d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7166d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7167d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7168d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7169d3d1a6afSToby Isaac } 7170d3d1a6afSToby Isaac } 7171d3d1a6afSToby Isaac } 7172d3d1a6afSToby Isaac } 7173d3d1a6afSToby Isaac else { 7174d3d1a6afSToby Isaac /* copy this row as is */ 7175d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7176d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7177d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7178d3d1a6afSToby Isaac } 7179d3d1a6afSToby Isaac } 7180d3d1a6afSToby Isaac } 7181d3d1a6afSToby Isaac oldOff += dof; 7182d3d1a6afSToby Isaac } 7183d3d1a6afSToby Isaac } 7184d3d1a6afSToby Isaac } 7185d3d1a6afSToby Isaac else { 7186d3d1a6afSToby Isaac PetscInt oldOff = 0; 7187d3d1a6afSToby Isaac 7188d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7189d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7190d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7191d3d1a6afSToby Isaac PetscInt c, r, k; 7192d3d1a6afSToby Isaac PetscInt dof; 7193d3d1a6afSToby Isaac 71945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,b,&dof)); 7195d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7196d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7197d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7198d3d1a6afSToby Isaac 7199d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7200d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7201d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 7202d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7203d3d1a6afSToby Isaac } 7204d3d1a6afSToby Isaac } 7205d3d1a6afSToby Isaac } 7206d3d1a6afSToby Isaac } 7207d3d1a6afSToby Isaac else { 7208d3d1a6afSToby Isaac /* copy this row as is */ 72099fc93327SToby Isaac for (r = 0; r < dof; r++) { 7210d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7211d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7212d3d1a6afSToby Isaac } 7213d3d1a6afSToby Isaac } 7214d3d1a6afSToby Isaac } 7215d3d1a6afSToby Isaac oldOff += dof; 7216d3d1a6afSToby Isaac } 7217d3d1a6afSToby Isaac } 7218d3d1a6afSToby Isaac 72195f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues)); 72206ecaa68aSToby Isaac } 72216ecaa68aSToby Isaac else { 72226ecaa68aSToby Isaac newValues = tmpValues; 72236ecaa68aSToby Isaac } 72246ecaa68aSToby Isaac } 72256ecaa68aSToby Isaac 7226d3d1a6afSToby Isaac /* clean up */ 72275f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices)); 72285f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices)); 72296ecaa68aSToby Isaac 7230d3d1a6afSToby Isaac if (numFields) { 7231d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 72325f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f])); 72335f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f])); 72345f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f])); 7235d3d1a6afSToby Isaac } 7236d3d1a6afSToby Isaac } 7237d3d1a6afSToby Isaac else { 72385f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0])); 72395f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0])); 72405f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0])); 7241d3d1a6afSToby Isaac } 72425f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(aIS,&anchors)); 7243d3d1a6afSToby Isaac 7244d3d1a6afSToby Isaac /* output */ 72456ecaa68aSToby Isaac if (outPoints) { 7246d3d1a6afSToby Isaac *outPoints = newPoints; 72476ecaa68aSToby Isaac } 72486ecaa68aSToby Isaac else { 72495f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints)); 72506ecaa68aSToby Isaac } 725131620726SToby Isaac if (outValues) { 7252d3d1a6afSToby Isaac *outValues = newValues; 72536ecaa68aSToby Isaac } 72546ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 7255d3d1a6afSToby Isaac offsets[f] = newOffsets[f]; 7256d3d1a6afSToby Isaac } 7257d3d1a6afSToby Isaac PetscFunctionReturn(0); 7258d3d1a6afSToby Isaac } 7259d3d1a6afSToby Isaac 72604a1e0b3eSMatthew G. Knepley /*@C 726171f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 72627cd05799SMatthew G. Knepley 72637cd05799SMatthew G. Knepley Not collective 72647cd05799SMatthew G. Knepley 72657cd05799SMatthew G. Knepley Input Parameters: 72667cd05799SMatthew G. Knepley + dm - The DM 726771f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 726871f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 726971f0bbf9SMatthew G. Knepley . point - The point defining the closure 727071f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 72717cd05799SMatthew G. Knepley 727271f0bbf9SMatthew G. Knepley Output Parameters: 727371f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 727471f0bbf9SMatthew G. Knepley . indices - The dof indices 727571f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 727671f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 72777cd05799SMatthew G. Knepley 727836fa2b79SJed Brown Notes: 727936fa2b79SJed Brown Must call DMPlexRestoreClosureIndices() to free allocated memory 728036fa2b79SJed Brown 728136fa2b79SJed Brown If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 728236fa2b79SJed Brown of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 728336fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 728436fa2b79SJed Brown indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 728536fa2b79SJed Brown indices (with the above semantics) are implied. 72867cd05799SMatthew G. Knepley 72877cd05799SMatthew G. Knepley Level: advanced 72887cd05799SMatthew G. Knepley 728936fa2b79SJed Brown .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 72904a1e0b3eSMatthew G. Knepley @*/ 729171f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 729271f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 72937773e69fSMatthew G. Knepley { 729471f0bbf9SMatthew G. Knepley /* Closure ordering */ 72957773e69fSMatthew G. Knepley PetscSection clSection; 72967773e69fSMatthew G. Knepley IS clPoints; 729771f0bbf9SMatthew G. Knepley const PetscInt *clp; 729871f0bbf9SMatthew G. Knepley PetscInt *points; 729971f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 730071f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 73014acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 730271f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 730371f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 730471f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 730571f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 730671f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 730771f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 730871f0bbf9SMatthew G. Knepley 730971f0bbf9SMatthew G. Knepley PetscInt *idx; 731071f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 731171f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 73127773e69fSMatthew G. Knepley 731371f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 73147773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 73157773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 731636fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7317*dadcf809SJacob Faibussowitsch if (numIndices) PetscValidIntPointer(numIndices, 6); 731871f0bbf9SMatthew G. Knepley if (indices) PetscValidPointer(indices, 7); 7319*dadcf809SJacob Faibussowitsch if (outOffsets) PetscValidIntPointer(outOffsets, 8); 732071f0bbf9SMatthew G. Knepley if (values) PetscValidPointer(values, 9); 73215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &Nf)); 73222c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 73235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(offsets, 32)); 732471f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 73255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7326c459fbc1SJed Brown if (useClPerm) { 7327c459fbc1SJed Brown PetscInt depth, clsize; 73285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPointDepth(dm, point, &depth)); 7329c459fbc1SJed Brown for (clsize=0,p=0; p<Ncl; p++) { 7330c459fbc1SJed Brown PetscInt dof; 73315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, points[2*p], &dof)); 7332c459fbc1SJed Brown clsize += dof; 7333c459fbc1SJed Brown } 73345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm)); 7335c459fbc1SJed Brown } 733671f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 733771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl*2; p += 2) { 73387773e69fSMatthew G. Knepley PetscInt dof, fdof; 73397773e69fSMatthew G. Knepley 73405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, points[p], &dof)); 73417773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 73425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 73437773e69fSMatthew G. Knepley offsets[f+1] += fdof; 73447773e69fSMatthew G. Knepley } 734571f0bbf9SMatthew G. Knepley Ni += dof; 73467773e69fSMatthew G. Knepley } 73477773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 73482c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 734971f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 735071f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73515f80ce2aSJacob Faibussowitsch if (Nf) CHKERRQ(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73525f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 735371f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 735471f0bbf9SMatthew G. Knepley if (values && flips[f]) { 735571f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 73566ecaa68aSToby Isaac 735771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 735871f0bbf9SMatthew G. Knepley PetscInt pnt = points[2*p], fdof; 735971f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 736071f0bbf9SMatthew G. Knepley 73615f80ce2aSJacob Faibussowitsch if (!Nf) CHKERRQ(PetscSectionGetDof(section, pnt, &fdof)); 73625f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 736371f0bbf9SMatthew G. Knepley if (flip) { 736471f0bbf9SMatthew G. Knepley PetscInt i, j, k; 736571f0bbf9SMatthew G. Knepley 736671f0bbf9SMatthew G. Knepley if (!valCopy) { 73675f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 736871f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 736971f0bbf9SMatthew G. Knepley *values = valCopy; 737071f0bbf9SMatthew G. Knepley } 737171f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 737271f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 737371f0bbf9SMatthew G. Knepley 737471f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 737571f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 737671f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 73776ecaa68aSToby Isaac } 73786ecaa68aSToby Isaac } 737971f0bbf9SMatthew G. Knepley } 738071f0bbf9SMatthew G. Knepley foffset += fdof; 738171f0bbf9SMatthew G. Knepley } 738271f0bbf9SMatthew G. Knepley } 738371f0bbf9SMatthew G. Knepley } 738471f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 73855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 738671f0bbf9SMatthew G. Knepley if (NclC) { 73875f80ce2aSJacob Faibussowitsch if (valCopy) CHKERRQ(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy)); 738871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73895f80ce2aSJacob Faibussowitsch if (Nf) CHKERRQ(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 73905f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 739171f0bbf9SMatthew G. Knepley } 739271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 73935f80ce2aSJacob Faibussowitsch if (Nf) CHKERRQ(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 73945f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 739571f0bbf9SMatthew G. Knepley } 73965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 739771f0bbf9SMatthew G. Knepley Ncl = NclC; 739871f0bbf9SMatthew G. Knepley Ni = NiC; 739971f0bbf9SMatthew G. Knepley points = pointsC; 740071f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 740171f0bbf9SMatthew G. Knepley } 740271f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 74035f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 740471f0bbf9SMatthew G. Knepley if (Nf) { 740571f0bbf9SMatthew G. Knepley PetscInt idxOff; 740671f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 740771f0bbf9SMatthew G. Knepley 740871f0bbf9SMatthew G. Knepley if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 74095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 741071f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 741171f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 741271f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 741371f0bbf9SMatthew G. Knepley 74145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 74157773e69fSMatthew G. Knepley } 74167773e69fSMatthew G. Knepley } else { 741771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 741871f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 741971f0bbf9SMatthew G. Knepley 74205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 742171f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 742271f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 742371f0bbf9SMatthew G. Knepley * global section. */ 74245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 742571f0bbf9SMatthew G. Knepley } 742671f0bbf9SMatthew G. Knepley } 742771f0bbf9SMatthew G. Knepley } else { 742871f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 742971f0bbf9SMatthew G. Knepley 743071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 743171f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p*2]; 74324acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 74334acb8e1eSToby Isaac 74345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 743571f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 743671f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 74375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 74387773e69fSMatthew G. Knepley } 74397773e69fSMatthew G. Knepley } 744071f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 744171f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 74425f80ce2aSJacob Faibussowitsch if (Nf) CHKERRQ(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 74435f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 74444acb8e1eSToby Isaac } 744571f0bbf9SMatthew G. Knepley if (NclC) { 74465f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC)); 74477773e69fSMatthew G. Knepley } else { 74485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 74497773e69fSMatthew G. Knepley } 745071f0bbf9SMatthew G. Knepley 745171f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 745271f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 74537773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74547773e69fSMatthew G. Knepley } 74557773e69fSMatthew G. Knepley 74567cd05799SMatthew G. Knepley /*@C 745771f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 74587cd05799SMatthew G. Knepley 74597cd05799SMatthew G. Knepley Not collective 74607cd05799SMatthew G. Knepley 74617cd05799SMatthew G. Knepley Input Parameters: 74627cd05799SMatthew G. Knepley + dm - The DM 746371f0bbf9SMatthew G. Knepley . section - The PetscSection describing the points (a local section) 746471f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global) 746571f0bbf9SMatthew G. Knepley . point - The point defining the closure 746671f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 746771f0bbf9SMatthew G. Knepley 746871f0bbf9SMatthew G. Knepley Output Parameters: 746971f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 747071f0bbf9SMatthew G. Knepley . indices - The dof indices 747171f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL 747271f0bbf9SMatthew G. Knepley - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 747371f0bbf9SMatthew G. Knepley 747471f0bbf9SMatthew G. Knepley Notes: 747571f0bbf9SMatthew G. Knepley If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 747671f0bbf9SMatthew G. Knepley 747771f0bbf9SMatthew G. Knepley If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 747871f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 747971f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 748071f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 748171f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 74827cd05799SMatthew G. Knepley 74837cd05799SMatthew G. Knepley Level: advanced 74847cd05799SMatthew G. Knepley 748571f0bbf9SMatthew G. Knepley .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 74867cd05799SMatthew G. Knepley @*/ 748771f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 748871f0bbf9SMatthew G. Knepley PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 74897773e69fSMatthew G. Knepley { 74907773e69fSMatthew G. Knepley PetscFunctionBegin; 74917773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7492064a246eSJacob Faibussowitsch PetscValidPointer(indices, 7); 74935f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 74947773e69fSMatthew G. Knepley PetscFunctionReturn(0); 74957773e69fSMatthew G. Knepley } 74967773e69fSMatthew G. Knepley 74977f5d1fdeSMatthew G. Knepley /*@C 74987f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 74997f5d1fdeSMatthew G. Knepley 75007f5d1fdeSMatthew G. Knepley Not collective 75017f5d1fdeSMatthew G. Knepley 75027f5d1fdeSMatthew G. Knepley Input Parameters: 75037f5d1fdeSMatthew G. Knepley + dm - The DM 7504ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section 7505ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section 75067f5d1fdeSMatthew G. Knepley . A - The matrix 7507eaf898f9SPatrick Sanan . point - The point in the DM 75087f5d1fdeSMatthew G. Knepley . values - The array of values 75097f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75107f5d1fdeSMatthew G. Knepley 75117f5d1fdeSMatthew G. Knepley Fortran Notes: 75127f5d1fdeSMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 75137f5d1fdeSMatthew G. Knepley 75147f5d1fdeSMatthew G. Knepley Level: intermediate 75157f5d1fdeSMatthew G. Knepley 75164a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 75177f5d1fdeSMatthew G. Knepley @*/ 75187c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7519552f7358SJed Brown { 7520552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7521552f7358SJed Brown PetscInt *indices; 752271f0bbf9SMatthew G. Knepley PetscInt numIndices; 752371f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 7524552f7358SJed Brown PetscErrorCode ierr; 7525552f7358SJed Brown 7526552f7358SJed Brown PetscFunctionBegin; 7527552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 75285f80ce2aSJacob Faibussowitsch if (!section) CHKERRQ(DMGetLocalSection(dm, §ion)); 75293dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 75305f80ce2aSJacob Faibussowitsch if (!globalSection) CHKERRQ(DMGetGlobalSection(dm, &globalSection)); 75313dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 75323dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7533552f7358SJed Brown 75345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75350d644c17SKarl Rupp 75365f80ce2aSJacob Faibussowitsch if (mesh->printSetValues) CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 75374a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7538552f7358SJed Brown if (ierr) { 7539552f7358SJed Brown PetscMPIInt rank; 7540552f7358SJed Brown 75415f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 75425f80ce2aSJacob Faibussowitsch CHKERRQ((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 75435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 75445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75455f80ce2aSJacob Faibussowitsch if (values != valuesOrig) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 7546c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7547552f7358SJed Brown } 75484a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 75494a1e0b3eSMatthew G. Knepley PetscInt i; 75505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 75515f80ce2aSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) CHKERRQ(PetscPrintf(PETSC_COMM_SELF, " %D", indices[i])); 75525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n")); 75534a1e0b3eSMatthew G. Knepley } 755471f0bbf9SMatthew G. Knepley 75555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values)); 75565f80ce2aSJacob Faibussowitsch if (values != valuesOrig) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 755771f0bbf9SMatthew G. Knepley PetscFunctionReturn(0); 75584acb8e1eSToby Isaac } 755971f0bbf9SMatthew G. Knepley 75604a1e0b3eSMatthew G. Knepley /*@C 75614a1e0b3eSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 75624a1e0b3eSMatthew G. Knepley 75634a1e0b3eSMatthew G. Knepley Not collective 75644a1e0b3eSMatthew G. Knepley 75654a1e0b3eSMatthew G. Knepley Input Parameters: 75664a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields 75674a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 75684a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 75694a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields 75704a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 75714a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 75724a1e0b3eSMatthew G. Knepley . A - The matrix 75734a1e0b3eSMatthew G. Knepley . point - The point in the DMs 75744a1e0b3eSMatthew G. Knepley . values - The array of values 75754a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 75764a1e0b3eSMatthew G. Knepley 75774a1e0b3eSMatthew G. Knepley Level: intermediate 75784a1e0b3eSMatthew G. Knepley 75794a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 75804a1e0b3eSMatthew G. Knepley @*/ 758171f0bbf9SMatthew 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) 758271f0bbf9SMatthew G. Knepley { 758371f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmRow->data; 758471f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 758571f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 758671f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 758771f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 758871f0bbf9SMatthew G. Knepley 758971f0bbf9SMatthew G. Knepley PetscFunctionBegin; 759071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 75915f80ce2aSJacob Faibussowitsch if (!sectionRow) CHKERRQ(DMGetLocalSection(dmRow, §ionRow)); 759271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 75935f80ce2aSJacob Faibussowitsch if (!globalSectionRow) CHKERRQ(DMGetGlobalSection(dmRow, &globalSectionRow)); 759471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 759571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 75965f80ce2aSJacob Faibussowitsch if (!sectionCol) CHKERRQ(DMGetLocalSection(dmCol, §ionCol)); 759771f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 75985f80ce2aSJacob Faibussowitsch if (!globalSectionCol) CHKERRQ(DMGetGlobalSection(dmCol, &globalSectionCol)); 759971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 760071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 760171f0bbf9SMatthew G. Knepley 76025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 760471f0bbf9SMatthew G. Knepley 76055f80ce2aSJacob Faibussowitsch if (mesh->printSetValues) CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 76064a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 760771f0bbf9SMatthew G. Knepley if (ierr) { 760871f0bbf9SMatthew G. Knepley PetscMPIInt rank; 760971f0bbf9SMatthew G. Knepley 76105f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 76115f80ce2aSJacob Faibussowitsch CHKERRQ((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 76125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 76135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values)); 76155f80ce2aSJacob Faibussowitsch if (values != valuesOrig) CHKERRQ(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 761671f0bbf9SMatthew G. Knepley CHKERRQ(ierr); 7617d3d1a6afSToby Isaac } 761871f0bbf9SMatthew G. Knepley 76195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values)); 76205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values)); 76215f80ce2aSJacob Faibussowitsch if (values != valuesOrig) CHKERRQ(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 7622552f7358SJed Brown PetscFunctionReturn(0); 7623552f7358SJed Brown } 7624552f7358SJed Brown 7625de41b84cSMatthew 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) 7626de41b84cSMatthew G. Knepley { 7627de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmf->data; 7628de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 7629de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 7630de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 763117c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7632de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 7633412e9a14SMatthew G. Knepley DMPolytopeType ct; 76344ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7635de41b84cSMatthew G. Knepley PetscErrorCode ierr; 7636de41b84cSMatthew G. Knepley 7637de41b84cSMatthew G. Knepley PetscFunctionBegin; 7638de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7639de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 76405f80ce2aSJacob Faibussowitsch if (!fsection) CHKERRQ(DMGetLocalSection(dmf, &fsection)); 7641de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 76425f80ce2aSJacob Faibussowitsch if (!csection) CHKERRQ(DMGetLocalSection(dmc, &csection)); 7643de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 76445f80ce2aSJacob Faibussowitsch if (!globalFSection) CHKERRQ(DMGetGlobalSection(dmf, &globalFSection)); 7645de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 76465f80ce2aSJacob Faibussowitsch if (!globalCSection) CHKERRQ(DMGetGlobalSection(dmc, &globalCSection)); 7647de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7648de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 76495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(fsection, &numFields)); 76502c71b3e2SJacob Faibussowitsch PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 76515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(foffsets, 32)); 76525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(coffsets, 32)); 7653de41b84cSMatthew G. Knepley /* Column indices */ 76545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 76554ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 7656de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 7657de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 76585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(csection, &pStart, &pEnd)); 7659de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7660de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7661de41b84cSMatthew G. Knepley cpoints[q*2] = cpoints[p]; 7662de41b84cSMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 7663de41b84cSMatthew G. Knepley ++q; 7664de41b84cSMatthew G. Knepley } 7665de41b84cSMatthew G. Knepley } 7666de41b84cSMatthew G. Knepley numCPoints = q; 7667de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7668de41b84cSMatthew G. Knepley PetscInt fdof; 7669de41b84cSMatthew G. Knepley 76705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(csection, cpoints[p], &dof)); 76714ca5e9f5SMatthew G. Knepley if (!dof) continue; 7672de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 76735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 7674de41b84cSMatthew G. Knepley coffsets[f+1] += fdof; 7675de41b84cSMatthew G. Knepley } 7676de41b84cSMatthew G. Knepley numCIndices += dof; 7677de41b84cSMatthew G. Knepley } 7678de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7679de41b84cSMatthew G. Knepley /* Row indices */ 76805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dmc, point, &ct)); 7681412e9a14SMatthew G. Knepley { 7682012bc364SMatthew G. Knepley DMPlexTransform tr; 7683012bc364SMatthew G. Knepley DMPolytopeType *rct; 7684012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7685012bc364SMatthew G. Knepley 76865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 76875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 76885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7689012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 76905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransformDestroy(&tr)); 7691412e9a14SMatthew G. Knepley } 76925f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 7693de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 7694de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 76955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 7696de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 76975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(fsection, &pStart, &pEnd)); 7698de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 7699de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 77005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(fsection, fpoints[p], &dof)); 77014ca5e9f5SMatthew G. Knepley if (!dof) continue; 77024ca5e9f5SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 77034ca5e9f5SMatthew G. Knepley if (s < q) continue; 7704de41b84cSMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 7705de41b84cSMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 7706de41b84cSMatthew G. Knepley ++q; 7707de41b84cSMatthew G. Knepley } 7708de41b84cSMatthew G. Knepley } 77095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 7710de41b84cSMatthew G. Knepley } 7711de41b84cSMatthew G. Knepley numFPoints = q; 7712de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7713de41b84cSMatthew G. Knepley PetscInt fdof; 7714de41b84cSMatthew G. Knepley 77155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 77164ca5e9f5SMatthew G. Knepley if (!dof) continue; 7717de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 77185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 7719de41b84cSMatthew G. Knepley foffsets[f+1] += fdof; 7720de41b84cSMatthew G. Knepley } 7721de41b84cSMatthew G. Knepley numFIndices += dof; 7722de41b84cSMatthew G. Knepley } 7723de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7724de41b84cSMatthew G. Knepley 77252c71b3e2SJacob Faibussowitsch PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 77262c71b3e2SJacob Faibussowitsch PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 77275f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77285f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7729de41b84cSMatthew G. Knepley if (numFields) { 77304acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 77314acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 77324acb8e1eSToby Isaac 77334acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7736de41b84cSMatthew G. Knepley } 77374acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 77385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 77404acb8e1eSToby Isaac } 77414acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 77425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 77444acb8e1eSToby Isaac } 77454acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 77465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 77475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 7748de41b84cSMatthew G. Knepley } 7749de41b84cSMatthew G. Knepley } else { 77504acb8e1eSToby Isaac const PetscInt **permsF = NULL; 77514acb8e1eSToby Isaac const PetscInt **permsC = NULL; 77524acb8e1eSToby Isaac 77535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 77554acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 77564acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 77574acb8e1eSToby Isaac 77585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 77595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 7760de41b84cSMatthew G. Knepley } 77614acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 77624acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 77634acb8e1eSToby Isaac 77645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 77655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 7766de41b84cSMatthew G. Knepley } 77675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 77685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 7769de41b84cSMatthew G. Knepley } 77705f80ce2aSJacob Faibussowitsch if (mesh->printSetValues) CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77714acb8e1eSToby Isaac /* TODO: flips */ 7772de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7773de41b84cSMatthew G. Knepley if (ierr) { 7774de41b84cSMatthew G. Knepley PetscMPIInt rank; 7775de41b84cSMatthew G. Knepley 77765f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 77775f80ce2aSJacob Faibussowitsch CHKERRQ((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 77785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 77795f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77805f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7781de41b84cSMatthew G. Knepley CHKERRQ(ierr); 7782de41b84cSMatthew G. Knepley } 77835f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 77845f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 77855f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 77865f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 7787de41b84cSMatthew G. Knepley PetscFunctionReturn(0); 7788de41b84cSMatthew G. Knepley } 7789de41b84cSMatthew G. Knepley 77907c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 77917c927364SMatthew G. Knepley { 77927c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 77937c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 77947c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 779517c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7796412e9a14SMatthew G. Knepley DMPolytopeType ct; 77977c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 77987c927364SMatthew G. Knepley 77997c927364SMatthew G. Knepley PetscFunctionBegin; 78007c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 78017c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 78025f80ce2aSJacob Faibussowitsch if (!fsection) CHKERRQ(DMGetLocalSection(dmf, &fsection)); 78037c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 78045f80ce2aSJacob Faibussowitsch if (!csection) CHKERRQ(DMGetLocalSection(dmc, &csection)); 78057c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 78065f80ce2aSJacob Faibussowitsch if (!globalFSection) CHKERRQ(DMGetGlobalSection(dmf, &globalFSection)); 78077c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 78085f80ce2aSJacob Faibussowitsch if (!globalCSection) CHKERRQ(DMGetGlobalSection(dmc, &globalCSection)); 78097c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 78105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(fsection, &numFields)); 78112c71b3e2SJacob Faibussowitsch PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 78125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(foffsets, 32)); 78135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(coffsets, 32)); 78147c927364SMatthew G. Knepley /* Column indices */ 78155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 78167c927364SMatthew G. Knepley maxFPoints = numCPoints; 78177c927364SMatthew G. Knepley /* Compress out points not in the section */ 78187c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 78195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(csection, &pStart, &pEnd)); 78207c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 78217c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 78227c927364SMatthew G. Knepley cpoints[q*2] = cpoints[p]; 78237c927364SMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 78247c927364SMatthew G. Knepley ++q; 78257c927364SMatthew G. Knepley } 78267c927364SMatthew G. Knepley } 78277c927364SMatthew G. Knepley numCPoints = q; 78287c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 78297c927364SMatthew G. Knepley PetscInt fdof; 78307c927364SMatthew G. Knepley 78315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(csection, cpoints[p], &dof)); 78327c927364SMatthew G. Knepley if (!dof) continue; 78337c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 78357c927364SMatthew G. Knepley coffsets[f+1] += fdof; 78367c927364SMatthew G. Knepley } 78377c927364SMatthew G. Knepley numCIndices += dof; 78387c927364SMatthew G. Knepley } 78397c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 78407c927364SMatthew G. Knepley /* Row indices */ 78415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dmc, point, &ct)); 7842412e9a14SMatthew G. Knepley { 7843012bc364SMatthew G. Knepley DMPlexTransform tr; 7844012bc364SMatthew G. Knepley DMPolytopeType *rct; 7845012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 7846012bc364SMatthew G. Knepley 78475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 78485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 78495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 7850012bc364SMatthew G. Knepley numSubcells = rsize[Nt-1]; 78515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransformDestroy(&tr)); 7852412e9a14SMatthew G. Knepley } 78535f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints)); 78547c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 78557c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 78565f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 78577c927364SMatthew G. Knepley /* Compress out points not in the section */ 78585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(fsection, &pStart, &pEnd)); 78597c927364SMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 78607c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 78615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(fsection, fpoints[p], &dof)); 78627c927364SMatthew G. Knepley if (!dof) continue; 78637c927364SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 78647c927364SMatthew G. Knepley if (s < q) continue; 78657c927364SMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 78667c927364SMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 78677c927364SMatthew G. Knepley ++q; 78687c927364SMatthew G. Knepley } 78697c927364SMatthew G. Knepley } 78705f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 78717c927364SMatthew G. Knepley } 78727c927364SMatthew G. Knepley numFPoints = q; 78737c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 78747c927364SMatthew G. Knepley PetscInt fdof; 78757c927364SMatthew G. Knepley 78765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 78777c927364SMatthew G. Knepley if (!dof) continue; 78787c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 78795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 78807c927364SMatthew G. Knepley foffsets[f+1] += fdof; 78817c927364SMatthew G. Knepley } 78827c927364SMatthew G. Knepley numFIndices += dof; 78837c927364SMatthew G. Knepley } 78847c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 78857c927364SMatthew G. Knepley 78862c71b3e2SJacob Faibussowitsch PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 78872c71b3e2SJacob Faibussowitsch PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 78887c927364SMatthew G. Knepley if (numFields) { 78894acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 78904acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 78914acb8e1eSToby Isaac 78924acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 78935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 78945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 78957c927364SMatthew G. Knepley } 78964acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 78975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 78985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 78994acb8e1eSToby Isaac } 79004acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 79015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 79034acb8e1eSToby Isaac } 79044acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 79055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL)); 79065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL)); 79077c927364SMatthew G. Knepley } 79087c927364SMatthew G. Knepley } else { 79094acb8e1eSToby Isaac const PetscInt **permsF = NULL; 79104acb8e1eSToby Isaac const PetscInt **permsC = NULL; 79114acb8e1eSToby Isaac 79125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79144acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 79154acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 79164acb8e1eSToby Isaac 79175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff)); 79185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 79197c927364SMatthew G. Knepley } 79204acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 79214acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 79224acb8e1eSToby Isaac 79235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff)); 79245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 79257c927364SMatthew G. Knepley } 79265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL)); 79275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL)); 79287c927364SMatthew G. Knepley } 79295f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints)); 79305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 79317c927364SMatthew G. Knepley PetscFunctionReturn(0); 79327c927364SMatthew G. Knepley } 79337c927364SMatthew G. Knepley 79347cd05799SMatthew G. Knepley /*@C 79357cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 79367cd05799SMatthew G. Knepley 79377cd05799SMatthew G. Knepley Input Parameter: 79387cd05799SMatthew G. Knepley . dm - The DMPlex object 79397cd05799SMatthew G. Knepley 79407cd05799SMatthew G. Knepley Output Parameter: 79417cd05799SMatthew G. Knepley . cellHeight - The height of a cell 79427cd05799SMatthew G. Knepley 79437cd05799SMatthew G. Knepley Level: developer 79447cd05799SMatthew G. Knepley 79457cd05799SMatthew G. Knepley .seealso DMPlexSetVTKCellHeight() 79467cd05799SMatthew G. Knepley @*/ 7947552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7948552f7358SJed Brown { 7949552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7950552f7358SJed Brown 7951552f7358SJed Brown PetscFunctionBegin; 7952552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7953*dadcf809SJacob Faibussowitsch PetscValidIntPointer(cellHeight, 2); 7954552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 7955552f7358SJed Brown PetscFunctionReturn(0); 7956552f7358SJed Brown } 7957552f7358SJed Brown 79587cd05799SMatthew G. Knepley /*@C 79597cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 79607cd05799SMatthew G. Knepley 79617cd05799SMatthew G. Knepley Input Parameters: 79627cd05799SMatthew G. Knepley + dm - The DMPlex object 79637cd05799SMatthew G. Knepley - cellHeight - The height of a cell 79647cd05799SMatthew G. Knepley 79657cd05799SMatthew G. Knepley Level: developer 79667cd05799SMatthew G. Knepley 79677cd05799SMatthew G. Knepley .seealso DMPlexGetVTKCellHeight() 79687cd05799SMatthew G. Knepley @*/ 7969552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7970552f7358SJed Brown { 7971552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7972552f7358SJed Brown 7973552f7358SJed Brown PetscFunctionBegin; 7974552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7975552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 7976552f7358SJed Brown PetscFunctionReturn(0); 7977552f7358SJed Brown } 7978552f7358SJed Brown 7979e6139122SMatthew G. Knepley /*@ 7980e6139122SMatthew G. Knepley DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7981e6139122SMatthew G. Knepley 7982e6139122SMatthew G. Knepley Input Parameter: 7983e6139122SMatthew G. Knepley . dm - The DMPlex object 7984e6139122SMatthew G. Knepley 7985e6139122SMatthew G. Knepley Output Parameters: 79862a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL 79872a9f31c0SMatthew G. Knepley - gcEnd - The upper bound on ghost cells, or NULL 7988e6139122SMatthew G. Knepley 79892a9f31c0SMatthew G. Knepley Level: advanced 7990e6139122SMatthew G. Knepley 79918065b584SMatthew Knepley .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7992e6139122SMatthew G. Knepley @*/ 7993e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7994e6139122SMatthew G. Knepley { 7995412e9a14SMatthew G. Knepley DMLabel ctLabel; 7996e6139122SMatthew G. Knepley 7997e6139122SMatthew G. Knepley PetscFunctionBegin; 7998e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 79995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellTypeLabel(dm, &ctLabel)); 80005f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd)); 8001e6139122SMatthew G. Knepley PetscFunctionReturn(0); 8002e6139122SMatthew G. Knepley } 8003e6139122SMatthew G. Knepley 80049886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8005552f7358SJed Brown { 8006552f7358SJed Brown PetscSection section, globalSection; 8007552f7358SJed Brown PetscInt *numbers, p; 8008552f7358SJed Brown 8009552f7358SJed Brown PetscFunctionBegin; 80105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 80115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(section, pStart, pEnd)); 8012552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(section, p, 1)); 8014552f7358SJed Brown } 80155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(section)); 80165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 80175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd - pStart, &numbers)); 8018552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 80195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart])); 8020ef48cebcSMatthew G. Knepley if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8021ef48cebcSMatthew G. Knepley else numbers[p-pStart] += shift; 8022552f7358SJed Brown } 80235f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8024ef48cebcSMatthew G. Knepley if (globalSize) { 8025ef48cebcSMatthew G. Knepley PetscLayout layout; 80265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout)); 80275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetSize(layout, globalSize)); 80285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutDestroy(&layout)); 8029ef48cebcSMatthew G. Knepley } 80305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(§ion)); 80315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&globalSection)); 8032552f7358SJed Brown PetscFunctionReturn(0); 8033552f7358SJed Brown } 8034552f7358SJed Brown 803581ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8036552f7358SJed Brown { 8037412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8038552f7358SJed Brown 8039552f7358SJed Brown PetscFunctionBegin; 80405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight)); 80415f80ce2aSJacob Faibussowitsch if (includeHybrid) CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 80425f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 80435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 804481ed3555SMatthew G. Knepley PetscFunctionReturn(0); 8045552f7358SJed Brown } 804681ed3555SMatthew G. Knepley 80478dab3259SMatthew G. Knepley /*@ 80487cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 80497cd05799SMatthew G. Knepley 80507cd05799SMatthew G. Knepley Input Parameter: 80517cd05799SMatthew G. Knepley . dm - The DMPlex object 80527cd05799SMatthew G. Knepley 80537cd05799SMatthew G. Knepley Output Parameter: 80547cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 80557cd05799SMatthew G. Knepley 80567cd05799SMatthew G. Knepley Level: developer 80577cd05799SMatthew G. Knepley 80587cd05799SMatthew G. Knepley .seealso DMPlexGetVertexNumbering() 80597cd05799SMatthew G. Knepley @*/ 806081ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 806181ed3555SMatthew G. Knepley { 806281ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 806381ed3555SMatthew G. Knepley 806481ed3555SMatthew G. Knepley PetscFunctionBegin; 806581ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80665f80ce2aSJacob Faibussowitsch if (!mesh->globalCellNumbers) CHKERRQ(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8067552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 8068552f7358SJed Brown PetscFunctionReturn(0); 8069552f7358SJed Brown } 8070552f7358SJed Brown 807181ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 807281ed3555SMatthew G. Knepley { 8073412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 807481ed3555SMatthew G. Knepley 807581ed3555SMatthew G. Knepley PetscFunctionBegin; 807681ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 80785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 807981ed3555SMatthew G. Knepley PetscFunctionReturn(0); 808081ed3555SMatthew G. Knepley } 808181ed3555SMatthew G. Knepley 80828dab3259SMatthew G. Knepley /*@ 80836aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 80847cd05799SMatthew G. Knepley 80857cd05799SMatthew G. Knepley Input Parameter: 80867cd05799SMatthew G. Knepley . dm - The DMPlex object 80877cd05799SMatthew G. Knepley 80887cd05799SMatthew G. Knepley Output Parameter: 80897cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 80907cd05799SMatthew G. Knepley 80917cd05799SMatthew G. Knepley Level: developer 80927cd05799SMatthew G. Knepley 80937cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering() 80947cd05799SMatthew G. Knepley @*/ 8095552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8096552f7358SJed Brown { 8097552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 8098552f7358SJed Brown 8099552f7358SJed Brown PetscFunctionBegin; 8100552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81015f80ce2aSJacob Faibussowitsch if (!mesh->globalVertexNumbers) CHKERRQ(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8102552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 8103552f7358SJed Brown PetscFunctionReturn(0); 8104552f7358SJed Brown } 8105552f7358SJed Brown 81068dab3259SMatthew G. Knepley /*@ 81077cd05799SMatthew G. Knepley DMPlexCreatePointNumbering - Create a global numbering for all points on this process 81087cd05799SMatthew G. Knepley 81097cd05799SMatthew G. Knepley Input Parameter: 81107cd05799SMatthew G. Knepley . dm - The DMPlex object 81117cd05799SMatthew G. Knepley 81127cd05799SMatthew G. Knepley Output Parameter: 81137cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 81147cd05799SMatthew G. Knepley 81157cd05799SMatthew G. Knepley Level: developer 81167cd05799SMatthew G. Knepley 81177cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering() 81187cd05799SMatthew G. Knepley @*/ 8119ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8120ef48cebcSMatthew G. Knepley { 8121ef48cebcSMatthew G. Knepley IS nums[4]; 8122862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8123ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 8124ef48cebcSMatthew G. Knepley 8125ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8126ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 81288abc87a0SMichael Lange /* For unstratified meshes use dim instead of depth */ 81295f80ce2aSJacob Faibussowitsch if (depth < 0) CHKERRQ(DMGetDimension(dm, &depth)); 8130862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8131862913ffSStefano Zampini PetscInt end; 8132862913ffSStefano Zampini 8133862913ffSStefano Zampini depths[d] = depth-d; 81345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 8135862913ffSStefano Zampini if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8136862913ffSStefano Zampini } 81375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortIntWithArray(depth+1, starts, depths)); 81385f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm))); 8139862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 81402c71b3e2SJacob Faibussowitsch PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8141862913ffSStefano Zampini } 8142ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8143ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8144ef48cebcSMatthew G. Knepley 81455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 81465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8147ef48cebcSMatthew G. Knepley shift += gsize; 8148ef48cebcSMatthew G. Knepley } 81495f80ce2aSJacob Faibussowitsch CHKERRQ(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers)); 81505f80ce2aSJacob Faibussowitsch for (d = 0; d <= depth; ++d) CHKERRQ(ISDestroy(&nums[d])); 8151ef48cebcSMatthew G. Knepley PetscFunctionReturn(0); 8152ef48cebcSMatthew G. Knepley } 8153ef48cebcSMatthew G. Knepley 815408a22f4bSMatthew G. Knepley /*@ 815508a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 815608a22f4bSMatthew G. Knepley 815708a22f4bSMatthew G. Knepley Input Parameter: 815808a22f4bSMatthew G. Knepley . dm - The DMPlex object 815908a22f4bSMatthew G. Knepley 816008a22f4bSMatthew G. Knepley Output Parameter: 816108a22f4bSMatthew G. Knepley . ranks - The rank field 816208a22f4bSMatthew G. Knepley 816308a22f4bSMatthew G. Knepley Options Database Keys: 816408a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 816508a22f4bSMatthew G. Knepley 816608a22f4bSMatthew G. Knepley Level: intermediate 816708a22f4bSMatthew G. Knepley 816808a22f4bSMatthew G. Knepley .seealso: DMView() 816908a22f4bSMatthew G. Knepley @*/ 817008a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 817108a22f4bSMatthew G. Knepley { 817208a22f4bSMatthew G. Knepley DM rdm; 817308a22f4bSMatthew G. Knepley PetscFE fe; 817408a22f4bSMatthew G. Knepley PetscScalar *r; 817508a22f4bSMatthew G. Knepley PetscMPIInt rank; 8176a55f9a55SMatthew G. Knepley DMPolytopeType ct; 817708a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8178a55f9a55SMatthew G. Knepley PetscBool simplex; 817908a22f4bSMatthew G. Knepley 818008a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8181f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8182f95ace6aSMatthew G. Knepley PetscValidPointer(ranks, 2); 81835f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 81845f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dm, &rdm)); 81855f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(rdm, &dim)); 81865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 81875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cStart, &ct)); 8188a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 81895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 81905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) fe, "rank")); 81915f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 81925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fe)); 81935f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(rdm)); 81945f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(rdm, ranks)); 81955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *ranks, "partition")); 81965f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(*ranks, &r)); 819708a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 819808a22f4bSMatthew G. Knepley PetscScalar *lr; 819908a22f4bSMatthew G. Knepley 82005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointGlobalRef(rdm, c, r, &lr)); 820171f09efeSPierre Jolivet if (lr) *lr = rank; 820208a22f4bSMatthew G. Knepley } 82035f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(*ranks, &r)); 82045f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&rdm)); 820508a22f4bSMatthew G. Knepley PetscFunctionReturn(0); 820608a22f4bSMatthew G. Knepley } 820708a22f4bSMatthew G. Knepley 8208ca8062c8SMatthew G. Knepley /*@ 820918e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 821018e14f0cSMatthew G. Knepley 821118e14f0cSMatthew G. Knepley Input Parameters: 821218e14f0cSMatthew G. Knepley + dm - The DMPlex 821318e14f0cSMatthew G. Knepley - label - The DMLabel 821418e14f0cSMatthew G. Knepley 821518e14f0cSMatthew G. Knepley Output Parameter: 821618e14f0cSMatthew G. Knepley . val - The label value field 821718e14f0cSMatthew G. Knepley 821818e14f0cSMatthew G. Knepley Options Database Keys: 821918e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 822018e14f0cSMatthew G. Knepley 822118e14f0cSMatthew G. Knepley Level: intermediate 822218e14f0cSMatthew G. Knepley 822318e14f0cSMatthew G. Knepley .seealso: DMView() 822418e14f0cSMatthew G. Knepley @*/ 822518e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 822618e14f0cSMatthew G. Knepley { 822718e14f0cSMatthew G. Knepley DM rdm; 822818e14f0cSMatthew G. Knepley PetscFE fe; 822918e14f0cSMatthew G. Knepley PetscScalar *v; 823018e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 823118e14f0cSMatthew G. Knepley 823218e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 823318e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 823418e14f0cSMatthew G. Knepley PetscValidPointer(label, 2); 823518e14f0cSMatthew G. Knepley PetscValidPointer(val, 3); 82365f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dm, &rdm)); 82375f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(rdm, &dim)); 82385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 82395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) fe, "label_value")); 82405f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(rdm, 0, NULL, (PetscObject) fe)); 82415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fe)); 82425f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(rdm)); 82435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 82445f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(rdm, val)); 82455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *val, "label_value")); 82465f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(*val, &v)); 824718e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 824818e14f0cSMatthew G. Knepley PetscScalar *lv; 824918e14f0cSMatthew G. Knepley PetscInt cval; 825018e14f0cSMatthew G. Knepley 82515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointGlobalRef(rdm, c, v, &lv)); 82525f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(label, c, &cval)); 825318e14f0cSMatthew G. Knepley *lv = cval; 825418e14f0cSMatthew G. Knepley } 82555f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(*val, &v)); 82565f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&rdm)); 825718e14f0cSMatthew G. Knepley PetscFunctionReturn(0); 825818e14f0cSMatthew G. Knepley } 825918e14f0cSMatthew G. Knepley 826018e14f0cSMatthew G. Knepley /*@ 8261ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8262ca8062c8SMatthew G. Knepley 826369916449SMatthew G. Knepley Input Parameter: 826469916449SMatthew G. Knepley . dm - The DMPlex object 8265ca8062c8SMatthew G. Knepley 826695eb5ee5SVaclav Hapla Notes: 826795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 826895eb5ee5SVaclav Hapla 826995eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8270ca8062c8SMatthew G. Knepley 8271ca8062c8SMatthew G. Knepley Level: developer 8272ca8062c8SMatthew G. Knepley 827395eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 8274ca8062c8SMatthew G. Knepley @*/ 8275ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm) 8276ca8062c8SMatthew G. Knepley { 8277ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8278ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8279ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 828057beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 828157beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8282ca8062c8SMatthew G. Knepley 8283ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8284ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 82855f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 82865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSection(dm, &coneSection)); 82875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSection(dm, &supportSection)); 8288ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 82895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 8290ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 82915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 82925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 8293ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 829442e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 829542e66dfaSMatthew G. Knepley PetscInt d; 829642e66dfaSMatthew G. Knepley for (d = c-1; d >= 0; --d) { 829742e66dfaSMatthew G. Knepley if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 829842e66dfaSMatthew G. Knepley } 82995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 83005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, cone[c], &support)); 8301ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8302ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8303ca8062c8SMatthew G. Knepley } 830442e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s+1] != p))) { 83055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p)); 8306ca8062c8SMatthew G. Knepley for (s = 0; s < coneSize; ++s) { 83075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s])); 8308ca8062c8SMatthew G. Knepley } 83095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n")); 83105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c])); 8311ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 83125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s])); 8313ca8062c8SMatthew G. Knepley } 83145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n")); 831528b400f6SJacob Faibussowitsch PetscCheck(!dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 831698921bdaSJacob Faibussowitsch else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8317ca8062c8SMatthew G. Knepley } 831842e66dfaSMatthew G. Knepley } 83195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm, p, &pp, NULL)); 832057beb4faSStefano Zampini if (p != pp) { storagecheck = PETSC_FALSE; continue; } 83215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize)); 83225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, p, &support)); 8323ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 83245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, support[s], &coneSize)); 83255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, support[s], &cone)); 8326ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 83275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 832857beb4faSStefano Zampini if (cone[c] != pp) { c = 0; break; } 8329ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8330ca8062c8SMatthew G. Knepley } 8331ca8062c8SMatthew G. Knepley if (c >= coneSize) { 83325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p)); 8333ca8062c8SMatthew G. Knepley for (c = 0; c < supportSize; ++c) { 83345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c])); 8335ca8062c8SMatthew G. Knepley } 83365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n")); 83375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s])); 8338ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 83395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c])); 8340ca8062c8SMatthew G. Knepley } 83415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n")); 834298921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8343ca8062c8SMatthew G. Knepley } 8344ca8062c8SMatthew G. Knepley } 8345ca8062c8SMatthew G. Knepley } 834657beb4faSStefano Zampini if (storagecheck) { 83475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coneSection, &csize)); 83485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(supportSection, &ssize)); 83492c71b3e2SJacob Faibussowitsch PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 835057beb4faSStefano Zampini } 8351ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8352ca8062c8SMatthew G. Knepley } 8353ca8062c8SMatthew G. Knepley 8354412e9a14SMatthew G. Knepley /* 8355412e9a14SMatthew 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. 8356412e9a14SMatthew G. Knepley */ 8357412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8358412e9a14SMatthew G. Knepley { 8359412e9a14SMatthew G. Knepley DMPolytopeType cct; 8360412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8361412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8362412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8363412e9a14SMatthew G. Knepley 8364412e9a14SMatthew G. Knepley PetscFunctionBegin; 8365412e9a14SMatthew G. Knepley *unsplit = 0; 8366412e9a14SMatthew G. Knepley switch (ct) { 8367b5a892a1SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 8368b5a892a1SMatthew G. Knepley ptpoints[npt++] = c; 8369b5a892a1SMatthew G. Knepley break; 8370412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 83715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 83725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize)); 8373412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cone[cp], &cct)); 8375412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8376412e9a14SMatthew G. Knepley } 8377412e9a14SMatthew G. Knepley break; 8378412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8379412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 83805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 83815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize)); 8382412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 83835f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, cone[cp], &ccone)); 83845f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8385412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 83865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8387412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8388412e9a14SMatthew G. Knepley PetscInt p; 8389412e9a14SMatthew G. Knepley for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8390412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8391412e9a14SMatthew G. Knepley } 8392412e9a14SMatthew G. Knepley } 8393412e9a14SMatthew G. Knepley } 8394412e9a14SMatthew G. Knepley break; 8395412e9a14SMatthew G. Knepley default: break; 8396412e9a14SMatthew G. Knepley } 8397412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 83985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8399412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8400412e9a14SMatthew G. Knepley } 8401412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 8402412e9a14SMatthew G. Knepley } 8403412e9a14SMatthew G. Knepley 8404ca8062c8SMatthew G. Knepley /*@ 8405ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8406ca8062c8SMatthew G. Knepley 8407ca8062c8SMatthew G. Knepley Input Parameters: 8408ca8062c8SMatthew G. Knepley + dm - The DMPlex object 840958723a97SMatthew G. Knepley - cellHeight - Normally 0 8410ca8062c8SMatthew G. Knepley 841195eb5ee5SVaclav Hapla Notes: 841295eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 841325c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 8414ca8062c8SMatthew G. Knepley 841595eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 841695eb5ee5SVaclav Hapla 8417ca8062c8SMatthew G. Knepley Level: developer 8418ca8062c8SMatthew G. Knepley 841995eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 8420ca8062c8SMatthew G. Knepley @*/ 842125c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8422ca8062c8SMatthew G. Knepley { 8423412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 8424412e9a14SMatthew G. Knepley DMPolytopeType ct; 8425412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 8426ca8062c8SMatthew G. Knepley 8427ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8428ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated(dm, &interp)); 84305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 84315f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8432412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8433412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 8434412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 843558723a97SMatthew G. Knepley 84365f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, c, &ct)); 84372c71b3e2SJacob Faibussowitsch PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8438412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 8439412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 84405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize)); 84412c71b3e2SJacob Faibussowitsch PetscCheckFalse(coneSize != DMPolytopeTypeGetConeSize(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has cone size %D != %D", c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct)); 8442412e9a14SMatthew G. Knepley } 84435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 844458723a97SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 844558723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 8446412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 844758723a97SMatthew G. Knepley } 84485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8449412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 8450412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8451412e9a14SMatthew G. Knepley PetscInt unsplit; 845242363296SMatthew G. Knepley 84535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8454412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 845542363296SMatthew G. Knepley } 84562c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nv != DMPolytopeTypeGetNumVertices(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D vertices != %D", c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct)); 845742363296SMatthew G. Knepley } 8458ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 8459ca8062c8SMatthew G. Knepley } 84609bf0dad6SMatthew G. Knepley 84619bf0dad6SMatthew G. Knepley /*@ 84629bf0dad6SMatthew 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 84639bf0dad6SMatthew G. Knepley 8464899ea2b8SJacob Faibussowitsch Not Collective 8465899ea2b8SJacob Faibussowitsch 84669bf0dad6SMatthew G. Knepley Input Parameters: 84679bf0dad6SMatthew G. Knepley + dm - The DMPlex object 84689bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 84699bf0dad6SMatthew G. Knepley 847045da879fSVaclav Hapla Notes: 847145da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 847245da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 847345da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 847445da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 84759bf0dad6SMatthew G. Knepley 847695eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 847795eb5ee5SVaclav Hapla 84789bf0dad6SMatthew G. Knepley Level: developer 84799bf0dad6SMatthew G. Knepley 848095eb5ee5SVaclav Hapla .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 84819bf0dad6SMatthew G. Knepley @*/ 848225c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 84839bf0dad6SMatthew G. Knepley { 8484ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8485899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 84869bf0dad6SMatthew G. Knepley 84879bf0dad6SMatthew G. Knepley PetscFunctionBegin; 84889bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated(dm, &interpEnum)); 849045da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 849145da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8492899ea2b8SJacob Faibussowitsch PetscMPIInt rank; 8493899ea2b8SJacob Faibussowitsch MPI_Comm comm; 8494899ea2b8SJacob Faibussowitsch 84955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 84965f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 849798921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8498899ea2b8SJacob Faibussowitsch } 8499899ea2b8SJacob Faibussowitsch 85005f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 85015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 85025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 8503ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 85045f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 85053554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8506412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 8507412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 8508ba2698f1SMatthew G. Knepley DMPolytopeType ct; 8509412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 8510412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 85119bf0dad6SMatthew G. Knepley 85125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, c, &ct)); 85135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8514412e9a14SMatthew G. Knepley if (unsplit) continue; 85155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize)); 85165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 85175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, c, &ornt)); 85185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85199bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 85209bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 85219bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 85229bf0dad6SMatthew G. Knepley } 85235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 85242c71b3e2SJacob Faibussowitsch PetscCheckFalse(coneSize != numFaces,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D faces but should have %D", c, DMPolytopeTypes[ct], coneSize, numFaces); 85259bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 8526d4961f80SStefano Zampini DMPolytopeType fct; 85279bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 85289bf0dad6SMatthew G. Knepley 85295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, cone[f], &fct)); 85305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 85319bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize*2; cl += 2) { 85329bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 85339bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 85349bf0dad6SMatthew G. Knepley } 85352c71b3e2SJacob Faibussowitsch PetscCheckFalse(fnumCorners != faceSizes[f],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %D) of cell %D of type %s has %D vertices but should have %D", cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], fnumCorners, faceSizes[f]); 85369bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 8537b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff+v]) { 8538b5a892a1SMatthew G. Knepley PetscInt v1; 8539b5a892a1SMatthew G. Knepley 85405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 85415f80ce2aSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) CHKERRQ(PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1])); 85425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 85435f80ce2aSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) CHKERRQ(PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1])); 85445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n")); 854598921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %d, ornt %D) of cell %D of type %s vertex %D, %D != %D", cone[f], DMPolytopeTypes[fct], f, ornt[f], c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff+v]); 8546b5a892a1SMatthew G. Knepley } 85479bf0dad6SMatthew G. Knepley } 85485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 8549412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 85509bf0dad6SMatthew G. Knepley } 85515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 85525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 85539bf0dad6SMatthew G. Knepley } 85543554e41dSMatthew G. Knepley } 8555552f7358SJed Brown PetscFunctionReturn(0); 8556552f7358SJed Brown } 85573913d7c8SMatthew G. Knepley 8558bb6a34a8SMatthew G. Knepley /*@ 8559bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 8560bb6a34a8SMatthew G. Knepley 8561bb6a34a8SMatthew G. Knepley Input Parameter: 8562bb6a34a8SMatthew G. Knepley . dm - The DMPlex object 8563bb6a34a8SMatthew G. Knepley 856495eb5ee5SVaclav Hapla Notes: 856595eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 856695eb5ee5SVaclav Hapla 856795eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8568bb6a34a8SMatthew G. Knepley 8569bb6a34a8SMatthew G. Knepley Level: developer 8570bb6a34a8SMatthew G. Knepley 857195eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 8572bb6a34a8SMatthew G. Knepley @*/ 8573bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm) 8574bb6a34a8SMatthew G. Knepley { 8575a2a9e04cSMatthew G. Knepley Vec coordinates; 8576bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 8577bb6a34a8SMatthew G. Knepley PetscReal vol; 8578412e9a14SMatthew G. Knepley PetscBool periodic; 857951a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 8580bb6a34a8SMatthew G. Knepley 8581bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 85825f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 85835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &dE)); 858451a74b61SMatthew G. Knepley if (dim != dE) PetscFunctionReturn(0); 85855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 85865f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL)); 8587bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 85885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8589a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 85905f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates)); 8591412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 8592412e9a14SMatthew G. Knepley DMPolytopeType ct; 8593412e9a14SMatthew G. Knepley PetscInt unsplit; 8594412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 8595412e9a14SMatthew G. Knepley 85965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, c, &ct)); 8597412e9a14SMatthew G. Knepley switch (ct) { 8598412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 8599412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8600412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8601412e9a14SMatthew G. Knepley ignoreZeroVol = PETSC_TRUE; break; 8602412e9a14SMatthew G. Knepley default: break; 8603412e9a14SMatthew G. Knepley } 8604412e9a14SMatthew G. Knepley switch (ct) { 8605412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 8606412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8607412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8608a2a9e04cSMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 8609412e9a14SMatthew G. Knepley continue; 8610412e9a14SMatthew G. Knepley default: break; 8611412e9a14SMatthew G. Knepley } 86125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 8613412e9a14SMatthew G. Knepley if (unsplit) continue; 86145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 86152c71b3e2SJacob Faibussowitsch PetscCheckFalse(detJ < -PETSC_SMALL || (detJ <= 0.0 && !ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double) detJ); 86165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol)); 8617412e9a14SMatthew G. Knepley if (depth > 1 && !periodic) { 86185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 86192c71b3e2SJacob Faibussowitsch PetscCheckFalse(vol < -PETSC_SMALL || (vol <= 0.0 && !ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double) vol); 86205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol)); 8621bb6a34a8SMatthew G. Knepley } 8622bb6a34a8SMatthew G. Knepley } 8623bb6a34a8SMatthew G. Knepley PetscFunctionReturn(0); 8624bb6a34a8SMatthew G. Knepley } 8625bb6a34a8SMatthew G. Knepley 862603da9461SVaclav Hapla /*@ 8627e83a0d2dSVaclav Hapla DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 862803da9461SVaclav Hapla 862903da9461SVaclav Hapla Input Parameters: 863003da9461SVaclav Hapla . dm - The DMPlex object 863103da9461SVaclav Hapla 8632e83a0d2dSVaclav Hapla Notes: 8633e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 86348918e3e2SVaclav Hapla It currently checks only meshes with no partition overlapping. 863503da9461SVaclav Hapla 863695eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 863795eb5ee5SVaclav Hapla 863803da9461SVaclav Hapla Level: developer 863903da9461SVaclav Hapla 864095eb5ee5SVaclav Hapla .seealso: DMGetPointSF(), DMSetFromOptions() 864103da9461SVaclav Hapla @*/ 864203da9461SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm) 864303da9461SVaclav Hapla { 8644f0cfc026SVaclav Hapla PetscSF pointSF; 8645f5869d18SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8646f5869d18SMatthew G. Knepley const PetscInt *locals, *rootdegree; 8647f0cfc026SVaclav Hapla PetscBool distributed; 864803da9461SVaclav Hapla 864903da9461SVaclav Hapla PetscFunctionBegin; 865003da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86515f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &pointSF)); 86525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsDistributed(dm, &distributed)); 8653f0cfc026SVaclav Hapla if (!distributed) PetscFunctionReturn(0); 86545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetOverlap(dm, &overlap)); 8655f0cfc026SVaclav Hapla if (overlap) { 86565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping")); 86578918e3e2SVaclav Hapla PetscFunctionReturn(0); 86588918e3e2SVaclav Hapla } 865928b400f6SJacob Faibussowitsch PetscCheck(pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 86605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL)); 86612c71b3e2SJacob Faibussowitsch PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 86625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 86635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 866403da9461SVaclav Hapla 8665ece87651SVaclav Hapla /* 1) check there are no faces in 2D, cells in 3D, in interface */ 86665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight)); 86675f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 8668f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 8669f5869d18SMatthew G. Knepley const PetscInt point = locals[l]; 8670f5869d18SMatthew G. Knepley 86712c71b3e2SJacob Faibussowitsch PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 867203da9461SVaclav Hapla } 8673ece87651SVaclav Hapla 8674f5869d18SMatthew G. Knepley /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8675f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 8676f5869d18SMatthew G. Knepley const PetscInt point = locals[l]; 8677f5869d18SMatthew G. Knepley const PetscInt *cone; 8678f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 8679f5869d18SMatthew G. Knepley 86805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, point, &coneSize)); 86815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, point, &cone)); 8682f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8683f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 86845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(cone[c], nleaves, locals, &idx)); 86852c71b3e2SJacob Faibussowitsch PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8686f5869d18SMatthew G. Knepley } 8687f5869d18SMatthew G. Knepley } 8688ece87651SVaclav Hapla } 868903da9461SVaclav Hapla PetscFunctionReturn(0); 869003da9461SVaclav Hapla } 869103da9461SVaclav Hapla 8692b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8693b5a892a1SMatthew G. Knepley { 8694b5a892a1SMatthew G. Knepley PetscFunctionBegin; 86955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCheckSymmetry(dm)); 86965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCheckSkeleton(dm, cellHeight)); 86975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCheckFaces(dm, cellHeight)); 86985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCheckGeometry(dm)); 86995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCheckPointSF(dm)); 87005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCheckInterfaceCones(dm)); 8701b5a892a1SMatthew G. Knepley PetscFunctionReturn(0); 8702b5a892a1SMatthew G. Knepley } 8703b5a892a1SMatthew G. Knepley 8704068a5610SStefano Zampini typedef struct cell_stats 8705068a5610SStefano Zampini { 8706068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 8707068a5610SStefano Zampini PetscInt count; 8708068a5610SStefano Zampini } cell_stats_t; 8709068a5610SStefano Zampini 871025befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8711068a5610SStefano Zampini { 8712068a5610SStefano Zampini PetscInt i, N = *len; 8713068a5610SStefano Zampini 8714068a5610SStefano Zampini for (i = 0; i < N; i++) { 8715068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *) a; 8716068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *) b; 8717068a5610SStefano Zampini 8718068a5610SStefano Zampini B->min = PetscMin(A->min,B->min); 8719068a5610SStefano Zampini B->max = PetscMax(A->max,B->max); 8720068a5610SStefano Zampini B->sum += A->sum; 8721068a5610SStefano Zampini B->squaresum += A->squaresum; 8722068a5610SStefano Zampini B->count += A->count; 8723068a5610SStefano Zampini } 8724068a5610SStefano Zampini } 8725068a5610SStefano Zampini 8726068a5610SStefano Zampini /*@ 872743fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8728068a5610SStefano Zampini 87298261a58bSMatthew G. Knepley Collective on dm 87308261a58bSMatthew G. Knepley 8731068a5610SStefano Zampini Input Parameters: 8732068a5610SStefano Zampini + dm - The DMPlex object 873343fa8764SMatthew G. Knepley . output - If true, statistics will be displayed on stdout 873443fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8735068a5610SStefano Zampini 873695eb5ee5SVaclav Hapla Notes: 873795eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 873895eb5ee5SVaclav Hapla 873995eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8740068a5610SStefano Zampini 8741068a5610SStefano Zampini Level: developer 8742068a5610SStefano Zampini 8743f108dbd7SJacob Faibussowitsch .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8744068a5610SStefano Zampini @*/ 874543fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8746068a5610SStefano Zampini { 8747068a5610SStefano Zampini DM dmCoarse; 874843fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 874943fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 875043fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 875143fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8752412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 875343fa8764SMatthew G. Knepley PetscMPIInt rank,size; 8754068a5610SStefano Zampini 8755068a5610SStefano Zampini PetscFunctionBegin; 8756068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8757068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 8758068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 8759068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 8760068a5610SStefano Zampini stats.count = 0; 8761068a5610SStefano Zampini 87625f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 87635f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 87645f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm,&cdim)); 87655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 87665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd)); 87675f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd)); 8768412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 8769068a5610SStefano Zampini PetscInt i; 8770068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8771068a5610SStefano Zampini 87725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ)); 87732c71b3e2SJacob Faibussowitsch PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 877443fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 8775068a5610SStefano Zampini frobJ += J[i] * J[i]; 8776068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 8777068a5610SStefano Zampini } 8778068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 8779068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 8780068a5610SStefano Zampini 8781068a5610SStefano Zampini stats.min = PetscMin(stats.min,cond); 8782068a5610SStefano Zampini stats.max = PetscMax(stats.max,cond); 8783068a5610SStefano Zampini stats.sum += cond; 8784068a5610SStefano Zampini stats.squaresum += cond2; 8785068a5610SStefano Zampini stats.count++; 87868261a58bSMatthew G. Knepley if (output && cond > limit) { 878743fa8764SMatthew G. Knepley PetscSection coordSection; 878843fa8764SMatthew G. Knepley Vec coordsLocal; 878943fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 879043fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 879143fa8764SMatthew G. Knepley 87925f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordsLocal)); 87935f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 87945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 87955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond)); 879643fa8764SMatthew G. Knepley for (i = 0; i < Nv/cdim; ++i) { 87975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, " Vertex %D: (", i)); 879843fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 87995f80ce2aSJacob Faibussowitsch if (d > 0) CHKERRQ(PetscSynchronizedPrintf(comm, ", ")); 88005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]))); 880143fa8764SMatthew G. Knepley } 88025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, ")\n")); 880343fa8764SMatthew G. Knepley } 88045f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 880543fa8764SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) { 880643fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 880743fa8764SMatthew G. Knepley 880843fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 880943fa8764SMatthew G. Knepley PetscReal len; 881043fa8764SMatthew G. Knepley 88115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 88125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len)); 881343fa8764SMatthew G. Knepley } 881443fa8764SMatthew G. Knepley } 88155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 88165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 881743fa8764SMatthew G. Knepley } 8818068a5610SStefano Zampini } 88195f80ce2aSJacob Faibussowitsch if (output) CHKERRQ(PetscSynchronizedFlush(comm, NULL)); 8820068a5610SStefano Zampini 8821068a5610SStefano Zampini if (size > 1) { 8822068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4,1}; 8823068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8824068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8825068a5610SStefano Zampini MPI_Op statReduce; 8826068a5610SStefano Zampini 88275f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType)); 88285f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_commit(&statType)); 88295f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 88305f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm)); 88315f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Op_free(&statReduce)); 88325f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_free(&statType)); 8833068a5610SStefano Zampini } else { 88345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&globalStats,&stats,1)); 8835068a5610SStefano Zampini } 8836dd400576SPatrick Sanan if (rank == 0) { 8837068a5610SStefano Zampini count = globalStats.count; 8838068a5610SStefano Zampini min = globalStats.min; 8839068a5610SStefano Zampini max = globalStats.max; 8840068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 8841068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8842068a5610SStefano Zampini } 8843068a5610SStefano Zampini 8844068a5610SStefano Zampini if (output) { 88455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm,"Mesh with %D cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double) min, (double) max, (double) mean, (double) stdev)); 8846068a5610SStefano Zampini } 88475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(J,invJ)); 8848068a5610SStefano Zampini 88495f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(dm,&dmCoarse)); 8850068a5610SStefano Zampini if (dmCoarse) { 8851068a5610SStefano Zampini PetscBool isplex; 8852068a5610SStefano Zampini 88535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex)); 8854068a5610SStefano Zampini if (isplex) { 88555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCheckCellShape(dmCoarse,output,condLimit)); 8856068a5610SStefano Zampini } 8857068a5610SStefano Zampini } 8858068a5610SStefano Zampini PetscFunctionReturn(0); 8859068a5610SStefano Zampini } 8860068a5610SStefano Zampini 8861f108dbd7SJacob Faibussowitsch /*@ 8862f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8863f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 8864f108dbd7SJacob Faibussowitsch 88656ed19f2fSJacob Faibussowitsch Collective on dm 8866f108dbd7SJacob Faibussowitsch 8867f108dbd7SJacob Faibussowitsch Input Parameters: 8868f108dbd7SJacob Faibussowitsch + dm - The DMPlex object 8869f108dbd7SJacob Faibussowitsch . fv - Optional PetscFV object for pre-computed cell/face centroid information 8870f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 8871f108dbd7SJacob Faibussowitsch 8872f108dbd7SJacob Faibussowitsch Output Parameters: 8873f108dbd7SJacob Faibussowitsch + OrthQual - Vec containing orthogonal quality per cell 8874f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8875f108dbd7SJacob Faibussowitsch 8876f108dbd7SJacob Faibussowitsch Options Database Keys: 8877f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8878f108dbd7SJacob Faibussowitsch supported. 8879f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8880f108dbd7SJacob Faibussowitsch 8881f108dbd7SJacob Faibussowitsch Notes: 8882f108dbd7SJacob Faibussowitsch Orthogonal quality is given by the following formula: 8883f108dbd7SJacob Faibussowitsch 8884f108dbd7SJacob Faibussowitsch \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8885f108dbd7SJacob Faibussowitsch 8886f108dbd7SJacob 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 8887f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8888f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8889f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 8890f108dbd7SJacob Faibussowitsch 8891f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 8892f108dbd7SJacob Faibussowitsch 8893f108dbd7SJacob Faibussowitsch This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8894f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8895f108dbd7SJacob Faibussowitsch 8896f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8897f108dbd7SJacob Faibussowitsch 8898f108dbd7SJacob Faibussowitsch Level: intermediate 8899f108dbd7SJacob Faibussowitsch 8900f108dbd7SJacob Faibussowitsch .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8901f108dbd7SJacob Faibussowitsch @*/ 8902f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8903f108dbd7SJacob Faibussowitsch { 89046ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 89056ed19f2fSJacob Faibussowitsch PetscInt *idx; 89066ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 8907f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 89086ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 8909f108dbd7SJacob Faibussowitsch MPI_Comm comm; 8910f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 8911f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 8912f108dbd7SJacob Faibussowitsch IS glob; 8913f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 8914f108dbd7SJacob Faibussowitsch PetscViewer vwr; 8915f108dbd7SJacob Faibussowitsch 8916f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 8917f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89186ed19f2fSJacob Faibussowitsch if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8919f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQual, 4); 89206bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 89215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 89225f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &nc)); 89232c71b3e2SJacob Faibussowitsch PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 89246ed19f2fSJacob Faibussowitsch { 89256ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 89266ed19f2fSJacob Faibussowitsch 89275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated(dm, &interpFlag)); 8928f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8929f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 8930f108dbd7SJacob Faibussowitsch 89315f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 893298921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8933f108dbd7SJacob Faibussowitsch } 89346ed19f2fSJacob Faibussowitsch } 8935f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 8936f108dbd7SJacob Faibussowitsch PetscValidPointer(OrthQualLabel, 5); 89375f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "Orthogonal_Quality")); 89385f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 89396ed19f2fSJacob Faibussowitsch } else {*OrthQualLabel = NULL;} 89405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight)); 89415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 89425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 89435f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(glob, <og)); 89445f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 89455f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(comm, OrthQual)); 89465f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(*OrthQual, VECSTANDARD)); 89475f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE)); 89485f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 89495f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetUp(*OrthQual)); 89505f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&glob)); 89515f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(<og)); 89525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 89535f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(cellgeom, &cellGeomArr)); 89545f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(facegeom, &faceGeomArr)); 89555f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(cellgeom, &dmCell)); 89565f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(facegeom, &dmFace)); 89575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 89586ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++,cell++) { 89596ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8960f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 8961f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 8962898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 8963f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 8964f108dbd7SJacob Faibussowitsch 89656ed19f2fSJacob Faibussowitsch idx[cellIter] = cell-cStart; 8966f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 8967f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 89685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 89695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 8970f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 89715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 89726ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 89736ed19f2fSJacob Faibussowitsch PetscInt i; 89746ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 8975f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 8976f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 8977f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 8978f108dbd7SJacob Faibussowitsch 8979f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 8980f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 89815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 8982f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 89836ed19f2fSJacob Faibussowitsch { 89846ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 89856ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 89866ed19f2fSJacob Faibussowitsch 89875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 89885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 89895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 89906ed19f2fSJacob Faibussowitsch } 8991f108dbd7SJacob Faibussowitsch 8992f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 8993f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 8994f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8995f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 8996f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 8997addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 8998addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 8999addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9000f108dbd7SJacob Faibussowitsch } 9001addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9002addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9003addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9004f108dbd7SJacob Faibussowitsch 9005f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9006f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9007f108dbd7SJacob Faibussowitsch ci[i] = ci[i]/normci; 9008f108dbd7SJacob Faibussowitsch fi[i] = fi[i]/normfi; 9009f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i]/normai; 9010f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9011f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9012f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9013f108dbd7SJacob Faibussowitsch } 9014f108dbd7SJacob Faibussowitsch if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9015f108dbd7SJacob Faibussowitsch minvalc = PetscRealPart(cArr[cellneighiter]); 9016f108dbd7SJacob Faibussowitsch } 9017f108dbd7SJacob Faibussowitsch if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9018f108dbd7SJacob Faibussowitsch minvalf = PetscRealPart(fArr[cellneighiter]); 9019f108dbd7SJacob Faibussowitsch } 9020f108dbd7SJacob Faibussowitsch } 90215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adj)); 90225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(cArr, fArr)); 9023f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 90246ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9025f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 90265f80ce2aSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) CHKERRQ(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9027f108dbd7SJacob Faibussowitsch } 9028f108dbd7SJacob Faibussowitsch } 90295f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES)); 90305f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(*OrthQual)); 90315f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(*OrthQual)); 90325f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 90335f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(facegeom, &faceGeomArr)); 90345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9035f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 90365f80ce2aSJacob Faibussowitsch if (vwr) CHKERRQ(DMLabelView(*OrthQualLabel, vwr)); 9037f108dbd7SJacob Faibussowitsch } 90385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree5(idx, oqVals, ci, fi, Ai)); 90395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&vwr)); 90405f80ce2aSJacob Faibussowitsch CHKERRQ(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 9041f108dbd7SJacob Faibussowitsch PetscFunctionReturn(0); 9042f108dbd7SJacob Faibussowitsch } 9043f108dbd7SJacob Faibussowitsch 90441eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 90451eb70e55SToby Isaac * interpolator construction */ 90461eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 90471eb70e55SToby Isaac { 90481eb70e55SToby Isaac PetscSection section, newSection, gsection; 90491eb70e55SToby Isaac PetscSF sf; 90501eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 90511eb70e55SToby Isaac 90521eb70e55SToby Isaac PetscFunctionBegin; 90531eb70e55SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 90541eb70e55SToby Isaac PetscValidPointer(odm,2); 90555f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm, §ion)); 90565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionHasConstraints(section, &hasConstraints)); 90575f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm))); 90581eb70e55SToby Isaac if (!ghasConstraints) { 90595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)dm)); 90601eb70e55SToby Isaac *odm = dm; 90611eb70e55SToby Isaac PetscFunctionReturn(0); 90621eb70e55SToby Isaac } 90635f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dm, odm)); 90645f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyFields(dm, *odm)); 90655f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(*odm, &newSection)); 90665f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(*odm, &sf)); 90675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 90685f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetGlobalSection(*odm, gsection)); 90695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&gsection)); 90701eb70e55SToby Isaac PetscFunctionReturn(0); 90711eb70e55SToby Isaac } 90721eb70e55SToby Isaac 90731eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 90741eb70e55SToby Isaac { 90751eb70e55SToby Isaac DM dmco, dmfo; 90761eb70e55SToby Isaac Mat interpo; 90771eb70e55SToby Isaac Vec rscale; 90781eb70e55SToby Isaac Vec cglobalo, clocal; 90791eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 90801eb70e55SToby Isaac PetscBool regular; 90811eb70e55SToby Isaac 90821eb70e55SToby Isaac PetscFunctionBegin; 90835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetFullDM(dmc, &dmco)); 90845f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetFullDM(dmf, &dmfo)); 90855f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dmfo, dmco)); 90865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRegularRefinement(dmf, ®ular)); 90875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRegularRefinement(dmfo, regular)); 90885f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 90895f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dmco, &cglobalo)); 90905f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector(dmc, &clocal)); 90915f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(cglobalo, 0.)); 90925f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(clocal, 0.)); 90935f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dmf, &fglobal)); 90945f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dmfo, &fglobalo)); 90955f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector(dmf, &flocal)); 90965f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(fglobal, 0.)); 90975f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(fglobalo, 0.)); 90985f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(flocal, 0.)); 90995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 91005f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 91015f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 91025f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(interpo, cglobalo, fglobalo)); 91035f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 91045f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 91055f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 91065f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 91071eb70e55SToby Isaac *shift = fglobal; 91085f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&flocal)); 91095f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&fglobalo)); 91105f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&clocal)); 91115f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&cglobalo)); 91125f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&rscale)); 91135f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&interpo)); 91145f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dmfo)); 91155f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dmco)); 91161eb70e55SToby Isaac PetscFunctionReturn(0); 91171eb70e55SToby Isaac } 91181eb70e55SToby Isaac 91191eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 91201eb70e55SToby Isaac { 91211eb70e55SToby Isaac PetscObject shifto; 91221eb70e55SToby Isaac Vec shift; 91231eb70e55SToby Isaac 91241eb70e55SToby Isaac PetscFunctionBegin; 91251eb70e55SToby Isaac if (!interp) { 91261eb70e55SToby Isaac Vec rscale; 91271eb70e55SToby Isaac 91285f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 91295f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&rscale)); 91301eb70e55SToby Isaac } else { 91315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)interp)); 91321eb70e55SToby Isaac } 91335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 91341eb70e55SToby Isaac if (!shifto) { 91355f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 91365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift)); 91371eb70e55SToby Isaac shifto = (PetscObject) shift; 91385f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&shift)); 91391eb70e55SToby Isaac } 91401eb70e55SToby Isaac shift = (Vec) shifto; 91415f80ce2aSJacob Faibussowitsch CHKERRQ(MatInterpolate(interp, coarseSol, fineSol)); 91425f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(fineSol, 1.0, shift)); 91435f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&interp)); 91441eb70e55SToby Isaac PetscFunctionReturn(0); 91451eb70e55SToby Isaac } 91461eb70e55SToby Isaac 9147bceba477SMatthew G. Knepley /* Pointwise interpolation 9148bceba477SMatthew G. Knepley Just code FEM for now 9149bceba477SMatthew G. Knepley u^f = I u^c 91504ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 91514ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 91524ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9153bceba477SMatthew G. Knepley */ 9154bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9155bceba477SMatthew G. Knepley { 9156bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9157bceba477SMatthew G. Knepley PetscInt m, n; 9158a063dac3SMatthew G. Knepley void *ctx; 915968132eb9SMatthew G. Knepley DM cdm; 9160cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9161bceba477SMatthew G. Knepley 9162bceba477SMatthew G. Knepley PetscFunctionBegin; 91635f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(dmFine, &gsf)); 91645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstrainedStorageSize(gsf, &m)); 91655f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(dmCoarse, &gsc)); 91665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstrainedStorageSize(gsc, &n)); 916768132eb9SMatthew G. Knepley 91685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 91695f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation)); 91705f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 91715f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 91725f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetApplicationContext(dmFine, &ctx)); 917368132eb9SMatthew G. Knepley 91745f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(dmFine, &cdm)); 91755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRegularRefinement(dmFine, ®ular)); 91765f80ce2aSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) CHKERRQ(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 91775f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 91785f80ce2aSJacob Faibussowitsch CHKERRQ(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 91794db47ee9SStefano Zampini if (scaling) { 91805d1c2e58SMatthew G. Knepley /* Use naive scaling */ 91815f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 91824db47ee9SStefano Zampini } 9183a063dac3SMatthew G. Knepley PetscFunctionReturn(0); 9184a063dac3SMatthew G. Knepley } 9185bceba477SMatthew G. Knepley 91866dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9187a063dac3SMatthew G. Knepley { 91886dbf9973SLawrence Mitchell VecScatter ctx; 918990748bafSMatthew G. Knepley 9190a063dac3SMatthew G. Knepley PetscFunctionBegin; 91915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 91925f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 91935f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&ctx)); 9194bceba477SMatthew G. Knepley PetscFunctionReturn(0); 9195bceba477SMatthew G. Knepley } 9196bceba477SMatthew G. Knepley 91973e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 91983e9753d6SMatthew G. Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 91993e9753d6SMatthew G. Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 92003e9753d6SMatthew G. Knepley PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 92013e9753d6SMatthew G. Knepley { 920200635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 920300635df3SMatthew G. Knepley PetscInt c; 920400635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 92053e9753d6SMatthew G. Knepley } 92063e9753d6SMatthew G. Knepley 9207b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9208b4937a87SMatthew G. Knepley { 9209b4937a87SMatthew G. Knepley DM dmc; 9210b4937a87SMatthew G. Knepley PetscDS ds; 9211b4937a87SMatthew G. Knepley Vec ones, locmass; 9212b4937a87SMatthew G. Knepley IS cellIS; 9213b4937a87SMatthew G. Knepley PetscFormKey key; 9214b4937a87SMatthew G. Knepley PetscInt depth; 9215b4937a87SMatthew G. Knepley 9216b4937a87SMatthew G. Knepley PetscFunctionBegin; 92175f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dm, &dmc)); 92185f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(dm, dmc)); 92195f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dmc, &ds)); 92205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92215f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dmc, mass)); 92225f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(dmc, &ones)); 92235f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(dmc, &locmass)); 92245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dmc, &depth)); 92255f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 92265f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(locmass, 0.0)); 92275f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(ones, 1.0)); 9228b4937a87SMatthew G. Knepley key.label = NULL; 9229b4937a87SMatthew G. Knepley key.value = 0; 9230b4937a87SMatthew G. Knepley key.field = 0; 9231b4937a87SMatthew G. Knepley key.part = 0; 92325f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 92335f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellIS)); 92345f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(*mass, 0.0)); 92355f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 92365f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 92375f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(dmc, &ones)); 92385f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(dmc, &locmass)); 92395f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dmc)); 9240b4937a87SMatthew G. Knepley PetscFunctionReturn(0); 9241b4937a87SMatthew G. Knepley } 9242b4937a87SMatthew G. Knepley 9243bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9244bd041c0cSMatthew G. Knepley { 9245bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9246bd041c0cSMatthew G. Knepley PetscInt m, n; 9247bd041c0cSMatthew G. Knepley void *ctx; 9248bd041c0cSMatthew G. Knepley DM cdm; 9249bd041c0cSMatthew G. Knepley PetscBool regular; 9250bd041c0cSMatthew G. Knepley 9251bd041c0cSMatthew G. Knepley PetscFunctionBegin; 92523e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 92533e9753d6SMatthew G. Knepley DM dmc; 92543e9753d6SMatthew G. Knepley PetscDS ds; 9255b4937a87SMatthew G. Knepley PetscWeakForm wf; 92563e9753d6SMatthew G. Knepley Vec u; 92573e9753d6SMatthew G. Knepley IS cellIS; 925806ad1575SMatthew G. Knepley PetscFormKey key; 92593e9753d6SMatthew G. Knepley PetscInt depth; 92603e9753d6SMatthew G. Knepley 92615f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dmFine, &dmc)); 92625f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(dmFine, dmc)); 92635f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dmc, &ds)); 92645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetWeakForm(ds, &wf)); 92655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscWeakFormClear(wf)); 92665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 92675f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateMatrix(dmc, mass)); 92685f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalVector(dmc, &u)); 92695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dmc, &depth)); 92705f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 92715f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(*mass)); 92726528b96dSMatthew G. Knepley key.label = NULL; 92736528b96dSMatthew G. Knepley key.value = 0; 92746528b96dSMatthew G. Knepley key.field = 0; 927506ad1575SMatthew G. Knepley key.part = 0; 92765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 92775f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellIS)); 92785f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreGlobalVector(dmc, &u)); 92795f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dmc)); 92803e9753d6SMatthew G. Knepley } else { 92815f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(dmFine, &gsf)); 92825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstrainedStorageSize(gsf, &m)); 92835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(dmCoarse, &gsc)); 92845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9285bd041c0cSMatthew G. Knepley 92865f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass)); 92875f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 92885f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(*mass, dmCoarse->mattype)); 92895f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetApplicationContext(dmFine, &ctx)); 9290bd041c0cSMatthew G. Knepley 92915f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(dmFine, &cdm)); 92925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRegularRefinement(dmFine, ®ular)); 92935f80ce2aSJacob Faibussowitsch if (regular && cdm == dmCoarse) CHKERRQ(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 92945f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 92953e9753d6SMatthew G. Knepley } 92965f80ce2aSJacob Faibussowitsch CHKERRQ(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 9297bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 9298bd041c0cSMatthew G. Knepley } 9299bd041c0cSMatthew G. Knepley 93000aef6b92SMatthew G. Knepley /*@ 93010aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93020aef6b92SMatthew G. Knepley 93030aef6b92SMatthew G. Knepley Input Parameter: 93040aef6b92SMatthew G. Knepley . dm - The DMPlex object 93050aef6b92SMatthew G. Knepley 93060aef6b92SMatthew G. Knepley Output Parameter: 93070aef6b92SMatthew G. Knepley . regular - The flag 93080aef6b92SMatthew G. Knepley 93090aef6b92SMatthew G. Knepley Level: intermediate 93100aef6b92SMatthew G. Knepley 93110aef6b92SMatthew G. Knepley .seealso: DMPlexSetRegularRefinement() 93120aef6b92SMatthew G. Knepley @*/ 93130aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 93140aef6b92SMatthew G. Knepley { 93150aef6b92SMatthew G. Knepley PetscFunctionBegin; 93160aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9317*dadcf809SJacob Faibussowitsch PetscValidBoolPointer(regular, 2); 93180aef6b92SMatthew G. Knepley *regular = ((DM_Plex *) dm->data)->regularRefinement; 93190aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93200aef6b92SMatthew G. Knepley } 93210aef6b92SMatthew G. Knepley 93220aef6b92SMatthew G. Knepley /*@ 93230aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 93240aef6b92SMatthew G. Knepley 93250aef6b92SMatthew G. Knepley Input Parameters: 93260aef6b92SMatthew G. Knepley + dm - The DMPlex object 93270aef6b92SMatthew G. Knepley - regular - The flag 93280aef6b92SMatthew G. Knepley 93290aef6b92SMatthew G. Knepley Level: intermediate 93300aef6b92SMatthew G. Knepley 93310aef6b92SMatthew G. Knepley .seealso: DMPlexGetRegularRefinement() 93320aef6b92SMatthew G. Knepley @*/ 93330aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 93340aef6b92SMatthew G. Knepley { 93350aef6b92SMatthew G. Knepley PetscFunctionBegin; 93360aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93370aef6b92SMatthew G. Knepley ((DM_Plex *) dm->data)->regularRefinement = regular; 93380aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 93390aef6b92SMatthew G. Knepley } 93400aef6b92SMatthew G. Knepley 9341f7c74593SToby Isaac /* anchors */ 9342a68b90caSToby Isaac /*@ 9343f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9344ebdb1bfaSJed Brown call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9345a68b90caSToby Isaac 9346e228b242SToby Isaac not collective 9347a68b90caSToby Isaac 9348f899ff85SJose E. Roman Input Parameter: 9349a68b90caSToby Isaac . dm - The DMPlex object 9350a68b90caSToby Isaac 9351a68b90caSToby Isaac Output Parameters: 9352a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9353a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9354a68b90caSToby Isaac 9355a68b90caSToby Isaac Level: intermediate 9356a68b90caSToby Isaac 9357ebdb1bfaSJed Brown .seealso: DMPlexSetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9358a68b90caSToby Isaac @*/ 9359a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9360a68b90caSToby Isaac { 9361a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9362a68b90caSToby Isaac 9363a68b90caSToby Isaac PetscFunctionBegin; 9364a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93655f80ce2aSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) CHKERRQ((*plex->createanchors)(dm)); 9366a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 9367a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 9368a68b90caSToby Isaac PetscFunctionReturn(0); 9369a68b90caSToby Isaac } 9370a68b90caSToby Isaac 9371a68b90caSToby Isaac /*@ 9372f7c74593SToby Isaac DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9373f7c74593SToby Isaac when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9374a68b90caSToby Isaac point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9375a68b90caSToby Isaac 9376a17985deSToby Isaac After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9377ebdb1bfaSJed Brown DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9378a68b90caSToby Isaac 9379e228b242SToby Isaac collective on dm 9380a68b90caSToby Isaac 9381a68b90caSToby Isaac Input Parameters: 9382a68b90caSToby Isaac + dm - The DMPlex object 9383e228b242SToby 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). 9384e228b242SToby Isaac - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9385a68b90caSToby Isaac 9386a68b90caSToby Isaac The reference counts of anchorSection and anchorIS are incremented. 9387a68b90caSToby Isaac 9388a68b90caSToby Isaac Level: intermediate 9389a68b90caSToby Isaac 9390ebdb1bfaSJed Brown .seealso: DMPlexGetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9391a68b90caSToby Isaac @*/ 9392a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9393a68b90caSToby Isaac { 9394a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9395e228b242SToby Isaac PetscMPIInt result; 9396a68b90caSToby Isaac 9397a68b90caSToby Isaac PetscFunctionBegin; 9398a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9399e228b242SToby Isaac if (anchorSection) { 9400e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 94015f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result)); 94022c71b3e2SJacob Faibussowitsch PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9403e228b242SToby Isaac } 9404e228b242SToby Isaac if (anchorIS) { 9405e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 94065f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result)); 94072c71b3e2SJacob Faibussowitsch PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9408e228b242SToby Isaac } 9409a68b90caSToby Isaac 94105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)anchorSection)); 94115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&plex->anchorSection)); 9412a68b90caSToby Isaac plex->anchorSection = anchorSection; 9413a68b90caSToby Isaac 94145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)anchorIS)); 94155f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&plex->anchorIS)); 9416a68b90caSToby Isaac plex->anchorIS = anchorIS; 9417a68b90caSToby Isaac 9418cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9419a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 9420a68b90caSToby Isaac const PetscInt *anchors; 9421a68b90caSToby Isaac 94225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 94235f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(anchorIS,&size)); 94245f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(anchorIS,&anchors)); 9425a68b90caSToby Isaac for (a = 0; a < size; a++) { 9426a68b90caSToby Isaac PetscInt p; 9427a68b90caSToby Isaac 9428a68b90caSToby Isaac p = anchors[a]; 9429a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 9430a68b90caSToby Isaac PetscInt dof; 9431a68b90caSToby Isaac 94325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(anchorSection,p,&dof)); 9433a68b90caSToby Isaac if (dof) { 9434a68b90caSToby Isaac 94355f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(anchorIS,&anchors)); 943698921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9437a68b90caSToby Isaac } 9438a68b90caSToby Isaac } 9439a68b90caSToby Isaac } 94405f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(anchorIS,&anchors)); 9441a68b90caSToby Isaac } 9442f7c74593SToby Isaac /* reset the generic constraints */ 94435f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDefaultConstraints(dm,NULL,NULL,NULL)); 9444a68b90caSToby Isaac PetscFunctionReturn(0); 9445a68b90caSToby Isaac } 9446a68b90caSToby Isaac 9447f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9448a68b90caSToby Isaac { 9449f7c74593SToby Isaac PetscSection anchorSection; 94506995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9451a68b90caSToby Isaac 9452a68b90caSToby Isaac PetscFunctionBegin; 9453a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(dm,&anchorSection,NULL)); 94555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF,cSec)); 94565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section,&numFields)); 94576995de1eSToby Isaac if (numFields) { 9458719ab38cSToby Isaac PetscInt f; 94595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(*cSec,numFields)); 9460719ab38cSToby Isaac 9461719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 9462719ab38cSToby Isaac PetscInt numComp; 9463719ab38cSToby Isaac 94645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldComponents(section,f,&numComp)); 94655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(*cSec,f,numComp)); 9466719ab38cSToby Isaac } 94676995de1eSToby Isaac } 94685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(anchorSection,&pStart,&pEnd)); 94695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section,&sStart,&sEnd)); 94706995de1eSToby Isaac pStart = PetscMax(pStart,sStart); 94716995de1eSToby Isaac pEnd = PetscMin(pEnd,sEnd); 94726995de1eSToby Isaac pEnd = PetscMax(pStart,pEnd); 94735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(*cSec,pStart,pEnd)); 9474a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 94755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(anchorSection,p,&dof)); 9476a68b90caSToby Isaac if (dof) { 94775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,p,&dof)); 94785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(*cSec,p,dof)); 9479a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 94805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,p,f,&dof)); 94815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(*cSec,p,f,dof)); 9482a68b90caSToby Isaac } 9483a68b90caSToby Isaac } 9484a68b90caSToby Isaac } 94855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(*cSec)); 94865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *cSec, "Constraint Section")); 9487a68b90caSToby Isaac PetscFunctionReturn(0); 9488a68b90caSToby Isaac } 9489a68b90caSToby Isaac 9490f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9491a68b90caSToby Isaac { 9492f7c74593SToby Isaac PetscSection aSec; 9493ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 94940ac89760SToby Isaac const PetscInt *anchors; 94950ac89760SToby Isaac PetscInt numFields, f; 949666ad2231SToby Isaac IS aIS; 9497e19f7ee6SMark Adams MatType mtype; 9498e19f7ee6SMark Adams PetscBool iscuda,iskokkos; 94990ac89760SToby Isaac 95000ac89760SToby Isaac PetscFunctionBegin; 95010ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(cSec, &m)); 95035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(section, &n)); 95045f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF,cMat)); 95055f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(*cMat,m,n,m,n)); 95065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda)); 95075f80ce2aSJacob Faibussowitsch if (!iscuda) CHKERRQ(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda)); 95085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos)); 95095f80ce2aSJacob Faibussowitsch if (!iskokkos) CHKERRQ(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos)); 9510e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 9511e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9512e19f7ee6SMark Adams else mtype = MATSEQAIJ; 95135f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(*cMat,mtype)); 95145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(dm,&aSec,&aIS)); 95155f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(aIS,&anchors)); 95166995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 95175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(cSec,&pStart,&pEnd)); 95185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section,&sStart,&sEnd)); 95195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(m+1,&i)); 95200ac89760SToby Isaac i[0] = 0; 95215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section,&numFields)); 95220ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 9523f19733c5SToby Isaac PetscInt rDof, rOff, r; 9524f19733c5SToby Isaac 95255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec,p,&rDof)); 9526f19733c5SToby Isaac if (!rDof) continue; 95275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,p,&rOff)); 95280ac89760SToby Isaac if (numFields) { 95290ac89760SToby Isaac for (f = 0; f < numFields; f++) { 95300ac89760SToby Isaac annz = 0; 9531f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 9532f19733c5SToby Isaac a = anchors[rOff + r]; 9533ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,a,f,&aDof)); 95350ac89760SToby Isaac annz += aDof; 95360ac89760SToby Isaac } 95375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSec,p,f,&dof)); 95385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(cSec,p,f,&off)); 95390ac89760SToby Isaac for (q = 0; q < dof; q++) { 95400ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 95410ac89760SToby Isaac } 95420ac89760SToby Isaac } 95432f7452b8SBarry Smith } else { 95440ac89760SToby Isaac annz = 0; 95455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSec,p,&dof)); 95460ac89760SToby Isaac for (q = 0; q < dof; q++) { 9547ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 9548ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,a,&aDof)); 95500ac89760SToby Isaac annz += aDof; 95510ac89760SToby Isaac } 95525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSec,p,&dof)); 95535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(cSec,p,&off)); 95540ac89760SToby Isaac for (q = 0; q < dof; q++) { 95550ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 95560ac89760SToby Isaac } 95570ac89760SToby Isaac } 95580ac89760SToby Isaac } 95590ac89760SToby Isaac nnz = i[m]; 95605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nnz,&j)); 95610ac89760SToby Isaac offset = 0; 95620ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 95630ac89760SToby Isaac if (numFields) { 95640ac89760SToby Isaac for (f = 0; f < numFields; f++) { 95655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSec,p,f,&dof)); 95660ac89760SToby Isaac for (q = 0; q < dof; q++) { 95670ac89760SToby Isaac PetscInt rDof, rOff, r; 95685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec,p,&rDof)); 95695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,p,&rOff)); 95700ac89760SToby Isaac for (r = 0; r < rDof; r++) { 95710ac89760SToby Isaac PetscInt s; 95720ac89760SToby Isaac 95730ac89760SToby Isaac a = anchors[rOff + r]; 9574ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,a,f,&aDof)); 95765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(section,a,f,&aOff)); 95770ac89760SToby Isaac for (s = 0; s < aDof; s++) { 95780ac89760SToby Isaac j[offset++] = aOff + s; 95790ac89760SToby Isaac } 95800ac89760SToby Isaac } 95810ac89760SToby Isaac } 95820ac89760SToby Isaac } 95832f7452b8SBarry Smith } else { 95845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSec,p,&dof)); 95850ac89760SToby Isaac for (q = 0; q < dof; q++) { 95860ac89760SToby Isaac PetscInt rDof, rOff, r; 95875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec,p,&rDof)); 95885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,p,&rOff)); 95890ac89760SToby Isaac for (r = 0; r < rDof; r++) { 95900ac89760SToby Isaac PetscInt s; 95910ac89760SToby Isaac 95920ac89760SToby Isaac a = anchors[rOff + r]; 9593ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 95945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,a,&aDof)); 95955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section,a,&aOff)); 95960ac89760SToby Isaac for (s = 0; s < aDof; s++) { 95970ac89760SToby Isaac j[offset++] = aOff + s; 95980ac89760SToby Isaac } 95990ac89760SToby Isaac } 96000ac89760SToby Isaac } 96010ac89760SToby Isaac } 96020ac89760SToby Isaac } 96035f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL)); 96045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(i)); 96055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(j)); 96065f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(aIS,&anchors)); 96070ac89760SToby Isaac PetscFunctionReturn(0); 96080ac89760SToby Isaac } 96090ac89760SToby Isaac 961066ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 961166ad2231SToby Isaac { 9612f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 9613f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 961466ad2231SToby Isaac Mat cMat; 961566ad2231SToby Isaac 961666ad2231SToby Isaac PetscFunctionBegin; 961766ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 96185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(dm,&anchorSection,NULL)); 961966ad2231SToby Isaac if (anchorSection) { 962044a7f3ddSMatthew G. Knepley PetscInt Nf; 9621e228b242SToby Isaac 96225f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm,§ion)); 96235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec)); 96245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat)); 96255f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumFields(dm,&Nf)); 96265f80ce2aSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) CHKERRQ((*plex->computeanchormatrix)(dm,section,cSec,cMat)); 96275f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDefaultConstraints(dm,cSec,cMat,NULL)); 96285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&cSec)); 96295f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&cMat)); 963066ad2231SToby Isaac } 963166ad2231SToby Isaac PetscFunctionReturn(0); 963266ad2231SToby Isaac } 9633a93c429eSMatthew G. Knepley 9634a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9635a93c429eSMatthew G. Knepley { 9636a93c429eSMatthew G. Knepley IS subis; 9637a93c429eSMatthew G. Knepley PetscSection section, subsection; 9638a93c429eSMatthew G. Knepley 9639a93c429eSMatthew G. Knepley PetscFunctionBegin; 96405f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm, §ion)); 964128b400f6SJacob Faibussowitsch PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 964228b400f6SJacob Faibussowitsch PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9643a93c429eSMatthew G. Knepley /* Create subdomain */ 96445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexFilter(dm, label, value, subdm)); 9645a93c429eSMatthew G. Knepley /* Create submodel */ 96465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSubpointIS(*subdm, &subis)); 96475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 96485f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLocalSection(*subdm, subsection)); 96495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&subsection)); 96505f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(dm, *subdm)); 9651a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 9652a93c429eSMatthew G. Knepley if (is) { 9653a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 9654a93c429eSMatthew G. Knepley IS spIS; 9655a93c429eSMatthew G. Knepley const PetscInt *spmap; 9656a93c429eSMatthew G. Knepley PetscInt *subIndices; 9657a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9658a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9659a93c429eSMatthew G. Knepley 96605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSubpointIS(*subdm, &spIS)); 96615f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(spIS, &spmap)); 96625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section, &Nf)); 96635f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(dm, §ionGlobal)); 96645f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(*subdm, &subsectionGlobal)); 96655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(subsection, &pStart, &pEnd)); 9666a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9667a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 9668a93c429eSMatthew G. Knepley 96695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(sectionGlobal, p, &gdof)); 9670a93c429eSMatthew G. Knepley if (gdof > 0) { 9671a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9672a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 9673a93c429eSMatthew G. Knepley 96745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 96755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 9676a93c429eSMatthew G. Knepley pSubSize += fdof-fcdof; 9677a93c429eSMatthew G. Knepley } 9678a93c429eSMatthew G. Knepley subSize += pSubSize; 9679a93c429eSMatthew G. Knepley if (pSubSize) { 9680a93c429eSMatthew G. Knepley if (bs < 0) { 9681a93c429eSMatthew G. Knepley bs = pSubSize; 9682a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 9683a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 9684a93c429eSMatthew G. Knepley bs = 1; 9685a93c429eSMatthew G. Knepley } 9686a93c429eSMatthew G. Knepley } 9687a93c429eSMatthew G. Knepley } 9688a93c429eSMatthew G. Knepley } 9689a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 9690a93c429eSMatthew G. Knepley bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 96915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax)); 9692a93c429eSMatthew G. Knepley if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9693a93c429eSMatthew G. Knepley else {bs = bsMinMax[0];} 96945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(subSize, &subIndices)); 9695a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 9696a93c429eSMatthew G. Knepley PetscInt gdof, goff; 9697a93c429eSMatthew G. Knepley 96985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 9699a93c429eSMatthew G. Knepley if (gdof > 0) { 9700a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 9701a93c429eSMatthew G. Knepley 97025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(sectionGlobal, point, &goff)); 9703a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9704a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 9705a93c429eSMatthew G. Knepley 9706a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 9707a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 97085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, p, f2, &fdof)); 97095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 9710a93c429eSMatthew G. Knepley poff += fdof-fcdof; 9711a93c429eSMatthew G. Knepley } 97125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section, p, f, &fdof)); 97135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 9714a93c429eSMatthew G. Knepley for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9715a93c429eSMatthew G. Knepley subIndices[subOff] = goff+poff+fc; 9716a93c429eSMatthew G. Knepley } 9717a93c429eSMatthew G. Knepley } 9718a93c429eSMatthew G. Knepley } 9719a93c429eSMatthew G. Knepley } 97205f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(spIS, &spmap)); 97215f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 9722a93c429eSMatthew G. Knepley if (bs > 1) { 9723a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 9724a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 9725a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 9726a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 9727a93c429eSMatthew G. Knepley if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9728a93c429eSMatthew G. Knepley } 9729a93c429eSMatthew G. Knepley } 97305f80ce2aSJacob Faibussowitsch if (set) CHKERRQ(ISSetBlockSize(*is, bs)); 9731a93c429eSMatthew G. Knepley } 9732a93c429eSMatthew G. Knepley /* Attach nullspace */ 9733a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9734a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9735a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 9736a93c429eSMatthew G. Knepley } 9737a93c429eSMatthew G. Knepley if (f < Nf) { 9738a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 97395f80ce2aSJacob Faibussowitsch CHKERRQ((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 97406823f3c5SBlaise Bourdin 97415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace)); 97425f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceDestroy(&nullSpace)); 9743a93c429eSMatthew G. Knepley } 9744a93c429eSMatthew G. Knepley } 9745a93c429eSMatthew G. Knepley PetscFunctionReturn(0); 9746a93c429eSMatthew G. Knepley } 9747c0f0dcc3SMatthew G. Knepley 9748c0f0dcc3SMatthew G. Knepley /*@ 9749c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 9750c0f0dcc3SMatthew G. Knepley 9751c0f0dcc3SMatthew G. Knepley Input Parameter: 9752c0f0dcc3SMatthew G. Knepley - dm - The DM 9753c0f0dcc3SMatthew G. Knepley 9754c0f0dcc3SMatthew G. Knepley Level: developer 9755c0f0dcc3SMatthew G. Knepley 9756c0f0dcc3SMatthew G. Knepley Options Database Keys: 9757c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor 9758c0f0dcc3SMatthew G. Knepley 9759c0f0dcc3SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreate() 9760c0f0dcc3SMatthew G. Knepley @*/ 9761c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9762c0f0dcc3SMatthew G. Knepley { 9763e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG) 9764c0f0dcc3SMatthew G. Knepley PetscStageLog stageLog; 9765c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 9766c0f0dcc3SMatthew G. Knepley PetscLogStage stage; 9767c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 9768c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 9769c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 9770c0f0dcc3SMatthew G. Knepley const char *name; 9771e5ed2c37SJose E. Roman #endif 9772c0f0dcc3SMatthew G. Knepley 9773c0f0dcc3SMatthew G. Knepley PetscFunctionBegin; 9774c0f0dcc3SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9775c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG) 97765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) dm, &name)); 97775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 97785f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumFields(dm, &Nf)); 97795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogGetStageLog(&stageLog)); 97805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStageLogGetCurrent(stageLog, &stage)); 97815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventGetId("DMPlexResidualFE", &event)); 97825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 9783c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart)*Nf*eventInfo.count; 9784c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops/eventInfo.time; 9785c0f0dcc3SMatthew G. Knepley cellRate = N/eventInfo.time; 97865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PetscObjectComm((PetscObject) dm), "DM (%s) FE Residual Integration: %D 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))); 9787c0f0dcc3SMatthew G. Knepley #else 9788c0f0dcc3SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9789c0f0dcc3SMatthew G. Knepley #endif 9790c0f0dcc3SMatthew G. Knepley PetscFunctionReturn(0); 9791c0f0dcc3SMatthew G. Knepley } 9792