1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 60c312b8eSJed Brown #include <petscsf.h> 7e228b242SToby Isaac #include <petscds.h> 8e412dcbdSMatthew G. Knepley #include <petscdraw.h> 9f19dbd58SToby Isaac #include <petscdmfield.h> 10012bc364SMatthew G. Knepley #include <petscdmplextransform.h> 11*c789d87fSToby Isaac #include <petscblaslapack.h> 12552f7358SJed Brown 13552f7358SJed Brown /* Logging support */ 1402f7d72cSksagiyam 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; 15172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate; 16552f7358SJed Brown 17f39ec787SMatthew G. Knepley PetscBool Plexcite = PETSC_FALSE; 18f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n" 19f39ec787SMatthew G. Knepley "title = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n" 20f39ec787SMatthew G. Knepley "author = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n" 21f39ec787SMatthew G. Knepley "journal = {SIAM Journal on Scientific Computing},\n" 22f39ec787SMatthew G. Knepley "volume = {38},\n" 23f39ec787SMatthew G. Knepley "number = {5},\n" 24f39ec787SMatthew G. Knepley "pages = {S143--S155},\n" 25f39ec787SMatthew G. Knepley "eprint = {http://arxiv.org/abs/1506.07749},\n" 26f39ec787SMatthew G. Knepley "doi = {10.1137/15M1026092},\n" 27f39ec787SMatthew G. Knepley "year = {2016},\n" 28f39ec787SMatthew G. Knepley "petsc_uses={DMPlex},\n}\n"; 29f39ec787SMatthew G. Knepley 305a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 31552f7358SJed Brown 32e5337592SStefano Zampini /*@ 339318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 349318fe57SMatthew G. Knepley 359318fe57SMatthew G. Knepley Input Parameter: 36a1cb98faSBarry Smith . dm - The `DMPLEX` object 379318fe57SMatthew G. Knepley 389318fe57SMatthew G. Knepley Output Parameter: 399318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 409318fe57SMatthew G. Knepley 419318fe57SMatthew G. Knepley Level: intermediate 429318fe57SMatthew G. Knepley 43a1cb98faSBarry Smith Note: 44a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 45a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 46a1cb98faSBarry Smith 471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 489318fe57SMatthew G. Knepley @*/ 49d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 50d71ae5a4SJacob Faibussowitsch { 519318fe57SMatthew G. Knepley DMPolytopeType ct; 529318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 539318fe57SMatthew G. Knepley 549318fe57SMatthew G. Knepley PetscFunctionBegin; 559566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 569371c9d4SSatish Balay if (cEnd <= cStart) { 579371c9d4SSatish Balay *simplex = PETSC_FALSE; 583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 599371c9d4SSatish Balay } 609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 619318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 639318fe57SMatthew G. Knepley } 649318fe57SMatthew G. Knepley 659318fe57SMatthew G. Knepley /*@ 66412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 67e5337592SStefano Zampini 68d8d19677SJose E. Roman Input Parameters: 69a1cb98faSBarry Smith + dm - The `DMPLEX` object 70412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 71e5337592SStefano Zampini 72e5337592SStefano Zampini Output Parameters: 73412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 7440196513SBarry Smith - cEnd - The upper bound on "normal" cells 75e5337592SStefano Zampini 76412e9a14SMatthew G. Knepley Level: developer 77e5337592SStefano Zampini 78a1cb98faSBarry Smith Note: 795ae96e2bSMatthew G. Knepley This function requires that tensor cells are ordered last. 80a1cb98faSBarry Smith 812827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()` 82e5337592SStefano Zampini @*/ 83d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 84d71ae5a4SJacob Faibussowitsch { 855ae96e2bSMatthew G. Knepley DMLabel ctLabel; 865ae96e2bSMatthew G. Knepley IS valueIS; 875ae96e2bSMatthew G. Knepley const PetscInt *ctypes; 885ae96e2bSMatthew G. Knepley PetscInt Nct, cS = PETSC_MAX_INT, cE = 0; 89e5337592SStefano Zampini 90e5337592SStefano Zampini PetscFunctionBegin; 919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 925ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetValueIS(ctLabel, &valueIS)); 935ae96e2bSMatthew G. Knepley PetscCall(ISGetLocalSize(valueIS, &Nct)); 945ae96e2bSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &ctypes)); 955ae96e2bSMatthew G. Knepley if (!Nct) cS = cE = 0; 965ae96e2bSMatthew G. Knepley for (PetscInt t = 0; t < Nct; ++t) { 97c306944fSJed Brown const DMPolytopeType ct = (DMPolytopeType)ctypes[t]; 985ae96e2bSMatthew G. Knepley PetscInt ctS, ctE, ht; 995ae96e2bSMatthew G. Knepley 1005ae96e2bSMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 1015ae96e2bSMatthew G. Knepley // If any cells are not typed, just use all cells 1025ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd)); 1035ae96e2bSMatthew G. Knepley break; 1045ae96e2bSMatthew G. Knepley } 105c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue; 1065ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE)); 1075ae96e2bSMatthew G. Knepley if (ctS >= ctE) continue; 1085ae96e2bSMatthew G. Knepley // Check that a point has the right height 1095ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetPointHeight(dm, ctS, &ht)); 1105ae96e2bSMatthew G. Knepley if (ht != height) continue; 1115ae96e2bSMatthew G. Knepley cS = PetscMin(cS, ctS); 1125ae96e2bSMatthew G. Knepley cE = PetscMax(cE, ctE); 1135ae96e2bSMatthew G. Knepley } 1145ae96e2bSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 115695799ffSMatthew G. Knepley // Reset label for fast lookup 116695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 117412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 118412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 1193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 120e5337592SStefano Zampini } 121e5337592SStefano Zampini 1229c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft) 1239c600e38SMatt McGurn { 1249c600e38SMatt McGurn PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t; 1259c600e38SMatt McGurn PetscInt *sStart, *sEnd; 1269c600e38SMatt McGurn PetscViewerVTKFieldType *ft; 1279c600e38SMatt McGurn PetscInt vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1]; 1289c600e38SMatt McGurn DMLabel depthLabel, ctLabel; 1299c600e38SMatt McGurn 1309c600e38SMatt McGurn PetscFunctionBegin; 1319c600e38SMatt McGurn /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */ 1329c600e38SMatt McGurn PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1)); 1339c600e38SMatt McGurn PetscCall(DMGetCoordinateDim(dm, &cdim)); 1349c600e38SMatt McGurn PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1359c600e38SMatt McGurn PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1369c600e38SMatt McGurn if (field >= 0) { 1379c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES])); 1389c600e38SMatt McGurn } else { 1399c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES])); 1409c600e38SMatt McGurn } 1419c600e38SMatt McGurn 1429c600e38SMatt McGurn PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 1439c600e38SMatt McGurn PetscCall(DMPlexGetDepth(dm, &depth)); 1449c600e38SMatt McGurn PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 1459c600e38SMatt McGurn PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 1469c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1479c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1489c600e38SMatt McGurn PetscInt dep; 1499c600e38SMatt McGurn 1509c600e38SMatt McGurn if (ict == DM_POLYTOPE_FV_GHOST) continue; 1519c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1529c600e38SMatt McGurn if (pStart >= 0) { 1539c600e38SMatt McGurn PetscCall(DMLabelGetValue(depthLabel, cStart, &dep)); 1549c600e38SMatt McGurn if (dep != depth - cellHeight) continue; 1559c600e38SMatt McGurn } 1569c600e38SMatt McGurn if (field >= 0) { 1579c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c])); 1589c600e38SMatt McGurn } else { 1599c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c])); 1609c600e38SMatt McGurn } 1619c600e38SMatt McGurn } 1629c600e38SMatt McGurn 1639c600e38SMatt McGurn PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1649c600e38SMatt McGurn *types = 0; 1659c600e38SMatt McGurn 1669c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) { 1679c600e38SMatt McGurn if (globalvcdof[c]) ++(*types); 1689c600e38SMatt McGurn } 1699c600e38SMatt McGurn 1709c600e38SMatt McGurn PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft)); 1719c600e38SMatt McGurn t = 0; 1729c600e38SMatt McGurn if (globalvcdof[DM_NUM_POLYTOPES]) { 1739c600e38SMatt McGurn sStart[t] = vStart; 1749c600e38SMatt McGurn sEnd[t] = vEnd; 1759c600e38SMatt McGurn ft[t] = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 1769c600e38SMatt McGurn ++t; 1779c600e38SMatt McGurn } 1789c600e38SMatt McGurn 1799c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1809c600e38SMatt McGurn if (globalvcdof[c]) { 1819c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1829c600e38SMatt McGurn 1839c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1849c600e38SMatt McGurn sStart[t] = cStart; 1859c600e38SMatt McGurn sEnd[t] = cEnd; 1869c600e38SMatt McGurn ft[t] = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD; 1879c600e38SMatt McGurn ++t; 1889c600e38SMatt McGurn } 1899c600e38SMatt McGurn } 1909c600e38SMatt McGurn 1914ad8454bSPierre Jolivet if (!*types) { 1929c600e38SMatt McGurn if (field >= 0) { 1939c600e38SMatt McGurn const char *fieldname; 1949c600e38SMatt McGurn 1959c600e38SMatt McGurn PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 1969c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 1979c600e38SMatt McGurn } else { 1989c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 1999c600e38SMatt McGurn } 2009c600e38SMatt McGurn } 2019c600e38SMatt McGurn 2029c600e38SMatt McGurn *ssStart = sStart; 2039c600e38SMatt McGurn *ssEnd = sEnd; 2049c600e38SMatt McGurn *sft = ft; 2059c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2069c600e38SMatt McGurn } 2079c600e38SMatt McGurn 2089c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft) 2099c600e38SMatt McGurn { 2109c600e38SMatt McGurn PetscFunctionBegin; 2119c600e38SMatt McGurn PetscCall(PetscFree3(*sStart, *sEnd, *ft)); 2129c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2139c600e38SMatt McGurn } 2149c600e38SMatt McGurn 215d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 216d71ae5a4SJacob Faibussowitsch { 217412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 218a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 2197e42fee7SMatthew G. Knepley 2207e42fee7SMatthew G. Knepley PetscFunctionBegin; 221e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 2229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2249566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2267e42fee7SMatthew G. Knepley if (field >= 0) { 2279566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 2289566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 2297e42fee7SMatthew G. Knepley } else { 2309566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 2319566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 2327e42fee7SMatthew G. Knepley } 233712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 234a99a26bcSAdrian Croucher if (globalvcdof[0]) { 2357e42fee7SMatthew G. Knepley *sStart = vStart; 2367e42fee7SMatthew G. Knepley *sEnd = vEnd; 237f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 2387e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 239a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 2407e42fee7SMatthew G. Knepley *sStart = cStart; 2417e42fee7SMatthew G. Knepley *sEnd = cEnd; 242f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 2437e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 244e630c359SToby Isaac } else { 245e630c359SToby Isaac if (field >= 0) { 246e630c359SToby Isaac const char *fieldname; 247e630c359SToby Isaac 2489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 24963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 250e630c359SToby Isaac } else { 25163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 252e630c359SToby Isaac } 253e630c359SToby Isaac } 2543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2557e42fee7SMatthew G. Knepley } 2567e42fee7SMatthew G. Knepley 2576913077dSMatthew G. Knepley /*@ 2586913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 2596913077dSMatthew G. Knepley 26020f4b53cSBarry Smith Collective 2616913077dSMatthew G. Knepley 2626913077dSMatthew G. Knepley Input Parameters: 263a1cb98faSBarry Smith + dm - The `DMPLEX` object 2646913077dSMatthew G. Knepley . n - The number of vectors 2656913077dSMatthew G. Knepley . u - The array of local vectors 266a1cb98faSBarry Smith - viewer - The `PetscViewer` 2676913077dSMatthew G. Knepley 2686913077dSMatthew G. Knepley Level: advanced 2696913077dSMatthew G. Knepley 2701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 2716913077dSMatthew G. Knepley @*/ 272d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 273d71ae5a4SJacob Faibussowitsch { 2746913077dSMatthew G. Knepley PetscDS ds; 2756913077dSMatthew G. Knepley PetscDraw draw = NULL; 2766913077dSMatthew G. Knepley PetscDrawLG lg; 2776913077dSMatthew G. Knepley Vec coordinates; 2786913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 2796913077dSMatthew G. Knepley PetscReal *vals; 2806913077dSMatthew G. Knepley PetscInt *Nc; 2816913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 2826913077dSMatthew G. Knepley char **names; 2836913077dSMatthew G. Knepley 2846913077dSMatthew G. Knepley PetscFunctionBegin; 2859566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 2869566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 2879566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 2889566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 2896913077dSMatthew G. Knepley 2909566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2913ba16761SJacob Faibussowitsch if (!draw) PetscFunctionReturn(PETSC_SUCCESS); 2929566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 2936913077dSMatthew G. Knepley 2949566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 2956913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 2966913077dSMatthew G. Knepley const char *vname; 2976913077dSMatthew G. Knepley 2989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 2996913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 3006913077dSMatthew G. Knepley PetscObject disc; 3016913077dSMatthew G. Knepley const char *fname; 3026913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 3036913077dSMatthew G. Knepley 3049566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 3056913077dSMatthew G. Knepley /* TODO Create names for components */ 3066913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 3079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 308c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname))); 309c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname))); 310c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname))); 3119566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 3126913077dSMatthew G. Knepley } 3136913077dSMatthew G. Knepley } 3146913077dSMatthew G. Knepley } 3159566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 3166913077dSMatthew G. Knepley /* Just add P_1 support for now */ 3179566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3199566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 3209566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 3216913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 3226913077dSMatthew G. Knepley PetscScalar *x, *svals; 3236913077dSMatthew G. Knepley 3249566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 3256913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 3269566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 3276913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3286913077dSMatthew G. Knepley } 3299566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 3306913077dSMatthew G. Knepley } 3319566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 3329566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 3339566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 3349566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 3356913077dSMatthew G. Knepley 3369566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 3379566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3396913077dSMatthew G. Knepley } 3406913077dSMatthew G. Knepley 341d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 342d71ae5a4SJacob Faibussowitsch { 3436913077dSMatthew G. Knepley DM dm; 3446913077dSMatthew G. Knepley 3456913077dSMatthew G. Knepley PetscFunctionBegin; 3469566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 3479566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 3483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3496913077dSMatthew G. Knepley } 3506913077dSMatthew G. Knepley 351d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 352d71ae5a4SJacob Faibussowitsch { 353e412dcbdSMatthew G. Knepley DM dm; 354d1df6f1dSMatthew G. Knepley PetscSection s; 355e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 356e412dcbdSMatthew G. Knepley DM cdm; 357e412dcbdSMatthew G. Knepley PetscSection coordSection; 358e412dcbdSMatthew G. Knepley Vec coordinates; 359c9c77995SMatthew G. Knepley const PetscScalar *array; 360c9c77995SMatthew G. Knepley PetscReal lbound[3], ubound[3]; 361339e3443SMatthew G. Knepley PetscReal vbound[2], time; 3626913077dSMatthew G. Knepley PetscBool flg; 363d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 364e412dcbdSMatthew G. Knepley const char *name; 365339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 366e412dcbdSMatthew G. Knepley 367e412dcbdSMatthew G. Knepley PetscFunctionBegin; 3689566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3699566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3719566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 3729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 3739566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 3749566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 3759566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 3769566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3789566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 379e412dcbdSMatthew G. Knepley 3809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 3819566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 382e412dcbdSMatthew G. Knepley 3839566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 384c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lbound, ubound)); 3859566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 386e412dcbdSMatthew G. Knepley 387d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 388d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 389d1df6f1dSMatthew G. Knepley DM fdm = dm; 390d1df6f1dSMatthew G. Knepley Vec fv = v; 391d1df6f1dSMatthew G. Knepley IS fis; 392d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 393d1df6f1dSMatthew G. Knepley const char *fname; 394d1df6f1dSMatthew G. Knepley 3959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 3969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 397d1df6f1dSMatthew G. Knepley 3989566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 399ad540459SPierre Jolivet else prefix[0] = '\0'; 400d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4019566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 4029566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 4039566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 4049566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 405d1df6f1dSMatthew G. Knepley } 406d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 407d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 408d1df6f1dSMatthew G. Knepley 4099566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 41063a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 41163a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 4129566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 413d1df6f1dSMatthew G. Knepley 414d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 4159566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 416339e3443SMatthew G. Knepley if (!flg) { 4179566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 4189566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 419d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 420339e3443SMatthew G. Knepley } 421c9c77995SMatthew G. Knepley 4229566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 4239566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 424c9c77995SMatthew G. Knepley PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1])); 4259566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 426e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 42799a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 428c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 429c9c77995SMatthew G. Knepley PetscBool isDG; 430e56f9228SJed Brown PetscInt numCoords, color[4] = {-1, -1, -1, -1}; 431e412dcbdSMatthew G. Knepley 4329566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 433339e3443SMatthew G. Knepley if (a) { 434d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 435339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 436339e3443SMatthew G. Knepley } else { 437339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 438339e3443SMatthew G. Knepley PetscInt numVals, va; 439339e3443SMatthew G. Knepley 4409566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 44163a3b9bcSJacob Faibussowitsch PetscCheck(numVals % Nc == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %" PetscInt_FMT " does not divide the number of values in the closure %" PetscInt_FMT, Nc, numVals); 442d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 443d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 444d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 445d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 446339e3443SMatthew G. Knepley break; 447d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 448d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 449d1df6f1dSMatthew 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]); 450d1df6f1dSMatthew G. Knepley break; 451d71ae5a4SJacob Faibussowitsch default: 452d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 453339e3443SMatthew G. Knepley } 4549566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 455339e3443SMatthew G. Knepley } 456c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 457e412dcbdSMatthew G. Knepley switch (numCoords) { 458e412dcbdSMatthew G. Knepley case 6: 4599edc3542SMatthew Knepley case 12: /* Localized triangle */ 4609566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2])); 461e412dcbdSMatthew G. Knepley break; 462e412dcbdSMatthew G. Knepley case 8: 4639edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 4649566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2])); 4659566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0])); 466e412dcbdSMatthew G. Knepley break; 467d71ae5a4SJacob Faibussowitsch default: 468d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 469e412dcbdSMatthew G. Knepley } 470c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 471e412dcbdSMatthew G. Knepley } 4729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 4739566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 4749566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 4759566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 476d1df6f1dSMatthew G. Knepley } 477d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4789566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 4799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4809566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 481d1df6f1dSMatthew G. Knepley } 482d1df6f1dSMatthew G. Knepley } 4833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 484e412dcbdSMatthew G. Knepley } 485e412dcbdSMatthew G. Knepley 486d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 487d71ae5a4SJacob Faibussowitsch { 4886913077dSMatthew G. Knepley DM dm; 4896913077dSMatthew G. Knepley PetscDraw draw; 4906913077dSMatthew G. Knepley PetscInt dim; 4916913077dSMatthew G. Knepley PetscBool isnull; 4926913077dSMatthew G. Knepley 4936913077dSMatthew G. Knepley PetscFunctionBegin; 4949566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4959566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 4963ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 4976913077dSMatthew G. Knepley 4989566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 5006913077dSMatthew G. Knepley switch (dim) { 501d71ae5a4SJacob Faibussowitsch case 1: 502d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 503d71ae5a4SJacob Faibussowitsch break; 504d71ae5a4SJacob Faibussowitsch case 2: 505d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 506d71ae5a4SJacob Faibussowitsch break; 507d71ae5a4SJacob Faibussowitsch default: 508d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 5096913077dSMatthew G. Knepley } 5103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5116913077dSMatthew G. Knepley } 5126913077dSMatthew G. Knepley 513d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 514d71ae5a4SJacob Faibussowitsch { 515684b87d9SLisandro Dalcin DM dm; 516684b87d9SLisandro Dalcin Vec locv; 517684b87d9SLisandro Dalcin const char *name; 518684b87d9SLisandro Dalcin PetscSection section; 519684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 520e630c359SToby Isaac PetscInt numFields; 521684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 522684b87d9SLisandro Dalcin 523684b87d9SLisandro Dalcin PetscFunctionBegin; 5249566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5259566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 5269566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5289566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5299566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 5309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 531e630c359SToby Isaac if (!numFields) { 5329566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 5339566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 534e630c359SToby Isaac } else { 535e630c359SToby Isaac PetscInt f; 536e630c359SToby Isaac 537e630c359SToby Isaac for (f = 0; f < numFields; f++) { 5389566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 539e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 5409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 5419566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 542e630c359SToby Isaac } 5439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 544e630c359SToby Isaac } 5453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 546684b87d9SLisandro Dalcin } 547684b87d9SLisandro Dalcin 548d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 549d71ae5a4SJacob Faibussowitsch { 550552f7358SJed Brown DM dm; 5515f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 552552f7358SJed Brown 553552f7358SJed Brown PetscFunctionBegin; 5549566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 55528b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5605f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5615f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 562684b87d9SLisandro Dalcin PetscInt i, numFields; 563684b87d9SLisandro Dalcin PetscObject fe; 564ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 565684b87d9SLisandro Dalcin Vec locv = v; 566684b87d9SLisandro Dalcin const char *name; 567684b87d9SLisandro Dalcin PetscInt step; 568684b87d9SLisandro Dalcin PetscReal time; 569ef31f671SMatthew G. Knepley 5709566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 571684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 5729566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 5739371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 5749371c9d4SSatish Balay fem = PETSC_TRUE; 5759371c9d4SSatish Balay break; 5769371c9d4SSatish Balay } 577ef31f671SMatthew G. Knepley } 578684b87d9SLisandro Dalcin if (fem) { 579798534f6SMatthew G. Knepley PetscObject isZero; 580798534f6SMatthew G. Knepley 5819566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5849566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 5859566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 5869566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5879566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 5889566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 589ef31f671SMatthew G. Knepley } 590552f7358SJed Brown if (isvtk) { 5919566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 592b136c2c9SMatthew G. Knepley } else if (ishdf5) { 593b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5949566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 595b136c2c9SMatthew G. Knepley #else 596b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 597b136c2c9SMatthew G. Knepley #endif 598f13a32a3SMatthew G. Knepley } else if (isdraw) { 5999566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 600684b87d9SLisandro Dalcin } else if (isglvis) { 6019566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 6029566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 6039566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 6045f34f2dcSJed Brown } else if (iscgns) { 6055f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 6065f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 6075f34f2dcSJed Brown #else 6085f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 6095f34f2dcSJed Brown #endif 610684b87d9SLisandro Dalcin } 611798534f6SMatthew G. Knepley if (fem) { 6129566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6139566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 614798534f6SMatthew G. Knepley } 615552f7358SJed Brown } else { 616684b87d9SLisandro Dalcin PetscBool isseq; 617684b87d9SLisandro Dalcin 6189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6199566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6209566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 621552f7358SJed Brown } 6223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 623552f7358SJed Brown } 624552f7358SJed Brown 625d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 626d71ae5a4SJacob Faibussowitsch { 627552f7358SJed Brown DM dm; 6285f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 629552f7358SJed Brown 630552f7358SJed Brown PetscFunctionBegin; 6319566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 6349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 6375f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 6389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6395f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 640552f7358SJed Brown Vec locv; 641798534f6SMatthew G. Knepley PetscObject isZero; 642552f7358SJed Brown const char *name; 643552f7358SJed Brown 6449566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 6459566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6479566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 6489566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 6499566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 6509566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 6519566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 6529566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6539566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 654b136c2c9SMatthew G. Knepley } else if (ishdf5) { 655b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6569566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 657b136c2c9SMatthew G. Knepley #else 658b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 659b136c2c9SMatthew G. Knepley #endif 6606823f3c5SBlaise Bourdin } else if (isexodusii) { 6616823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6629566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 6636823f3c5SBlaise Bourdin #else 6646823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6656823f3c5SBlaise Bourdin #endif 666552f7358SJed Brown } else { 667684b87d9SLisandro Dalcin PetscBool isseq; 668684b87d9SLisandro Dalcin 6699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6709566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6719566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 672552f7358SJed Brown } 6733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 674552f7358SJed Brown } 675552f7358SJed Brown 676d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 677d71ae5a4SJacob Faibussowitsch { 678d930f514SMatthew G. Knepley DM dm; 679d930f514SMatthew G. Knepley MPI_Comm comm; 680d930f514SMatthew G. Knepley PetscViewerFormat format; 681d930f514SMatthew G. Knepley Vec v; 682d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 683d930f514SMatthew G. Knepley 684d930f514SMatthew G. Knepley PetscFunctionBegin; 6859566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 6869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 68728b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6889566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 691d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 692a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 693a8ad634aSStefano Zampini /* this need a better fix */ 694a8ad634aSStefano Zampini if (dm->useNatural) { 695a8ad634aSStefano Zampini if (dm->sfNatural) { 696d930f514SMatthew G. Knepley const char *vecname; 697d930f514SMatthew G. Knepley PetscInt n, nroots; 698d930f514SMatthew G. Knepley 6999566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 7009566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 701d930f514SMatthew G. Knepley if (n == nroots) { 702f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 7039566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 7049566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 7059566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7069566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 707d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 708d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 709a8ad634aSStefano Zampini } else v = originalv; 710a8ad634aSStefano Zampini } else v = originalv; 711a8ad634aSStefano Zampini 712d930f514SMatthew G. Knepley if (ishdf5) { 713d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7149566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 715d930f514SMatthew G. Knepley #else 716d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 717d930f514SMatthew G. Knepley #endif 718d930f514SMatthew G. Knepley } else if (isvtk) { 719d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 720d930f514SMatthew G. Knepley } else { 721d930f514SMatthew G. Knepley PetscBool isseq; 722d930f514SMatthew G. Knepley 7239566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 7249566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 7259566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 726d930f514SMatthew G. Knepley } 727f16a8b29SMatthew G. Knepley if (v != originalv) PetscCall(VecDestroy(&v)); 7283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 729d930f514SMatthew G. Knepley } 730d930f514SMatthew G. Knepley 731d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 732d71ae5a4SJacob Faibussowitsch { 7332c40f234SMatthew G. Knepley DM dm; 7342c40f234SMatthew G. Knepley PetscBool ishdf5; 7352c40f234SMatthew G. Knepley 7362c40f234SMatthew G. Knepley PetscFunctionBegin; 7379566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 73828b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7402c40f234SMatthew G. Knepley if (ishdf5) { 7412c40f234SMatthew G. Knepley DM dmBC; 7422c40f234SMatthew G. Knepley Vec gv; 7432c40f234SMatthew G. Knepley const char *name; 7442c40f234SMatthew G. Knepley 7459566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 7469566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 7479566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 7489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 7499566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 7509566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 7519566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 7529566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 7531baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7552c40f234SMatthew G. Knepley } 7562c40f234SMatthew G. Knepley 757d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 758d71ae5a4SJacob Faibussowitsch { 7592c40f234SMatthew G. Knepley DM dm; 7606823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 7612c40f234SMatthew G. Knepley 7622c40f234SMatthew G. Knepley PetscFunctionBegin; 7639566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 76428b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 7672c40f234SMatthew G. Knepley if (ishdf5) { 768878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7699566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 770b136c2c9SMatthew G. Knepley #else 771b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 772878b459fSMatthew G. Knepley #endif 7736823f3c5SBlaise Bourdin } else if (isexodusii) { 7746823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 7759566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 7766823f3c5SBlaise Bourdin #else 7776823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 7786823f3c5SBlaise Bourdin #endif 7791baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 781552f7358SJed Brown } 782552f7358SJed Brown 783d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 784d71ae5a4SJacob Faibussowitsch { 785d930f514SMatthew G. Knepley DM dm; 786d930f514SMatthew G. Knepley PetscViewerFormat format; 787d930f514SMatthew G. Knepley PetscBool ishdf5; 788d930f514SMatthew G. Knepley 789d930f514SMatthew G. Knepley PetscFunctionBegin; 7909566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 79128b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7929566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 794d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 795a8ad634aSStefano Zampini if (dm->useNatural) { 796d930f514SMatthew G. Knepley if (dm->sfNatural) { 797d930f514SMatthew G. Knepley if (ishdf5) { 798d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 799d930f514SMatthew G. Knepley Vec v; 800d930f514SMatthew G. Knepley const char *vecname; 801d930f514SMatthew G. Knepley 802f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 8039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 8049566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 8059566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 8069566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 8079566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 808f16a8b29SMatthew G. Knepley PetscCall(VecDestroy(&v)); 809d930f514SMatthew G. Knepley #else 810d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 811d930f514SMatthew G. Knepley #endif 812d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 813d930f514SMatthew G. Knepley } 8141baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 815d930f514SMatthew G. Knepley } 8163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 817d930f514SMatthew G. Knepley } 818d930f514SMatthew G. Knepley 819d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 820d71ae5a4SJacob Faibussowitsch { 821731e8ddeSMatthew G. Knepley PetscSection coordSection; 822731e8ddeSMatthew G. Knepley Vec coordinates; 823ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 824731e8ddeSMatthew G. Knepley const char *name[4]; 825731e8ddeSMatthew G. Knepley const PetscScalar *a; 826731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 827731e8ddeSMatthew G. Knepley 828731e8ddeSMatthew G. Knepley PetscFunctionBegin; 8299566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8309566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 8339566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 8349566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 8369566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 837731e8ddeSMatthew G. Knepley name[0] = "vertex"; 838731e8ddeSMatthew G. Knepley name[1] = "edge"; 839731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 840731e8ddeSMatthew G. Knepley name[dim] = "cell"; 841731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 842731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 843ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 844731e8ddeSMatthew G. Knepley 8459566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 84663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 8479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 849731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 850731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 851731e8ddeSMatthew G. Knepley 852731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 8539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 854731e8ddeSMatthew G. Knepley if (!dof) continue; 8559566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 8569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 85763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 858731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 8599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 860731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8619566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 8629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 863731e8ddeSMatthew G. Knepley } 8649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 865731e8ddeSMatthew G. Knepley } 8669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 867731e8ddeSMatthew G. Knepley } 8689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 870731e8ddeSMatthew G. Knepley } 8719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 8723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 873731e8ddeSMatthew G. Knepley } 874731e8ddeSMatthew G. Knepley 8759371c9d4SSatish Balay typedef enum { 8769371c9d4SSatish Balay CS_CARTESIAN, 8779371c9d4SSatish Balay CS_POLAR, 8789371c9d4SSatish Balay CS_CYLINDRICAL, 8799371c9d4SSatish Balay CS_SPHERICAL 8809371c9d4SSatish Balay } CoordSystem; 88119ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 88219ad8254SMatthew G. Knepley 883d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 884d71ae5a4SJacob Faibussowitsch { 88519ad8254SMatthew G. Knepley PetscInt i; 88619ad8254SMatthew G. Knepley 88719ad8254SMatthew G. Knepley PetscFunctionBegin; 88819ad8254SMatthew G. Knepley if (dim > 3) { 8899566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 89019ad8254SMatthew G. Knepley } else { 891bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 89219ad8254SMatthew G. Knepley 89319ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 89419ad8254SMatthew G. Knepley switch (cs) { 8959371c9d4SSatish Balay case CS_CARTESIAN: 8969371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 8979371c9d4SSatish Balay break; 89819ad8254SMatthew G. Knepley case CS_POLAR: 89963a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 90019ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90119ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90219ad8254SMatthew G. Knepley break; 90319ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 90463a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 90519ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90619ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90719ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 90819ad8254SMatthew G. Knepley break; 90919ad8254SMatthew G. Knepley case CS_SPHERICAL: 91063a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 91119ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 91219ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 91319ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 91419ad8254SMatthew G. Knepley break; 91519ad8254SMatthew G. Knepley } 9169566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 91719ad8254SMatthew G. Knepley } 9183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91919ad8254SMatthew G. Knepley } 92019ad8254SMatthew G. Knepley 921d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 922d71ae5a4SJacob Faibussowitsch { 923552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 9246858538eSMatthew G. Knepley DM cdm, cdmCell; 9256858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 9266858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 927552f7358SJed Brown PetscViewerFormat format; 928552f7358SJed Brown 929552f7358SJed Brown PetscFunctionBegin; 9309566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 931552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 932552f7358SJed Brown const char *name; 933f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 9349318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 935552f7358SJed Brown PetscMPIInt rank, size; 936552f7358SJed Brown 9379f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 9389f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9399f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9409f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 9419f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 9429f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 9439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9459566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 9469566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9479566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 9489566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9499566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 95063a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 95163a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 95263a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 95363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 9549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 95563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 956552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 957552f7358SJed Brown PetscInt dof, off, s; 958552f7358SJed Brown 9599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 9609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 96148a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 962552f7358SJed Brown } 9639566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 96463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 96563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 966552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 967552f7358SJed Brown PetscInt dof, off, c; 968552f7358SJed Brown 9699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 9709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 97148a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c])); 972552f7358SJed Brown } 9739566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 9753d2e540fSStefano Zampini if (coordSection && coordinates) { 97619ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 9776858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 9786858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 97919ad8254SMatthew G. Knepley PetscMPIInt rank; 98019ad8254SMatthew G. Knepley const char *name; 98119ad8254SMatthew G. Knepley 9829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 9839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 9849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 98563a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 9869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 9876858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 9886858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 9896858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 9906858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 9919566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 99263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 99363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 9949566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 99519ad8254SMatthew G. Knepley 9969566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 9976858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 9989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 9999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 100019ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 100119ad8254SMatthew G. Knepley PetscInt dof, off; 100219ad8254SMatthew G. Knepley 10036858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 10049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 10059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 10066858538eSMatthew G. Knepley if (dof) { 100763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10089566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 10099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 101019ad8254SMatthew G. Knepley } 10116858538eSMatthew G. Knepley } 10126858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 10136858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 10146858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 10156858538eSMatthew G. Knepley if (dof) { 10166858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10176858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 10186858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 10196858538eSMatthew G. Knepley } 10206858538eSMatthew G. Knepley } 10216858538eSMatthew G. Knepley } 10229566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 10249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 10256858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 10263d2e540fSStefano Zampini } 10279566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10289566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 10299318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10309318fe57SMatthew G. Knepley DMLabel label; 10319318fe57SMatthew G. Knepley PetscBool isdepth; 10329318fe57SMatthew G. Knepley const char *name; 10339318fe57SMatthew G. Knepley 10349566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 10359566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 10369318fe57SMatthew G. Knepley if (isdepth) continue; 10379566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 10389566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 10399318fe57SMatthew G. Knepley } 1040552f7358SJed Brown if (size > 1) { 1041552f7358SJed Brown PetscSF sf; 1042552f7358SJed Brown 10439566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10449566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 1045552f7358SJed Brown } 10464e2e9504SJed Brown if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer)); 10479566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1048552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 10490588280cSMatthew G. Knepley const char *name, *color; 10500588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 10510588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 1052fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 1053552f7358SJed Brown PetscReal scale = 2.0; 105478081901SStefano Zampini PetscReal tikzscale = 1.0; 1055b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 10560588280cSMatthew G. Knepley double tcoords[3]; 1057552f7358SJed Brown PetscScalar *coords; 1058b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 1059552f7358SJed Brown PetscMPIInt rank, size; 10600588280cSMatthew G. Knepley char **names, **colors, **lcolors; 1061b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 1062fe1cc32dSStefano Zampini PetscBT wp = NULL; 1063fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 1064552f7358SJed Brown 10659f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 10669f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 10679f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10689f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 10699f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 10709f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 10719566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 10729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 10739566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10740588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 10750588280cSMatthew G. Knepley numColors = 10; 10760588280cSMatthew G. Knepley numLColors = 10; 10779566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 10789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 10799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 10809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 1081b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 1082b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 1083b7f6ffafSMatthew G. Knepley n = 4; 10849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 10851dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 1086bd3611e6SMatthew G. Knepley n = 4; 10879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 10881dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 10899566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 10900588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 10919566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 10920588280cSMatthew G. Knepley if (!useColors) { 10930588280cSMatthew G. Knepley numColors = 3; 10949566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 10950588280cSMatthew G. Knepley } 10969566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 10970588280cSMatthew G. Knepley if (!useColors) { 10980588280cSMatthew G. Knepley numLColors = 4; 10999566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 11000588280cSMatthew G. Knepley } 11019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1102b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 11039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 11041dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1105202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 11069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1107fe1cc32dSStefano Zampini 1108fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 11099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 11119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 11129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1113fe1cc32dSStefano Zampini if (lflg) { 1114fe1cc32dSStefano Zampini DMLabel lbl; 1115fe1cc32dSStefano Zampini 11169566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1117fe1cc32dSStefano Zampini if (lbl) { 1118fe1cc32dSStefano Zampini PetscInt val, defval; 1119fe1cc32dSStefano Zampini 11209566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 11219566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1122fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1123fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1124fe1cc32dSStefano Zampini PetscInt closureSize; 1125fe1cc32dSStefano Zampini 11269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1127fe1cc32dSStefano Zampini if (val == defval) continue; 1128fe1cc32dSStefano Zampini 11299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 113048a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 11319566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1132fe1cc32dSStefano Zampini } 1133fe1cc32dSStefano Zampini } 1134fe1cc32dSStefano Zampini } 1135fe1cc32dSStefano Zampini 11369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 11379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 11399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 11400588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1141552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1142552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1143552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 11445f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 11450588280cSMatthew G. Knepley if (size > 1) { 11469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1147770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 114863a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 114963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1150770b213bSMatthew G Knepley } 11519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 11520588280cSMatthew G. Knepley } 1153b7f6ffafSMatthew G. Knepley if (drawHasse) { 1154b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1155b7f6ffafSMatthew G. Knepley 115663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 115763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 115863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 11599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 116063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 116163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 11629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 116363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 116463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 116563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 116663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 11679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1168b7f6ffafSMatthew G. Knepley } 11699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1170fe1cc32dSStefano Zampini 1171552f7358SJed Brown /* Plot vertices */ 11729566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 11739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1174552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1175552f7358SJed Brown PetscInt off, dof, d; 11760588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1177552f7358SJed Brown 1178fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 11799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 11809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 11819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 118263a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 11830588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11840588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1185c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 11860588280cSMatthew G. Knepley } 11870588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 11889371c9d4SSatish Balay if (dim == 3) { 11899371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11909371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11919371c9d4SSatish Balay tcoords[2] = -tmp; 11929371c9d4SSatish Balay } 1193552f7358SJed Brown for (d = 0; d < dof; ++d) { 11949566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1196552f7358SJed Brown } 1197b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1198b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 11990588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 12000588280cSMatthew G. Knepley PetscInt val; 12019566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12029371c9d4SSatish Balay if (val >= 0) { 12039371c9d4SSatish Balay color = lcolors[l % numLColors]; 12049371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12059371c9d4SSatish Balay break; 12069371c9d4SSatish Balay } 12070588280cSMatthew G. Knepley } 1208b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 120963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1210b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 121163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 12121baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1213552f7358SJed Brown } 12149566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12159566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1216b7f6ffafSMatthew G. Knepley /* Plot edges */ 1217b7f6ffafSMatthew G. Knepley if (plotEdges) { 12189566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1220b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1221b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1222b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1223b7f6ffafSMatthew G. Knepley 1224b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 12259566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 122663a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 12279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 12289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 12299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 12309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 12319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1232b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1233b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1234b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1235b7f6ffafSMatthew G. Knepley } 1236b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12379371c9d4SSatish Balay if (dim == 3) { 12389371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12399371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12409371c9d4SSatish Balay tcoords[2] = -tmp; 12419371c9d4SSatish Balay } 1242b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12439566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1245b7f6ffafSMatthew G. Knepley } 1246b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1247b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1248b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1249b7f6ffafSMatthew G. Knepley PetscInt val; 1250bd3611e6SMatthew G. Knepley PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12519371c9d4SSatish Balay if (val >= 0) { 12529371c9d4SSatish Balay color = lcolors[l % numLColors]; 12539371c9d4SSatish Balay break; 12549371c9d4SSatish Balay } 1255b7f6ffafSMatthew G. Knepley } 125663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1257b7f6ffafSMatthew G. Knepley } 12589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12599566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1261b7f6ffafSMatthew G. Knepley } 1262846a3e8bSMatthew G. Knepley /* Plot cells */ 1263b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1264846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1265846a3e8bSMatthew G. Knepley const PetscInt *cone; 1266846a3e8bSMatthew G. Knepley 1267fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1268846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1269846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1270846a3e8bSMatthew G. Knepley PetscInt val; 12719566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12729371c9d4SSatish Balay if (val >= 0) { 12739371c9d4SSatish Balay color = lcolors[l % numLColors]; 12749371c9d4SSatish Balay break; 12759371c9d4SSatish Balay } 1276846a3e8bSMatthew G. Knepley } 12779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 127863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1279846a3e8bSMatthew G. Knepley } 1280846a3e8bSMatthew G. Knepley } else { 1281b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1282846a3e8bSMatthew G. Knepley 1283b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1284b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1285fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 12869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1287c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct)) { 1288b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1289b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1290b7f6ffafSMatthew G. Knepley 12919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 12929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1293b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1294b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1295b7f6ffafSMatthew G. Knepley 12969566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 129763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank)); 1298b7f6ffafSMatthew G. Knepley } 1299b7f6ffafSMatthew G. Knepley } else { 1300b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1301b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1302b7f6ffafSMatthew G. Knepley 13039566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1304846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1305846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1306846a3e8bSMatthew G. Knepley 1307b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1308846a3e8bSMatthew G. Knepley } 13099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1310b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1311b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1312b7f6ffafSMatthew G. Knepley 1313b7f6ffafSMatthew G. Knepley if (v > 0) { 1314b7f6ffafSMatthew G. Knepley if (plotEdges) { 1315b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1316b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1317b7f6ffafSMatthew G. Knepley 13189371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 13199371c9d4SSatish Balay endpoints[1] = vertex; 13209566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 132163a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 132263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 13239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 13241baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1325b7f6ffafSMatthew G. Knepley } 132663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1327b7f6ffafSMatthew G. Knepley } 13289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 13299566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1330846a3e8bSMatthew G. Knepley } 1331846a3e8bSMatthew G. Knepley } 1332b7f6ffafSMatthew G. Knepley } 1333846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1334846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1335846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1336c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1337c713ec31SMatthew G. Knepley const PetscScalar *array; 1338c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1339c713ec31SMatthew G. Knepley PetscBool isDG; 1340846a3e8bSMatthew G. Knepley 1341fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1342c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1343c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1344c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 13459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1346c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1347c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1348c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1349846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1350846a3e8bSMatthew G. Knepley } 1351846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 13529371c9d4SSatish Balay if (cdim == 3) { 13539371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 13549371c9d4SSatish Balay tcoords[1] = tcoords[2]; 13559371c9d4SSatish Balay tcoords[2] = -tmp; 13569371c9d4SSatish Balay } 1357ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1358846a3e8bSMatthew G. Knepley } 1359ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1360c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1361c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 13629566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 13639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1364846a3e8bSMatthew G. Knepley } 1365b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1366b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1367846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1368846a3e8bSMatthew G. Knepley PetscInt val; 13699566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 13709371c9d4SSatish Balay if (val >= 0) { 13719371c9d4SSatish Balay color = lcolors[l % numLColors]; 13729371c9d4SSatish Balay isLabeled = PETSC_TRUE; 13739371c9d4SSatish Balay break; 13749371c9d4SSatish Balay } 1375846a3e8bSMatthew G. Knepley } 1376b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 137763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1378b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 137963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 13801baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1381846a3e8bSMatthew G. Knepley } 1382b7f6ffafSMatthew G. Knepley if (drawHasse) { 1383b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 13849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 13859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 13869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 13889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1389552f7358SJed Brown 1390b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 13919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 13929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 13939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 13959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1396b7f6ffafSMatthew G. Knepley 1397b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 13989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 13999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 14009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 14019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 14029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1403b7f6ffafSMatthew G. Knepley 1404b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1405b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1406b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1407b7f6ffafSMatthew G. Knepley 14089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 14099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 141048a46eb9SPierre Jolivet for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank)); 14110588280cSMatthew G. Knepley } 14120588280cSMatthew G. Knepley } 14139566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 14149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 14159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 141663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 14179566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 14189566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 14199566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 14209566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 14219566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 14220f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 14230f7d6e4aSStefano Zampini Vec cown, acown; 14240f7d6e4aSStefano Zampini VecScatter sct; 14250f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 14260f7d6e4aSStefano Zampini IS gid, acis; 14270f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 14280f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 14290f7d6e4aSStefano Zampini PetscScalar *array, nid; 14300f7d6e4aSStefano Zampini const PetscInt *idxs; 14310f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 14320f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 14330f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 14340f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 14350f7d6e4aSStefano Zampini 14369566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1438b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 14399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 14400f7d6e4aSStefano Zampini #endif 14410f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 14429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 14439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 14440f7d6e4aSStefano Zampini d1 = 0; 14459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 14460f7d6e4aSStefano Zampini nid = d2; 14479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 14489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 14499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 14500f7d6e4aSStefano Zampini } else nid = 0.0; 14510f7d6e4aSStefano Zampini 14520f7d6e4aSStefano Zampini /* Get connectivity */ 14539566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14549566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 14550f7d6e4aSStefano Zampini 14560f7d6e4aSStefano Zampini /* filter overlapped local cells */ 14579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 14589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 14599566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 14609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 14610f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 14620f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 14630f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 14640f7d6e4aSStefano Zampini } 14659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 146663a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 14679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 14690f7d6e4aSStefano Zampini 14700f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 14719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 14729566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 14739566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 14749566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 14750f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 14769566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 14779566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 14789566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14799566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 14819566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 14829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 14830f7d6e4aSStefano Zampini 14840f7d6e4aSStefano Zampini /* compute edgeCut */ 14850f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 14869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 14879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 14889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 14899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14909566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 14910f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 14920f7d6e4aSStefano Zampini PetscInt totl; 14930f7d6e4aSStefano Zampini 14940f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 14959566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 14960f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 14970f7d6e4aSStefano Zampini if (work[i] < 0) { 14980f7d6e4aSStefano Zampini ect += 1; 14990f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 15000f7d6e4aSStefano Zampini } 15010f7d6e4aSStefano Zampini } 15020f7d6e4aSStefano Zampini } 15039566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 15049566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 15050f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 15060f7d6e4aSStefano Zampini lm[1] = -numVertices; 15071c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 150863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0])); 15090f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 15100f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 15110f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 15121c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 151363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1514b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1515f4f49eeaSPierre Jolivet PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)gm[1]) / ((double)gm[0]) : 1.)); 15160f7d6e4aSStefano Zampini #else 151763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 15180f7d6e4aSStefano Zampini #endif 15199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 15209566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 15219566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 15229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1523552f7358SJed Brown } else { 1524412e9a14SMatthew G. Knepley const char *name; 1525d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1526412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1527d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1528ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 15299318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1530412e9a14SMatthew G. Knepley MPI_Comm comm; 1531412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1532552f7358SJed Brown 15339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 15349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15369566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15379566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 15389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 153963a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 154063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 154163a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 15429566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 15431c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 15442827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1545d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 15469566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 15479566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1548412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1549412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1550412e9a14SMatthew G. Knepley 15519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 15529566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1553412e9a14SMatthew G. Knepley ict = ct0; 15549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1555412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1556412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1557412e9a14SMatthew G. Knepley DMPolytopeType ct; 1558412e9a14SMatthew G. Knepley 15599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1560412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1561412e9a14SMatthew G. Knepley else ++Nc[1]; 1562412e9a14SMatthew G. Knepley } 1563ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 15649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 15659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 15669566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 156763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1568834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1569dd400576SPatrick Sanan if (rank == 0) { 157063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 157163a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 157263a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1573834065abSMatthew G. Knepley } 1574cbb7f117SMark Adams } 1575ca7bf7eeSMatthew G. Knepley } else { 1576ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1577ca7bf7eeSMatthew G. Knepley 15789371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 15799371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 15809566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 15819371c9d4SSatish Balay locMinMax[0] = Nc[1]; 15829371c9d4SSatish Balay locMinMax[1] = Nc[1]; 15839566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1584ca7bf7eeSMatthew G. Knepley if (d == depth) { 15859371c9d4SSatish Balay locMinMax[0] = gcNum; 15869371c9d4SSatish Balay locMinMax[1] = gcNum; 15879566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1588ca7bf7eeSMatthew G. Knepley } 158963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 15909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 15919566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 15929566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1593ca7bf7eeSMatthew G. Knepley } 15949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1595552f7358SJed Brown } 15969566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 15979318fe57SMatthew G. Knepley { 15989318fe57SMatthew G. Knepley const PetscReal *maxCell; 15999318fe57SMatthew G. Knepley const PetscReal *L; 16006858538eSMatthew G. Knepley PetscBool localized; 16019318fe57SMatthew G. Knepley 16024fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 16039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 16046858538eSMatthew G. Knepley if (L || localized) { 16056858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 16069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 16076858538eSMatthew G. Knepley if (L) { 16086858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 16099318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 16106858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 16116858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 16129318fe57SMatthew G. Knepley } 16136858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 16146858538eSMatthew G. Knepley } 16156858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 16169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16179318fe57SMatthew G. Knepley } 16189318fe57SMatthew G. Knepley } 16199566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 16209566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1621a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1622a57dd577SMatthew G Knepley DMLabel label; 1623a57dd577SMatthew G Knepley const char *name; 1624a57dd577SMatthew G Knepley IS valueIS; 1625a57dd577SMatthew G Knepley const PetscInt *values; 1626a57dd577SMatthew G Knepley PetscInt numValues, v; 1627a57dd577SMatthew G Knepley 16289566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 16299566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 16309566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 163163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 16329566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 16339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 16349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1635a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1636a57dd577SMatthew G Knepley PetscInt size; 1637a57dd577SMatthew G Knepley 16389566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 16399566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 164063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1641a57dd577SMatthew G Knepley } 16429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 16439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 16459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1646a57dd577SMatthew G Knepley } 1647c1cad2e7SMatthew G. Knepley { 1648c1cad2e7SMatthew G. Knepley char **labelNames; 1649c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1650c1cad2e7SMatthew G. Knepley PetscBool flg; 1651c1cad2e7SMatthew G. Knepley 16529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 16539566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1654c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1655c1cad2e7SMatthew G. Knepley DMLabel label; 1656c1cad2e7SMatthew G. Knepley 16579566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1658c1cad2e7SMatthew G. Knepley if (flg) { 16599566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 16609566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1661c1cad2e7SMatthew G. Knepley } 16629566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1663c1cad2e7SMatthew G. Knepley } 16649566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1665c1cad2e7SMatthew G. Knepley } 166634aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 166734aa8a36SMatthew G. Knepley if (dm->Nf) { 166834aa8a36SMatthew G. Knepley PetscInt f; 166934aa8a36SMatthew G. Knepley 167034aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 167134aa8a36SMatthew G. Knepley const char *name; 167234aa8a36SMatthew G. Knepley 16739566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 16749566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 16759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16769566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 167734aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 16789566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 16799566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 168034aa8a36SMatthew G. Knepley } else { 16819566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 16829566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 168334aa8a36SMatthew G. Knepley } 16849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 168534aa8a36SMatthew G. Knepley } 168634aa8a36SMatthew G. Knepley } 16879566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 16888e7ff633SMatthew G. Knepley if (cdm) { 16899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16909f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 16919566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 16929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 16938e7ff633SMatthew G. Knepley } 1694552f7358SJed Brown } 16953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1696552f7358SJed Brown } 1697552f7358SJed Brown 1698d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1699d71ae5a4SJacob Faibussowitsch { 1700e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1701e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1702a12d352dSMatthew G. Knepley PetscInt cdim; 1703e5c487bfSMatthew G. Knepley 1704e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 17079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1708e5c487bfSMatthew G. Knepley switch (ct) { 1709a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1710a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1711a12d352dSMatthew G. Knepley switch (cdim) { 17129371c9d4SSatish Balay case 1: { 1713a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1714a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1715a12d352dSMatthew G. Knepley 17169566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 17179566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 17189566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 17199371c9d4SSatish Balay } break; 17209371c9d4SSatish Balay case 2: { 1721a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1722a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1723a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1724a12d352dSMatthew G. Knepley 17259566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17269566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK)); 17279566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK)); 17289371c9d4SSatish Balay } break; 1729d71ae5a4SJacob Faibussowitsch default: 1730d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1731a12d352dSMatthew G. Knepley } 1732a12d352dSMatthew G. Knepley break; 1733e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 17349371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17359566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17369566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17379566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1738e5c487bfSMatthew G. Knepley break; 1739e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 17409371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17419371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17429566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17439566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17449566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17459566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1746e5c487bfSMatthew G. Knepley break; 17479f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 17489f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17499f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17509f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17519f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17529f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17539f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 17549f4ada15SMatthew G. Knepley break; 1755d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1756d71ae5a4SJacob Faibussowitsch break; 1757d71ae5a4SJacob Faibussowitsch default: 1758d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1759e5c487bfSMatthew G. Knepley } 17603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1761e5c487bfSMatthew G. Knepley } 1762e5c487bfSMatthew G. Knepley 1763c5aedaa3SMatthew G. Knepley static PetscErrorCode DrawPolygon_Private(DM dm, PetscDraw draw, PetscInt cell, PetscInt Nv, const PetscReal refVertices[], const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1764d71ae5a4SJacob Faibussowitsch { 1765e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1766e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1767c5aedaa3SMatthew G. Knepley PetscInt fillColor; 1768e5c487bfSMatthew G. Knepley 1769e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1771e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1772c5aedaa3SMatthew G. Knepley for (PetscInt v = 0; v < Nv; ++v) { 1773c5aedaa3SMatthew G. Knepley centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv; 1774c5aedaa3SMatthew G. Knepley centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv; 17759371c9d4SSatish Balay } 1776c5aedaa3SMatthew G. Knepley for (PetscInt e = 0; e < Nv; ++e) { 1777e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1778e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1779c5aedaa3SMatthew G. Knepley for (PetscInt d = 1; d <= edgeDiv; ++d) { 1780c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv; 1781c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv; 1782e5c487bfSMatthew G. Knepley } 17839566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1784c5aedaa3SMatthew G. Knepley for (PetscInt d = 0; d < edgeDiv; ++d) { 17859566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], fillColor, fillColor, fillColor)); 17869566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], PETSC_DRAW_BLACK)); 1787e5c487bfSMatthew G. Knepley } 1788e5c487bfSMatthew G. Knepley } 1789c5aedaa3SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1790c5aedaa3SMatthew G. Knepley } 1791c5aedaa3SMatthew G. Knepley 1792c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1793c5aedaa3SMatthew G. Knepley { 1794c5aedaa3SMatthew G. Knepley DMPolytopeType ct; 1795c5aedaa3SMatthew G. Knepley 1796c5aedaa3SMatthew G. Knepley PetscFunctionBegin; 1797c5aedaa3SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1798c5aedaa3SMatthew G. Knepley switch (ct) { 1799c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: { 1800c5aedaa3SMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1801c5aedaa3SMatthew G. Knepley 1802c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 1803c5aedaa3SMatthew G. Knepley } break; 1804c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: { 1805c5aedaa3SMatthew G. Knepley PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.}; 1806c5aedaa3SMatthew G. Knepley 1807c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 18089371c9d4SSatish Balay } break; 1809d71ae5a4SJacob Faibussowitsch default: 1810d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1811e5c487bfSMatthew G. Knepley } 18123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1813e5c487bfSMatthew G. Knepley } 1814e5c487bfSMatthew G. Knepley 1815d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1816d71ae5a4SJacob Faibussowitsch { 1817e412dcbdSMatthew G. Knepley PetscDraw draw; 1818e412dcbdSMatthew G. Knepley DM cdm; 1819e412dcbdSMatthew G. Knepley PetscSection coordSection; 1820e412dcbdSMatthew G. Knepley Vec coordinates; 1821c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1822e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1823c5aedaa3SMatthew G. Knepley PetscBool isnull, drawAffine; 1824c5aedaa3SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv; 1825e412dcbdSMatthew G. Knepley 1826e412dcbdSMatthew G. Knepley PetscFunctionBegin; 18279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 182863a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 1829c5aedaa3SMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree)); 1830c5aedaa3SMatthew G. Knepley drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE; 1831c5aedaa3SMatthew G. Knepley edgeDiv = cDegree + 1; 18329566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 18339566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 18349566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18359566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 18369566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 18379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18389566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1839e412dcbdSMatthew G. Knepley 18409566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18419566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 18423ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 18439566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1844e412dcbdSMatthew G. Knepley 1845c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 18469566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 18479566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1848e412dcbdSMatthew G. Knepley 1849cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1850cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1851c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1852ba2698f1SMatthew G. Knepley PetscInt numCoords; 1853c9c77995SMatthew G. Knepley PetscBool isDG; 1854cf3064d3SMatthew G. Knepley 1855c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 18561baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 18571baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1858c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1859cf3064d3SMatthew G. Knepley } 18609566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 18619566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 18629566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 18639566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 18643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1865e412dcbdSMatthew G. Knepley } 1866e412dcbdSMatthew G. Knepley 1867e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm) 1868e44f6aebSMatthew G. Knepley { 1869e44f6aebSMatthew G. Knepley DM odm = dm, rdm = dm, cdm; 1870e44f6aebSMatthew G. Knepley PetscFE fe; 1871e44f6aebSMatthew G. Knepley PetscSpace sp; 1872e44f6aebSMatthew G. Knepley PetscClassId id; 1873e44f6aebSMatthew G. Knepley PetscInt degree; 1874e44f6aebSMatthew G. Knepley PetscBool hoView = PETSC_TRUE; 1875e44f6aebSMatthew G. Knepley 1876e44f6aebSMatthew G. Knepley PetscFunctionBegin; 1877e44f6aebSMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1878e44f6aebSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL)); 1879e44f6aebSMatthew G. Knepley PetscOptionsEnd(); 1880e44f6aebSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dm)); 1881e44f6aebSMatthew G. Knepley *hdm = dm; 1882e44f6aebSMatthew G. Knepley if (!hoView) PetscFunctionReturn(PETSC_SUCCESS); 1883e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 1884e44f6aebSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 1885e44f6aebSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 1886e44f6aebSMatthew G. Knepley if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS); 1887e44f6aebSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &sp)); 1888e44f6aebSMatthew G. Knepley PetscCall(PetscSpaceGetDegree(sp, °ree, NULL)); 1889e44f6aebSMatthew G. Knepley for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) { 1890e44f6aebSMatthew G. Knepley DM cdm, rcdm; 1891e44f6aebSMatthew G. Knepley Mat In; 1892e44f6aebSMatthew G. Knepley Vec cl, rcl; 1893e44f6aebSMatthew G. Knepley 1894e44f6aebSMatthew G. Knepley PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm)); 1895c5aedaa3SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); 1896e44f6aebSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); 1897e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(odm, &cdm)); 1898e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(rdm, &rcdm)); 1899e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(odm, &cl)); 1900e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); 1901e44f6aebSMatthew G. Knepley PetscCall(DMSetCoarseDM(rcdm, cdm)); 1902e44f6aebSMatthew G. Knepley PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL)); 1903e44f6aebSMatthew G. Knepley PetscCall(MatMult(In, cl, rcl)); 1904e44f6aebSMatthew G. Knepley PetscCall(MatDestroy(&In)); 1905e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(rdm, rcl)); 1906e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&odm)); 1907e44f6aebSMatthew G. Knepley odm = rdm; 1908e44f6aebSMatthew G. Knepley } 1909e44f6aebSMatthew G. Knepley *hdm = rdm; 1910e44f6aebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1911e44f6aebSMatthew G. Knepley } 1912e44f6aebSMatthew G. Knepley 19131e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19141e50132fSMatthew G. Knepley #include <exodusII.h> 19156823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 19161e50132fSMatthew G. Knepley #endif 19171e50132fSMatthew G. Knepley 1918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1919d71ae5a4SJacob Faibussowitsch { 19205f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1921002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1922552f7358SJed Brown 1923552f7358SJed Brown PetscFunctionBegin; 1924552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1925552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 19279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 19289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 19309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 19319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 19325f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1933552f7358SJed Brown if (iascii) { 19348135c375SStefano Zampini PetscViewerFormat format; 19359566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 19361baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 19371baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1938c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1939c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 19409566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1941c6ccd67eSMatthew G. Knepley #else 1942c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1943552f7358SJed Brown #endif 1944e412dcbdSMatthew G. Knepley } else if (isvtk) { 19459566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1946e412dcbdSMatthew G. Knepley } else if (isdraw) { 1947e44f6aebSMatthew G. Knepley DM hdm; 1948e44f6aebSMatthew G. Knepley 1949e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 1950e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 1951e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 19528135c375SStefano Zampini } else if (isglvis) { 19539566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 19541e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19551e50132fSMatthew G. Knepley } else if (isexodus) { 19566823f3c5SBlaise Bourdin /* 19576823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 19586823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 1959da81f932SPierre Jolivet with ID 1, containing all cells. 19606823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 19616823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 19626823f3c5SBlaise Bourdin */ 19636823f3c5SBlaise Bourdin PetscInt numCS; 19649566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 19656823f3c5SBlaise Bourdin if (!numCS) { 19661e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 19679566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 19689566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 19699566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 19706823f3c5SBlaise Bourdin } 19719566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 19721e50132fSMatthew G. Knepley #endif 19735f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 19745f34f2dcSJed Brown } else if (iscgns) { 19755f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 19765f34f2dcSJed Brown #endif 19771baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1978cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 19799566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1980cb3ba0daSMatthew G. Knepley if (flg) { 1981cb3ba0daSMatthew G. Knepley Vec ranks; 19829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 19839566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 19849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1985cb3ba0daSMatthew G. Knepley } 1986002a2709SMatthew G. Knepley /* Optionally view a label */ 19879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1988002a2709SMatthew G. Knepley if (flg) { 1989002a2709SMatthew G. Knepley DMLabel label; 1990002a2709SMatthew G. Knepley Vec val; 1991002a2709SMatthew G. Knepley 19929566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 199328b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 19949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 19959566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 19969566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1997002a2709SMatthew G. Knepley } 19983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1999552f7358SJed Brown } 2000552f7358SJed Brown 20017f96f51bSksagiyam /*@ 2002a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 20037f96f51bSksagiyam 200420f4b53cSBarry Smith Collective 20057f96f51bSksagiyam 20067f96f51bSksagiyam Input Parameters: 2007a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 2008a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 20097f96f51bSksagiyam 20107f96f51bSksagiyam Level: advanced 20117f96f51bSksagiyam 20121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 20137f96f51bSksagiyam @*/ 2014d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 2015d71ae5a4SJacob Faibussowitsch { 20167f96f51bSksagiyam PetscBool ishdf5; 20177f96f51bSksagiyam 20187f96f51bSksagiyam PetscFunctionBegin; 20197f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20207f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20229566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20237f96f51bSksagiyam if (ishdf5) { 20247f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 20257f96f51bSksagiyam PetscViewerFormat format; 20269566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20277f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20287f96f51bSksagiyam IS globalPointNumbering; 20297f96f51bSksagiyam 20309566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20319566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 203398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 20347f96f51bSksagiyam #else 20357f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20367f96f51bSksagiyam #endif 20377f96f51bSksagiyam } 20389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20407f96f51bSksagiyam } 20417f96f51bSksagiyam 204277b8e257Sksagiyam /*@ 2043a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 204477b8e257Sksagiyam 204520f4b53cSBarry Smith Collective 204677b8e257Sksagiyam 204777b8e257Sksagiyam Input Parameters: 2048a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2049a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 205077b8e257Sksagiyam 205177b8e257Sksagiyam Level: advanced 205277b8e257Sksagiyam 20531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 205477b8e257Sksagiyam @*/ 2055d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2056d71ae5a4SJacob Faibussowitsch { 205777b8e257Sksagiyam PetscBool ishdf5; 205877b8e257Sksagiyam 205977b8e257Sksagiyam PetscFunctionBegin; 206077b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 206177b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 206477b8e257Sksagiyam if (ishdf5) { 206577b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 206677b8e257Sksagiyam PetscViewerFormat format; 20679566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 206877b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20699566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 2070fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 207177b8e257Sksagiyam #else 207277b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 207377b8e257Sksagiyam #endif 207477b8e257Sksagiyam } 20759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 20763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207777b8e257Sksagiyam } 207877b8e257Sksagiyam 2079bd6565f1Sksagiyam /*@ 2080a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2081bd6565f1Sksagiyam 208220f4b53cSBarry Smith Collective 2083bd6565f1Sksagiyam 2084bd6565f1Sksagiyam Input Parameters: 2085a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2086a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2087bd6565f1Sksagiyam 2088bd6565f1Sksagiyam Level: advanced 2089bd6565f1Sksagiyam 20901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2091bd6565f1Sksagiyam @*/ 2092d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2093d71ae5a4SJacob Faibussowitsch { 2094bd6565f1Sksagiyam PetscBool ishdf5; 2095bd6565f1Sksagiyam 2096bd6565f1Sksagiyam PetscFunctionBegin; 2097bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2098bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21009566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2101bd6565f1Sksagiyam if (ishdf5) { 2102bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2103bd6565f1Sksagiyam IS globalPointNumbering; 2104bd6565f1Sksagiyam PetscViewerFormat format; 2105bd6565f1Sksagiyam 21069566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2107bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21089566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 21099566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 21109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 211198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2112bd6565f1Sksagiyam #else 2113bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2114bd6565f1Sksagiyam #endif 2115bd6565f1Sksagiyam } 21169566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 21173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2118bd6565f1Sksagiyam } 2119bd6565f1Sksagiyam 2120021affd3Sksagiyam /*@ 2121a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2122021affd3Sksagiyam 212320f4b53cSBarry Smith Collective 2124021affd3Sksagiyam 2125021affd3Sksagiyam Input Parameters: 2126a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2127a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 21280318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL` 2129021affd3Sksagiyam 2130021affd3Sksagiyam Level: advanced 2131021affd3Sksagiyam 2132021affd3Sksagiyam Notes: 2133420bcc1bSBarry Smith 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. 2134021affd3Sksagiyam 21350318f8a0SStefano Zampini 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 (or in case `sectiondm` is `NULL`) 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. 2136021affd3Sksagiyam 21371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2138021affd3Sksagiyam @*/ 2139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2140d71ae5a4SJacob Faibussowitsch { 2141021affd3Sksagiyam PetscBool ishdf5; 2142021affd3Sksagiyam 2143021affd3Sksagiyam PetscFunctionBegin; 2144021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2145021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21460318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2147021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21499566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2150021affd3Sksagiyam if (ishdf5) { 2151021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 21529566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2153021affd3Sksagiyam #else 2154021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2155021affd3Sksagiyam #endif 2156021affd3Sksagiyam } 21579566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 21583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2159021affd3Sksagiyam } 2160021affd3Sksagiyam 21613e97647fSksagiyam /*@ 21623e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 21633e97647fSksagiyam 216420f4b53cSBarry Smith Collective 21653e97647fSksagiyam 21663e97647fSksagiyam Input Parameters: 2167a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2168a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 21690318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 21703e97647fSksagiyam - vec - The global vector to be saved 21713e97647fSksagiyam 21723e97647fSksagiyam Level: advanced 21733e97647fSksagiyam 21743e97647fSksagiyam Notes: 21750318f8a0SStefano Zampini 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 (or in case `sectiondm` is `NULL`) 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. 21763e97647fSksagiyam 217760225df5SJacob Faibussowitsch Calling sequence: 2178a1cb98faSBarry Smith .vb 2179a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2180a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2181a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2182a1cb98faSBarry Smith DMClone(dm, §iondm); 2183a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2184a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2185a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2186a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2187a1cb98faSBarry Smith PetscSectionSetUp(section); 2188a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2189a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2190a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2191a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2192a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2193a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2194a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2195a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2196a1cb98faSBarry Smith DMDestroy(§iondm); 2197a1cb98faSBarry Smith DMDestroy(&dm); 2198a1cb98faSBarry Smith .ve 21993e97647fSksagiyam 22001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22013e97647fSksagiyam @*/ 2202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2203d71ae5a4SJacob Faibussowitsch { 22043e97647fSksagiyam PetscBool ishdf5; 22053e97647fSksagiyam 22063e97647fSksagiyam PetscFunctionBegin; 22073e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22083e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22090318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 22103e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22113e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22123e97647fSksagiyam /* Check consistency */ 22133e97647fSksagiyam { 22143e97647fSksagiyam PetscSection section; 22153e97647fSksagiyam PetscBool includesConstraints; 22163e97647fSksagiyam PetscInt m, m1; 22173e97647fSksagiyam 22189566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22199566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 22209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22219566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22229566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 222363a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 22243e97647fSksagiyam } 22259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22273e97647fSksagiyam if (ishdf5) { 22283e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22299566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22303e97647fSksagiyam #else 22313e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22323e97647fSksagiyam #endif 22333e97647fSksagiyam } 22349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22363e97647fSksagiyam } 22373e97647fSksagiyam 22383e97647fSksagiyam /*@ 22393e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 22403e97647fSksagiyam 224120f4b53cSBarry Smith Collective 22423e97647fSksagiyam 22433e97647fSksagiyam Input Parameters: 2244a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2245a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 22460318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL` 22473e97647fSksagiyam - vec - The local vector to be saved 22483e97647fSksagiyam 22493e97647fSksagiyam Level: advanced 22503e97647fSksagiyam 2251a1cb98faSBarry Smith Note: 22520318f8a0SStefano Zampini 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 (or in case `sectiondm` is `NULL`) 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. 22533e97647fSksagiyam 225460225df5SJacob Faibussowitsch Calling sequence: 2255a1cb98faSBarry Smith .vb 2256a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2257a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2258a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2259a1cb98faSBarry Smith DMClone(dm, §iondm); 2260a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2261a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2262a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2263a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2264a1cb98faSBarry Smith PetscSectionSetUp(section); 2265a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2266a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2267a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2268a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2269a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2270a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2271a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2272a1cb98faSBarry Smith DMDestroy(§iondm); 2273a1cb98faSBarry Smith DMDestroy(&dm); 2274a1cb98faSBarry Smith .ve 22753e97647fSksagiyam 22761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22773e97647fSksagiyam @*/ 2278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2279d71ae5a4SJacob Faibussowitsch { 22803e97647fSksagiyam PetscBool ishdf5; 22813e97647fSksagiyam 22823e97647fSksagiyam PetscFunctionBegin; 22833e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22843e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22850318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 22863e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22873e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22883e97647fSksagiyam /* Check consistency */ 22893e97647fSksagiyam { 22903e97647fSksagiyam PetscSection section; 22913e97647fSksagiyam PetscBool includesConstraints; 22923e97647fSksagiyam PetscInt m, m1; 22933e97647fSksagiyam 22949566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22959566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 22969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22979566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22989566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 229963a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 23003e97647fSksagiyam } 23019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23033e97647fSksagiyam if (ishdf5) { 23043e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 23059566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 23063e97647fSksagiyam #else 23073e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23083e97647fSksagiyam #endif 23093e97647fSksagiyam } 23109566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23123e97647fSksagiyam } 23133e97647fSksagiyam 2314d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2315d71ae5a4SJacob Faibussowitsch { 2316d4f5a9a0SVaclav Hapla PetscBool ishdf5; 23172c40f234SMatthew G. Knepley 23182c40f234SMatthew G. Knepley PetscFunctionBegin; 23192c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23202c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2322d4f5a9a0SVaclav Hapla if (ishdf5) { 23232c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 23249c48423bSVaclav Hapla PetscViewerFormat format; 23259566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23269c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 23279566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2328509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23299566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 233098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23322c40f234SMatthew G. Knepley #else 23332c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2334552f7358SJed Brown #endif 233598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2336552f7358SJed Brown } 2337552f7358SJed Brown 2338ea8e1828Sksagiyam /*@ 2339a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2340ea8e1828Sksagiyam 234120f4b53cSBarry Smith Collective 2342ea8e1828Sksagiyam 2343ea8e1828Sksagiyam Input Parameters: 2344a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2345a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2346ea8e1828Sksagiyam 23472fe279fdSBarry Smith Output Parameter: 234820f4b53cSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded `DMPLEX`, where N is the global number of points; `NULL` if unneeded 2349dec9e869Sksagiyam 2350ea8e1828Sksagiyam Level: advanced 2351ea8e1828Sksagiyam 23521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2353a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2354ea8e1828Sksagiyam @*/ 2355d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2356d71ae5a4SJacob Faibussowitsch { 2357ea8e1828Sksagiyam PetscBool ishdf5; 2358ea8e1828Sksagiyam 2359ea8e1828Sksagiyam PetscFunctionBegin; 2360ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2361ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23624f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 23639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23649566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2365ea8e1828Sksagiyam if (ishdf5) { 2366ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2367ea8e1828Sksagiyam PetscViewerFormat format; 23689566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2369ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23709566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 237198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2372ea8e1828Sksagiyam #else 2373ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2374ea8e1828Sksagiyam #endif 2375ea8e1828Sksagiyam } 23769566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 23773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2378ea8e1828Sksagiyam } 2379ea8e1828Sksagiyam 23803e701f1cSksagiyam /*@ 2381a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 23823e701f1cSksagiyam 238320f4b53cSBarry Smith Collective 23843e701f1cSksagiyam 23853e701f1cSksagiyam Input Parameters: 2386a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2387a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2388a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 23893e701f1cSksagiyam 23903e701f1cSksagiyam Level: advanced 23913e701f1cSksagiyam 23921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2393a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 23943e701f1cSksagiyam @*/ 2395d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2396d71ae5a4SJacob Faibussowitsch { 23973e701f1cSksagiyam PetscBool ishdf5; 23983e701f1cSksagiyam 23993e701f1cSksagiyam PetscFunctionBegin; 24003e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24013e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2402c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24049566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24053e701f1cSksagiyam if (ishdf5) { 24063e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 24073e701f1cSksagiyam PetscViewerFormat format; 24089566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 24093e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24109566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 241198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 24123e701f1cSksagiyam #else 24133e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24143e701f1cSksagiyam #endif 24153e701f1cSksagiyam } 24169566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24183e701f1cSksagiyam } 24193e701f1cSksagiyam 2420b08ad5deSksagiyam /*@ 2421a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2422b08ad5deSksagiyam 242320f4b53cSBarry Smith Collective 2424b08ad5deSksagiyam 2425b08ad5deSksagiyam Input Parameters: 2426a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2427a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 242820f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2429b08ad5deSksagiyam 2430b08ad5deSksagiyam Level: advanced 2431b08ad5deSksagiyam 2432a1cb98faSBarry Smith Note: 2433a1cb98faSBarry Smith The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs. 2434e6368b79SVaclav Hapla 24351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2436a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2437b08ad5deSksagiyam @*/ 2438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2439d71ae5a4SJacob Faibussowitsch { 2440b08ad5deSksagiyam PetscBool ishdf5; 2441b08ad5deSksagiyam 2442b08ad5deSksagiyam PetscFunctionBegin; 2443b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2444b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2445e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2448b08ad5deSksagiyam if (ishdf5) { 2449b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2450b08ad5deSksagiyam PetscViewerFormat format; 2451b08ad5deSksagiyam 24529566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2453b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24549566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 245598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2456b08ad5deSksagiyam #else 2457b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2458b08ad5deSksagiyam #endif 2459b08ad5deSksagiyam } 24609566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 24613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2462b08ad5deSksagiyam } 2463b08ad5deSksagiyam 2464f84dd6b4Sksagiyam /*@ 2465a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2466f84dd6b4Sksagiyam 246720f4b53cSBarry Smith Collective 2468f84dd6b4Sksagiyam 2469f84dd6b4Sksagiyam Input Parameters: 2470a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2471a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 24720318f8a0SStefano Zampini . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL` 2473a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2474f84dd6b4Sksagiyam 2475a4e35b19SJacob Faibussowitsch Output Parameters: 247620f4b53cSBarry Smith + globalDofSF - The `PetscSF` 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) 247720f4b53cSBarry Smith - localDofSF - The `PetscSF` 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) 2478f84dd6b4Sksagiyam 2479f84dd6b4Sksagiyam Level: advanced 2480f84dd6b4Sksagiyam 2481f84dd6b4Sksagiyam Notes: 248220f4b53cSBarry Smith 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. 2483f84dd6b4Sksagiyam 24840318f8a0SStefano Zampini 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 (or in case `sectiondm` is `NULL`) 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. 2485f84dd6b4Sksagiyam 248620f4b53cSBarry Smith 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. 2487f84dd6b4Sksagiyam 2488f84dd6b4Sksagiyam Example using 2 processes: 2489a1cb98faSBarry Smith .vb 2490a1cb98faSBarry Smith NX (number of points on dm): 4 2491a1cb98faSBarry Smith sectionA : the on-disk section 2492a1cb98faSBarry Smith vecA : a vector associated with sectionA 2493a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2494a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2495a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2496f84dd6b4Sksagiyam 2497a1cb98faSBarry Smith rank 0 rank 1 2498a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2499a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2500a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2501a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2502a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2503a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2504a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2505a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2506a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2507a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2508a1cb98faSBarry Smith .ve 2509a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2510a1cb98faSBarry Smith 25111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2512f84dd6b4Sksagiyam @*/ 2513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2514d71ae5a4SJacob Faibussowitsch { 2515f84dd6b4Sksagiyam PetscBool ishdf5; 2516f84dd6b4Sksagiyam 2517f84dd6b4Sksagiyam PetscFunctionBegin; 2518f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2519f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25200318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2521f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2522f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 25234f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 25244f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 25259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2527f84dd6b4Sksagiyam if (ishdf5) { 2528f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 25299566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2530f84dd6b4Sksagiyam #else 2531f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2532f84dd6b4Sksagiyam #endif 2533f84dd6b4Sksagiyam } 25349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 25353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2536f84dd6b4Sksagiyam } 2537f84dd6b4Sksagiyam 25388be3dfe1Sksagiyam /*@ 25398be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 25408be3dfe1Sksagiyam 254120f4b53cSBarry Smith Collective 25428be3dfe1Sksagiyam 25438be3dfe1Sksagiyam Input Parameters: 2544a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2545a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 25460318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 2547a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 25488be3dfe1Sksagiyam - vec - The global vector to set values of 25498be3dfe1Sksagiyam 25508be3dfe1Sksagiyam Level: advanced 25518be3dfe1Sksagiyam 25528be3dfe1Sksagiyam Notes: 25530318f8a0SStefano Zampini 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 (or in case `sectiondm` is `NULL`) 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. 25548be3dfe1Sksagiyam 255560225df5SJacob Faibussowitsch Calling sequence: 2556a1cb98faSBarry Smith .vb 2557a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2558a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2559a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2560a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2561a1cb98faSBarry Smith DMClone(dm, §iondm); 2562a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2563a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2564a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2565a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2566a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2567a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2568a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2569a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2570a1cb98faSBarry Smith DMDestroy(§iondm); 2571a1cb98faSBarry Smith DMDestroy(&dm); 2572a1cb98faSBarry Smith .ve 25738be3dfe1Sksagiyam 25741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2575a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 25768be3dfe1Sksagiyam @*/ 2577d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2578d71ae5a4SJacob Faibussowitsch { 25798be3dfe1Sksagiyam PetscBool ishdf5; 25808be3dfe1Sksagiyam 25818be3dfe1Sksagiyam PetscFunctionBegin; 25828be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25838be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25840318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 25858be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 25868be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 25878be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 25888be3dfe1Sksagiyam /* Check consistency */ 25898be3dfe1Sksagiyam { 25908be3dfe1Sksagiyam PetscSection section; 25918be3dfe1Sksagiyam PetscBool includesConstraints; 25928be3dfe1Sksagiyam PetscInt m, m1; 25938be3dfe1Sksagiyam 25949566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 25959566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 25969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 25979566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 25989566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 259963a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 26008be3dfe1Sksagiyam } 26019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26038be3dfe1Sksagiyam if (ishdf5) { 26048be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26059566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26068be3dfe1Sksagiyam #else 26078be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26088be3dfe1Sksagiyam #endif 26098be3dfe1Sksagiyam } 26109566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26128be3dfe1Sksagiyam } 26138be3dfe1Sksagiyam 26148be3dfe1Sksagiyam /*@ 26158be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 26168be3dfe1Sksagiyam 261720f4b53cSBarry Smith Collective 26188be3dfe1Sksagiyam 26198be3dfe1Sksagiyam Input Parameters: 2620a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2621a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 26220318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL` 2623a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26248be3dfe1Sksagiyam - vec - The local vector to set values of 26258be3dfe1Sksagiyam 26268be3dfe1Sksagiyam Level: advanced 26278be3dfe1Sksagiyam 26288be3dfe1Sksagiyam Notes: 26290318f8a0SStefano Zampini 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 (or in case `sectiondm` is `NULL`) 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. 26308be3dfe1Sksagiyam 263160225df5SJacob Faibussowitsch Calling sequence: 2632a1cb98faSBarry Smith .vb 2633a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2634a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2635a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2636a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2637a1cb98faSBarry Smith DMClone(dm, §iondm); 2638a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2639a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2640a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2641a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2642a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2643a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2644a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2645a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2646a1cb98faSBarry Smith DMDestroy(§iondm); 2647a1cb98faSBarry Smith DMDestroy(&dm); 2648a1cb98faSBarry Smith .ve 26498be3dfe1Sksagiyam 26501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2651a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 26528be3dfe1Sksagiyam @*/ 2653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2654d71ae5a4SJacob Faibussowitsch { 26558be3dfe1Sksagiyam PetscBool ishdf5; 26568be3dfe1Sksagiyam 26578be3dfe1Sksagiyam PetscFunctionBegin; 26588be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26598be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26600318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 26618be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 26628be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 26638be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 26648be3dfe1Sksagiyam /* Check consistency */ 26658be3dfe1Sksagiyam { 26668be3dfe1Sksagiyam PetscSection section; 26678be3dfe1Sksagiyam PetscBool includesConstraints; 26688be3dfe1Sksagiyam PetscInt m, m1; 26698be3dfe1Sksagiyam 26709566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 26719566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 26729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 26739566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 26749566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 267563a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 26768be3dfe1Sksagiyam } 26779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26789566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26798be3dfe1Sksagiyam if (ishdf5) { 26808be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26819566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26828be3dfe1Sksagiyam #else 26838be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26848be3dfe1Sksagiyam #endif 26858be3dfe1Sksagiyam } 26869566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26888be3dfe1Sksagiyam } 26898be3dfe1Sksagiyam 2690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2691d71ae5a4SJacob Faibussowitsch { 2692552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2693552f7358SJed Brown 2694552f7358SJed Brown PetscFunctionBegin; 26959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 26969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 26979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 26989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 26996c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 27002e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 27012e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 27022e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 27032e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 27046bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 27056bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2706adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL)); 2707adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL)); 2708adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL)); 2709adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL)); 2710c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2711c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2712d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2713d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 27145f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 27153ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 27169566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 27179566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 27189566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 27199566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 27209566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 27219566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 272221027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 27239f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 27249566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 27259566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 27269566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 27271d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 27289566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 27299566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 27309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 27319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 27329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 27334e2e9504SJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.face_sf)); 27346725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 27356725e60dSJed Brown PetscCall(ISDestroy(&mesh->periodic.periodic_points)); 27369566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 27379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 27389566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 27399566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 27409566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 27419566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 27429566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 27439566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 27449566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 27459566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 27469566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2747552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 27489566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 27493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2750552f7358SJed Brown } 2751552f7358SJed Brown 2752d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2753d71ae5a4SJacob Faibussowitsch { 2754d02c7345SMatthew G. Knepley PetscSection sectionGlobal, sectionLocal; 2755acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 27569fca9976SJed Brown PetscInt localSize, localStart = 0; 2757837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2758b412c318SBarry Smith MatType mtype; 27591428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2760552f7358SJed Brown 2761552f7358SJed Brown PetscFunctionBegin; 27629566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2763b412c318SBarry Smith mtype = dm->mattype; 2764d02c7345SMatthew G. Knepley PetscCall(DMGetLocalSection(dm, §ionLocal)); 27659566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 27669566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 27679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 27689fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 27699566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 27709566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 27719566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 27729566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 27739566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2774acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 27759566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 27769566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 27779566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 27789566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 27799566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 27809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 27819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 27829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2783552f7358SJed Brown if (!isShell) { 2784837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 27859fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2786863027abSJed Brown PetscInt pStart, pEnd, p, dof, cdof, num_fields; 2787552f7358SJed Brown 27889566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 27899fca9976SJed Brown 27909fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 27919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2792863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 2793e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2794863027abSJed Brown switch (dm->blocking_type) { 27950e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 27969fca9976SJed Brown PetscInt bdof, offset; 2797a9d99c84SMatthew G. Knepley 27989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 27999fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 28009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 2801d02c7345SMatthew G. Knepley for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof; 2802d02c7345SMatthew G. Knepley // Signal block concatenation 2803d02c7345SMatthew G. Knepley if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof); 28041d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 28051d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 28061d17a0a3SMatthew G. Knepley if (dof) { 28079371c9d4SSatish Balay if (bs < 0) { 28089371c9d4SSatish Balay bs = bdof; 28099371c9d4SSatish Balay } else if (bs != bdof) { 28109371c9d4SSatish Balay bs = 1; 28119371c9d4SSatish Balay } 2812552f7358SJed Brown } 2813863027abSJed Brown } break; 2814863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2815863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2816863027abSJed Brown PetscInt num_comp, bdof, offset; 2817863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2818863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2819863027abSJed Brown if (dof < 0) continue; 2820863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2821863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2822863027abSJed Brown PetscAssert(dof % num_comp == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " field %" PetscInt_FMT " has %" PetscInt_FMT " dof, not divisible by %" PetscInt_FMT " component ", p, field, dof, num_comp); 2823863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2824863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2825863027abSJed Brown // Handle possibly constant block size (unlikely) 2826863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2827863027abSJed Brown if (dof) { 2828863027abSJed Brown if (bs < 0) { 2829863027abSJed Brown bs = bdof; 2830863027abSJed Brown } else if (bs != bdof) { 2831863027abSJed Brown bs = 1; 2832863027abSJed Brown } 2833863027abSJed Brown } 2834863027abSJed Brown } 2835863027abSJed Brown } break; 2836863027abSJed Brown } 28372a28c762SMatthew G Knepley } 28382a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2839e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2840e432b41dSStefano Zampini bsLocal[1] = bs; 28419566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2842e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2843e432b41dSStefano Zampini else bs = bsMinMax[0]; 28446fd5c86aSStefano Zampini bs = PetscMax(1, bs); 28459566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 28460682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 28479566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 28489566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 28490682b8bbSJed Brown } else { 28509566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 28519566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 28529566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2853552f7358SJed Brown } 28549fca9976SJed Brown { // Consolidate blocks 28559fca9976SJed Brown PetscInt nblocks = 0; 28569fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 28579fca9976SJed Brown if (pblocks[i] == 0) continue; 2858d02c7345SMatthew G. Knepley // Negative block size indicates the blocks should be concatenated 2859d02c7345SMatthew G. Knepley if (pblocks[i] < 0) { 2860d02c7345SMatthew G. Knepley pblocks[i] = -pblocks[i]; 2861d02c7345SMatthew G. Knepley pblocks[nblocks - 1] += pblocks[i]; 2862d02c7345SMatthew G. Knepley } else { 28639fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2864d02c7345SMatthew G. Knepley } 2865ad540459SPierre Jolivet for (PetscInt j = 1; j < pblocks[i]; j++) PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i + j]); 28669fca9976SJed Brown } 28679fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 28689fca9976SJed Brown } 28699fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2870aa0f6e3cSJed Brown } 28719566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 28723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2873552f7358SJed Brown } 2874552f7358SJed Brown 28757cd05799SMatthew G. Knepley /*@ 2876a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2877be36d101SStefano Zampini 2878a1cb98faSBarry Smith Not Collective 2879be36d101SStefano Zampini 2880be36d101SStefano Zampini Input Parameter: 288160225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2882be36d101SStefano Zampini 28832fe279fdSBarry Smith Output Parameter: 2884be36d101SStefano Zampini . subsection - The subdomain section 2885be36d101SStefano Zampini 2886be36d101SStefano Zampini Level: developer 2887be36d101SStefano Zampini 28881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 28897cd05799SMatthew G. Knepley @*/ 2890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2891d71ae5a4SJacob Faibussowitsch { 2892be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2893be36d101SStefano Zampini 2894be36d101SStefano Zampini PetscFunctionBegin; 2895be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2896be36d101SStefano Zampini if (!mesh->subdomainSection) { 2897be36d101SStefano Zampini PetscSection section; 2898be36d101SStefano Zampini PetscSF sf; 2899be36d101SStefano Zampini 29009566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 29019566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 2902eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 29039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2904be36d101SStefano Zampini } 2905be36d101SStefano Zampini *subsection = mesh->subdomainSection; 29063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2907be36d101SStefano Zampini } 2908be36d101SStefano Zampini 2909552f7358SJed Brown /*@ 291020f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2911552f7358SJed Brown 2912a1cb98faSBarry Smith Not Collective 2913552f7358SJed Brown 2914552f7358SJed Brown Input Parameter: 291560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2916552f7358SJed Brown 2917552f7358SJed Brown Output Parameters: 2918552f7358SJed Brown + pStart - The first mesh point 2919552f7358SJed Brown - pEnd - The upper bound for mesh points 2920552f7358SJed Brown 2921552f7358SJed Brown Level: beginner 2922552f7358SJed Brown 29231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2924552f7358SJed Brown @*/ 2925d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2926d71ae5a4SJacob Faibussowitsch { 2927552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2928552f7358SJed Brown 2929552f7358SJed Brown PetscFunctionBegin; 2930552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29319f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 29329f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 29333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2934552f7358SJed Brown } 2935552f7358SJed Brown 2936552f7358SJed Brown /*@ 293720f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 2938552f7358SJed Brown 2939a1cb98faSBarry Smith Not Collective 2940552f7358SJed Brown 2941552f7358SJed Brown Input Parameters: 294260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2943552f7358SJed Brown . pStart - The first mesh point 2944552f7358SJed Brown - pEnd - The upper bound for mesh points 2945552f7358SJed Brown 2946552f7358SJed Brown Level: beginner 2947552f7358SJed Brown 29481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2949552f7358SJed Brown @*/ 2950d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2951d71ae5a4SJacob Faibussowitsch { 2952552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2953552f7358SJed Brown 2954552f7358SJed Brown PetscFunctionBegin; 2955552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 29579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 295821027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 29593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2960552f7358SJed Brown } 2961552f7358SJed Brown 2962552f7358SJed Brown /*@ 2963eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2964552f7358SJed Brown 2965a1cb98faSBarry Smith Not Collective 2966552f7358SJed Brown 2967552f7358SJed Brown Input Parameters: 296860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2969a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2970552f7358SJed Brown 2971552f7358SJed Brown Output Parameter: 297220f4b53cSBarry Smith . size - The cone size for point `p` 2973552f7358SJed Brown 2974552f7358SJed Brown Level: beginner 2975552f7358SJed Brown 29761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2977552f7358SJed Brown @*/ 2978d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2979d71ae5a4SJacob Faibussowitsch { 2980552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2981552f7358SJed Brown 2982552f7358SJed Brown PetscFunctionBegin; 2983552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29844f572ea9SToby Isaac PetscAssertPointer(size, 3); 29859f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 29869f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 29873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2988552f7358SJed Brown } 2989552f7358SJed Brown 2990552f7358SJed Brown /*@ 2991eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2992552f7358SJed Brown 2993a1cb98faSBarry Smith Not Collective 2994552f7358SJed Brown 2995552f7358SJed Brown Input Parameters: 299660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2997a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 299820f4b53cSBarry Smith - size - The cone size for point `p` 2999552f7358SJed Brown 3000552f7358SJed Brown Level: beginner 3001552f7358SJed Brown 3002a1cb98faSBarry Smith Note: 3003a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 3004a1cb98faSBarry Smith 30051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 3006552f7358SJed Brown @*/ 3007d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 3008d71ae5a4SJacob Faibussowitsch { 3009552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3010552f7358SJed Brown 3011552f7358SJed Brown PetscFunctionBegin; 3012552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30139f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 30149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 30153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3016552f7358SJed Brown } 3017552f7358SJed Brown 3018552f7358SJed Brown /*@C 3019eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 3020552f7358SJed Brown 3021a1cb98faSBarry Smith Not Collective 3022552f7358SJed Brown 3023552f7358SJed Brown Input Parameters: 3024a1cb98faSBarry Smith + dm - The `DMPLEX` 3025a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3026552f7358SJed Brown 3027552f7358SJed Brown Output Parameter: 302820f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p` 3029552f7358SJed Brown 3030552f7358SJed Brown Level: beginner 3031552f7358SJed Brown 303260225df5SJacob Faibussowitsch Fortran Notes: 3033a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 3034a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 30353813dfbdSMatthew G Knepley 30361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3037552f7358SJed Brown @*/ 3038d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3039d71ae5a4SJacob Faibussowitsch { 3040552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3041552f7358SJed Brown PetscInt off; 3042552f7358SJed Brown 3043552f7358SJed Brown PetscFunctionBegin; 3044552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30454f572ea9SToby Isaac PetscAssertPointer(cone, 3); 30469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30478e3a54c0SPierre Jolivet *cone = PetscSafePointerPlusOffset(mesh->cones, off); 30483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3049552f7358SJed Brown } 3050552f7358SJed Brown 30510ce7577fSVaclav Hapla /*@C 30520ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 30530ce7577fSVaclav Hapla 3054a1cb98faSBarry Smith Not Collective 30550ce7577fSVaclav Hapla 30560ce7577fSVaclav Hapla Input Parameters: 3057a1cb98faSBarry Smith + dm - The `DMPLEX` 3058a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 30590ce7577fSVaclav Hapla 3060d8d19677SJose E. Roman Output Parameters: 306120f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 306220f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p` 30630ce7577fSVaclav Hapla 30640ce7577fSVaclav Hapla Level: intermediate 30650ce7577fSVaclav Hapla 30661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 30670ce7577fSVaclav Hapla @*/ 3068d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 3069d71ae5a4SJacob Faibussowitsch { 30700ce7577fSVaclav Hapla PetscSection cs, newcs; 30710ce7577fSVaclav Hapla PetscInt *cones; 30720ce7577fSVaclav Hapla PetscInt *newarr = NULL; 30730ce7577fSVaclav Hapla PetscInt n; 30740ce7577fSVaclav Hapla 30750ce7577fSVaclav Hapla PetscFunctionBegin; 30769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 30779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 30789566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 30790ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 30800ce7577fSVaclav Hapla if (pCones) { 30819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 30829566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 30830ce7577fSVaclav Hapla } 30843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30850ce7577fSVaclav Hapla } 30860ce7577fSVaclav Hapla 3087af9eab45SVaclav Hapla /*@ 3088af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3089d4636a37SVaclav Hapla 3090a1cb98faSBarry Smith Not Collective 3091d4636a37SVaclav Hapla 3092d4636a37SVaclav Hapla Input Parameters: 3093a1cb98faSBarry Smith + dm - The `DMPLEX` 3094a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3095d4636a37SVaclav Hapla 3096d4636a37SVaclav Hapla Output Parameter: 3097af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 3098d4636a37SVaclav Hapla 3099d4636a37SVaclav Hapla Level: advanced 3100d4636a37SVaclav Hapla 3101af9eab45SVaclav Hapla Notes: 310220f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3103af9eab45SVaclav Hapla 3104a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3105a1cb98faSBarry Smith 31061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3107a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3108d4636a37SVaclav Hapla @*/ 3109d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3110d71ae5a4SJacob Faibussowitsch { 3111af9eab45SVaclav Hapla IS *expandedPointsAll; 3112af9eab45SVaclav Hapla PetscInt depth; 3113d4636a37SVaclav Hapla 3114d4636a37SVaclav Hapla PetscFunctionBegin; 3115af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3116af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31174f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 31189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3119af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 31209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 31219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 31223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3123af9eab45SVaclav Hapla } 3124af9eab45SVaclav Hapla 3125af9eab45SVaclav Hapla /*@ 3126af9eab45SVaclav 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). 3127af9eab45SVaclav Hapla 3128a1cb98faSBarry Smith Not Collective 3129af9eab45SVaclav Hapla 3130af9eab45SVaclav Hapla Input Parameters: 3131a1cb98faSBarry Smith + dm - The `DMPLEX` 3132a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3133af9eab45SVaclav Hapla 3134d8d19677SJose E. Roman Output Parameters: 3135a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3136af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3137af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3138af9eab45SVaclav Hapla 3139af9eab45SVaclav Hapla Level: advanced 3140af9eab45SVaclav Hapla 3141af9eab45SVaclav Hapla Notes: 3142a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3143af9eab45SVaclav Hapla 3144a4e35b19SJacob Faibussowitsch 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. 3145af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3146af9eab45SVaclav Hapla 3147a4e35b19SJacob Faibussowitsch 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\: 3148a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3149a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3150af9eab45SVaclav Hapla 31511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3152a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3153af9eab45SVaclav Hapla @*/ 3154d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3155d71ae5a4SJacob Faibussowitsch { 3156af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3157af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3158af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3159af9eab45SVaclav Hapla IS *expandedPoints_; 3160af9eab45SVaclav Hapla PetscSection *sections_; 3161af9eab45SVaclav Hapla 3162af9eab45SVaclav Hapla PetscFunctionBegin; 3163af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3164af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31654f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 31664f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 31674f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 31689566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 31699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 31709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 31719566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 31729566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3173af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3174af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 31759566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 31769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3177af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3179af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 31809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 31819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3182af9eab45SVaclav Hapla } else { 31839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3184af9eab45SVaclav Hapla } 3185af9eab45SVaclav Hapla } 31869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 31879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 31889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3189af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 31919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3192af9eab45SVaclav Hapla if (cn > 1) { 31939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 31949566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3195af9eab45SVaclav Hapla } else { 3196af9eab45SVaclav Hapla newarr[co] = arr[i]; 3197af9eab45SVaclav Hapla } 3198af9eab45SVaclav Hapla } 31999566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3200af9eab45SVaclav Hapla arr = newarr; 3201af9eab45SVaclav Hapla n = newn; 3202af9eab45SVaclav Hapla } 32039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3204af9eab45SVaclav Hapla *depth = depth_; 3205af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3206af9eab45SVaclav Hapla else { 32079566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 32089566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3209af9eab45SVaclav Hapla } 3210af9eab45SVaclav Hapla if (sections) *sections = sections_; 3211af9eab45SVaclav Hapla else { 32129566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 32139566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3214af9eab45SVaclav Hapla } 32153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3216af9eab45SVaclav Hapla } 3217af9eab45SVaclav Hapla 3218af9eab45SVaclav Hapla /*@ 3219a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3220af9eab45SVaclav Hapla 3221a1cb98faSBarry Smith Not Collective 3222af9eab45SVaclav Hapla 3223af9eab45SVaclav Hapla Input Parameters: 3224a1cb98faSBarry Smith + dm - The `DMPLEX` 3225a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3226af9eab45SVaclav Hapla 3227d8d19677SJose E. Roman Output Parameters: 3228a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3229af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3230af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3231af9eab45SVaclav Hapla 3232af9eab45SVaclav Hapla Level: advanced 3233af9eab45SVaclav Hapla 3234a1cb98faSBarry Smith Note: 3235a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3236af9eab45SVaclav Hapla 32371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3238a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3239af9eab45SVaclav Hapla @*/ 3240d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3241d71ae5a4SJacob Faibussowitsch { 3242af9eab45SVaclav Hapla PetscInt d, depth_; 3243af9eab45SVaclav Hapla 3244af9eab45SVaclav Hapla PetscFunctionBegin; 32459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 32461dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3247af9eab45SVaclav Hapla if (depth) *depth = 0; 3248af9eab45SVaclav Hapla if (expandedPoints) { 32499566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 32509566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3251af9eab45SVaclav Hapla } 3252af9eab45SVaclav Hapla if (sections) { 32539566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 32549566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3255af9eab45SVaclav Hapla } 32563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3257d4636a37SVaclav Hapla } 3258d4636a37SVaclav Hapla 3259552f7358SJed Brown /*@ 326092371b87SBarry 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 3261552f7358SJed Brown 3262a1cb98faSBarry Smith Not Collective 3263552f7358SJed Brown 3264552f7358SJed Brown Input Parameters: 326560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3266a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 326720f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p` 3268552f7358SJed Brown 3269552f7358SJed Brown Level: beginner 3270552f7358SJed Brown 3271a1cb98faSBarry Smith Note: 3272a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3273a1cb98faSBarry Smith 32741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3275552f7358SJed Brown @*/ 3276d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3277d71ae5a4SJacob Faibussowitsch { 3278552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3279552f7358SJed Brown PetscInt dof, off, c; 3280552f7358SJed Brown 3281552f7358SJed Brown PetscFunctionBegin; 3282552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32844f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 32859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3286db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3287db485b19SStefano Zampini PetscInt pStart, pEnd; 3288db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 328963a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3290552f7358SJed Brown for (c = 0; c < dof; ++c) { 329163a3b9bcSJacob Faibussowitsch PetscCheck(!(cone[c] < pStart) && !(cone[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", cone[c], pStart, pEnd); 3292552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3293552f7358SJed Brown } 3294db485b19SStefano Zampini } else { 3295db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3296db485b19SStefano Zampini } 32973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3298552f7358SJed Brown } 3299552f7358SJed Brown 3300552f7358SJed Brown /*@C 3301eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3302552f7358SJed Brown 3303a1cb98faSBarry Smith Not Collective 3304552f7358SJed Brown 3305552f7358SJed Brown Input Parameters: 330660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3307a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3308552f7358SJed Brown 3309552f7358SJed Brown Output Parameter: 331020f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 3311b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3312552f7358SJed Brown 3313552f7358SJed Brown Level: beginner 3314552f7358SJed Brown 3315a1cb98faSBarry Smith Note: 3316b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3317b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3318a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3319b5a892a1SMatthew G. Knepley with the identity. 3320b5a892a1SMatthew G. Knepley 332160225df5SJacob Faibussowitsch Fortran Notes: 3322a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3323a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 33243813dfbdSMatthew G Knepley 33251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3326552f7358SJed Brown @*/ 3327d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3328d71ae5a4SJacob Faibussowitsch { 3329552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3330552f7358SJed Brown PetscInt off; 3331552f7358SJed Brown 3332552f7358SJed Brown PetscFunctionBegin; 3333552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 333476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3335552f7358SJed Brown PetscInt dof; 33369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33374f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3338552f7358SJed Brown } 33399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 33400d644c17SKarl Rupp 3341552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 33423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3343552f7358SJed Brown } 3344552f7358SJed Brown 3345552f7358SJed Brown /*@ 3346eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3347552f7358SJed Brown 3348a1cb98faSBarry Smith Not Collective 3349552f7358SJed Brown 3350552f7358SJed Brown Input Parameters: 335160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3352a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3353b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3354b5a892a1SMatthew G. Knepley 3355552f7358SJed Brown Level: beginner 3356552f7358SJed Brown 3357a1cb98faSBarry Smith Notes: 3358a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3359a1cb98faSBarry Smith 3360a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3361a1cb98faSBarry Smith 33621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3363552f7358SJed Brown @*/ 3364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3365d71ae5a4SJacob Faibussowitsch { 3366552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3367552f7358SJed Brown PetscInt pStart, pEnd; 3368552f7358SJed Brown PetscInt dof, off, c; 3369552f7358SJed Brown 3370552f7358SJed Brown PetscFunctionBegin; 3371552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33734f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 33749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3375db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3376db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 337763a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3378552f7358SJed Brown for (c = 0; c < dof; ++c) { 3379552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3380552f7358SJed Brown 33819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 33821dca8a05SBarry Smith PetscCheck(!o || (o >= -(cdof + 1) && o < cdof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ". %" PetscInt_FMT ")", o, -(cdof + 1), cdof); 3383552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3384552f7358SJed Brown } 3385db485b19SStefano Zampini } else { 3386db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3387db485b19SStefano Zampini } 33883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3389552f7358SJed Brown } 3390552f7358SJed Brown 33917cd05799SMatthew G. Knepley /*@ 3392eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 33937cd05799SMatthew G. Knepley 3394a1cb98faSBarry Smith Not Collective 33957cd05799SMatthew G. Knepley 33967cd05799SMatthew G. Knepley Input Parameters: 339760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3398a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33997cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34007cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 34017cd05799SMatthew G. Knepley 34027cd05799SMatthew G. Knepley Level: beginner 34037cd05799SMatthew G. Knepley 34041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34057cd05799SMatthew G. Knepley @*/ 3406d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3407d71ae5a4SJacob Faibussowitsch { 3408552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3409552f7358SJed Brown PetscInt pStart, pEnd; 3410552f7358SJed Brown PetscInt dof, off; 3411552f7358SJed Brown 3412552f7358SJed Brown PetscFunctionBegin; 3413552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3414a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 341663a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 341763a3b9bcSJacob Faibussowitsch PetscCheck(!(conePoint < pStart) && !(conePoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", conePoint, pStart, pEnd); 34189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 341963a3b9bcSJacob Faibussowitsch PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof); 3420a03d55ffSStefano Zampini } 3421a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3422552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 34233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3424552f7358SJed Brown } 3425552f7358SJed Brown 34267cd05799SMatthew G. Knepley /*@ 3427eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 34287cd05799SMatthew G. Knepley 3429a1cb98faSBarry Smith Not Collective 34307cd05799SMatthew G. Knepley 34317cd05799SMatthew G. Knepley Input Parameters: 343260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3433a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34347cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34357cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 34367cd05799SMatthew G. Knepley 34377cd05799SMatthew G. Knepley Level: beginner 34387cd05799SMatthew G. Knepley 3439a1cb98faSBarry Smith Note: 3440a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3441b5a892a1SMatthew G. Knepley 34421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34437cd05799SMatthew G. Knepley @*/ 3444d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3445d71ae5a4SJacob Faibussowitsch { 344677c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 344777c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 344877c88f5bSMatthew G Knepley PetscInt dof, off; 344977c88f5bSMatthew G Knepley 345077c88f5bSMatthew G Knepley PetscFunctionBegin; 345177c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3452a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 345463a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 34559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 345663a3b9bcSJacob Faibussowitsch PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof); 3457a03d55ffSStefano Zampini } 3458a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 345977c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 34603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 346177c88f5bSMatthew G Knepley } 346277c88f5bSMatthew G Knepley 34639f4ada15SMatthew G. Knepley /*@C 34649f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 34659f4ada15SMatthew G. Knepley 34669f4ada15SMatthew G. Knepley Not collective 34679f4ada15SMatthew G. Knepley 34689f4ada15SMatthew G. Knepley Input Parameters: 34699f4ada15SMatthew G. Knepley + dm - The DMPlex 34709f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 34719f4ada15SMatthew G. Knepley 34729f4ada15SMatthew G. Knepley Output Parameters: 347320f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 347420f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34759f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34769f4ada15SMatthew G. Knepley 34779f4ada15SMatthew G. Knepley Level: beginner 34789f4ada15SMatthew G. Knepley 34799f4ada15SMatthew G. Knepley Notes: 34809f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34819f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 348220f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 34839f4ada15SMatthew G. Knepley with the identity. 34849f4ada15SMatthew G. Knepley 34859f4ada15SMatthew G. Knepley Fortran Notes: 348620f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 348720f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 34889f4ada15SMatthew G. Knepley 34891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 34909f4ada15SMatthew G. Knepley @*/ 34919f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 34929f4ada15SMatthew G. Knepley { 34939f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 34949f4ada15SMatthew G. Knepley 34959f4ada15SMatthew G. Knepley PetscFunctionBegin; 34969f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34979f4ada15SMatthew G. Knepley if (mesh->tr) { 34989f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 34999f4ada15SMatthew G. Knepley } else { 35009f4ada15SMatthew G. Knepley PetscInt off; 35019f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 35029f4ada15SMatthew G. Knepley PetscInt dof; 35039f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35049f4ada15SMatthew G. Knepley if (dof) { 35054f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 35064f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 35079f4ada15SMatthew G. Knepley } 35089f4ada15SMatthew G. Knepley } 35099f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 35108e3a54c0SPierre Jolivet if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off); 35118e3a54c0SPierre Jolivet if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off); 35129f4ada15SMatthew G. Knepley } 35133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35149f4ada15SMatthew G. Knepley } 35159f4ada15SMatthew G. Knepley 35169f4ada15SMatthew G. Knepley /*@C 35179f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 35189f4ada15SMatthew G. Knepley 351920f4b53cSBarry Smith Not Collective 35209f4ada15SMatthew G. Knepley 35219f4ada15SMatthew G. Knepley Input Parameters: 35229f4ada15SMatthew G. Knepley + dm - The DMPlex 352320f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35249f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 352520f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 35269f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 35279f4ada15SMatthew G. Knepley 35289f4ada15SMatthew G. Knepley Level: beginner 35299f4ada15SMatthew G. Knepley 35309f4ada15SMatthew G. Knepley Notes: 35319f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 35329f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 353320f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 35349f4ada15SMatthew G. Knepley with the identity. 35359f4ada15SMatthew G. Knepley 353660225df5SJacob Faibussowitsch Fortran Notes: 353720f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 353820f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 35399f4ada15SMatthew G. Knepley 35401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 35419f4ada15SMatthew G. Knepley @*/ 35429f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 35439f4ada15SMatthew G. Knepley { 35449f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 35459f4ada15SMatthew G. Knepley 35469f4ada15SMatthew G. Knepley PetscFunctionBegin; 35479f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35489f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 35493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35509f4ada15SMatthew G. Knepley } 35519f4ada15SMatthew G. Knepley 3552552f7358SJed Brown /*@ 3553eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3554552f7358SJed Brown 3555a1cb98faSBarry Smith Not Collective 3556552f7358SJed Brown 3557552f7358SJed Brown Input Parameters: 355860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3559a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3560552f7358SJed Brown 3561552f7358SJed Brown Output Parameter: 356220f4b53cSBarry Smith . size - The support size for point `p` 3563552f7358SJed Brown 3564552f7358SJed Brown Level: beginner 3565552f7358SJed Brown 35661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3567552f7358SJed Brown @*/ 3568d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3569d71ae5a4SJacob Faibussowitsch { 3570552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3571552f7358SJed Brown 3572552f7358SJed Brown PetscFunctionBegin; 3573552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35744f572ea9SToby Isaac PetscAssertPointer(size, 3); 35759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 35763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3577552f7358SJed Brown } 3578552f7358SJed Brown 3579552f7358SJed Brown /*@ 3580eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3581552f7358SJed Brown 3582a1cb98faSBarry Smith Not Collective 3583552f7358SJed Brown 3584552f7358SJed Brown Input Parameters: 358560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3586a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 358720f4b53cSBarry Smith - size - The support size for point `p` 3588552f7358SJed Brown 3589a1cb98faSBarry Smith Level: beginner 3590552f7358SJed Brown 3591552f7358SJed Brown Note: 359220f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3593552f7358SJed Brown 35941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3595552f7358SJed Brown @*/ 3596d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3597d71ae5a4SJacob Faibussowitsch { 3598552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3599552f7358SJed Brown 3600552f7358SJed Brown PetscFunctionBegin; 3601552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 36033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3604552f7358SJed Brown } 3605552f7358SJed Brown 3606552f7358SJed Brown /*@C 3607eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3608552f7358SJed Brown 3609a1cb98faSBarry Smith Not Collective 3610552f7358SJed Brown 3611552f7358SJed Brown Input Parameters: 361260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3613a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3614552f7358SJed Brown 3615552f7358SJed Brown Output Parameter: 361620f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p` 3617552f7358SJed Brown 3618552f7358SJed Brown Level: beginner 3619552f7358SJed Brown 362060225df5SJacob Faibussowitsch Fortran Notes: 3621a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3622a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 36233813dfbdSMatthew G Knepley 36241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3625552f7358SJed Brown @*/ 3626d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3627d71ae5a4SJacob Faibussowitsch { 3628552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3629552f7358SJed Brown PetscInt off; 3630552f7358SJed Brown 3631552f7358SJed Brown PetscFunctionBegin; 3632552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36334f572ea9SToby Isaac PetscAssertPointer(support, 3); 36349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 36358e3a54c0SPierre Jolivet *support = PetscSafePointerPlusOffset(mesh->supports, off); 36363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3637552f7358SJed Brown } 3638552f7358SJed Brown 3639552f7358SJed Brown /*@ 364092371b87SBarry 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 3641552f7358SJed Brown 3642a1cb98faSBarry Smith Not Collective 3643552f7358SJed Brown 3644552f7358SJed Brown Input Parameters: 364560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3646a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 364720f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p` 3648552f7358SJed Brown 3649552f7358SJed Brown Level: beginner 3650552f7358SJed Brown 3651a1cb98faSBarry Smith Note: 3652a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3653a1cb98faSBarry Smith 36541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3655552f7358SJed Brown @*/ 3656d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3657d71ae5a4SJacob Faibussowitsch { 3658552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3659552f7358SJed Brown PetscInt pStart, pEnd; 3660552f7358SJed Brown PetscInt dof, off, c; 3661552f7358SJed Brown 3662552f7358SJed Brown PetscFunctionBegin; 3663552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36664f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 36679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 366863a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3669552f7358SJed Brown for (c = 0; c < dof; ++c) { 367063a3b9bcSJacob Faibussowitsch PetscCheck(!(support[c] < pStart) && !(support[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", support[c], pStart, pEnd); 3671552f7358SJed Brown mesh->supports[off + c] = support[c]; 3672552f7358SJed Brown } 36733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3674552f7358SJed Brown } 3675552f7358SJed Brown 36767cd05799SMatthew G. Knepley /*@ 3677eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 36787cd05799SMatthew G. Knepley 3679a1cb98faSBarry Smith Not Collective 36807cd05799SMatthew G. Knepley 36817cd05799SMatthew G. Knepley Input Parameters: 368260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3683a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36847cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 36857cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 36867cd05799SMatthew G. Knepley 36877cd05799SMatthew G. Knepley Level: beginner 36887cd05799SMatthew G. Knepley 36891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36907cd05799SMatthew G. Knepley @*/ 3691d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3692d71ae5a4SJacob Faibussowitsch { 3693552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3694552f7358SJed Brown PetscInt pStart, pEnd; 3695552f7358SJed Brown PetscInt dof, off; 3696552f7358SJed Brown 3697552f7358SJed Brown PetscFunctionBegin; 3698552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 37009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 37019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 370263a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 370363a3b9bcSJacob Faibussowitsch PetscCheck(!(supportPoint < pStart) && !(supportPoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", supportPoint, pStart, pEnd); 370463a3b9bcSJacob Faibussowitsch PetscCheck(supportPos < dof, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", supportPos, p, dof); 3705552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 37063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3707552f7358SJed Brown } 3708552f7358SJed Brown 3709b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3710d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3711d71ae5a4SJacob Faibussowitsch { 3712b5a892a1SMatthew G. Knepley switch (ct) { 3713b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3714b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3715b5a892a1SMatthew G. Knepley break; 3716b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3717b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3718b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3719b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3720b5a892a1SMatthew G. Knepley break; 3721b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3722b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3723b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3724b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3725b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3726b5a892a1SMatthew G. Knepley break; 3727d71ae5a4SJacob Faibussowitsch default: 3728d71ae5a4SJacob Faibussowitsch return o; 3729b5a892a1SMatthew G. Knepley } 3730b5a892a1SMatthew G. Knepley return o; 3731b5a892a1SMatthew G. Knepley } 3732b5a892a1SMatthew G. Knepley 3733b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3734d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3735d71ae5a4SJacob Faibussowitsch { 3736b5a892a1SMatthew G. Knepley switch (ct) { 3737b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3738b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3739b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3740b5a892a1SMatthew G. Knepley break; 3741b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3742b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3743b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3744b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3745b5a892a1SMatthew G. Knepley break; 3746b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3747b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3748b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3749b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3750b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3751b5a892a1SMatthew G. Knepley break; 3752d71ae5a4SJacob Faibussowitsch default: 3753d71ae5a4SJacob Faibussowitsch return o; 3754b5a892a1SMatthew G. Knepley } 3755b5a892a1SMatthew G. Knepley return o; 3756b5a892a1SMatthew G. Knepley } 3757b5a892a1SMatthew G. Knepley 3758b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3759d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3760d71ae5a4SJacob Faibussowitsch { 3761b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3762b5a892a1SMatthew G. Knepley 3763b5a892a1SMatthew G. Knepley PetscFunctionBegin; 37649566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3765b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3766b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3767b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3768b5a892a1SMatthew G. Knepley 37699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 37709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 37719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3772b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3773b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3774b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3775b5a892a1SMatthew G. Knepley 37769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3777b5a892a1SMatthew G. Knepley switch (ct) { 3778b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 37799566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37809566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3781b5a892a1SMatthew G. Knepley break; 3782b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 37839566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37849566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37859566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3786b5a892a1SMatthew G. Knepley break; 3787b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 37889566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37899566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37909566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 37919566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3792b5a892a1SMatthew G. Knepley break; 3793d71ae5a4SJacob Faibussowitsch default: 3794d71ae5a4SJacob Faibussowitsch break; 3795b5a892a1SMatthew G. Knepley } 3796b5a892a1SMatthew G. Knepley } 3797b5a892a1SMatthew G. Knepley } 37983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3799b5a892a1SMatthew G. Knepley } 3800b5a892a1SMatthew G. Knepley 380109015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 380209015e70SStefano Zampini { 380309015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 380409015e70SStefano Zampini 380509015e70SStefano Zampini PetscFunctionBeginHot; 380609015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 380709015e70SStefano Zampini if (useCone) { 380809015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 380909015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 381009015e70SStefano Zampini } else { 381109015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 381209015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 381309015e70SStefano Zampini } 381409015e70SStefano Zampini } else { 381509015e70SStefano Zampini if (useCone) { 381609015e70SStefano Zampini const PetscSection s = mesh->coneSection; 381709015e70SStefano Zampini const PetscInt ps = p - s->pStart; 381809015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 381909015e70SStefano Zampini 382009015e70SStefano Zampini *size = s->atlasDof[ps]; 382109015e70SStefano Zampini *arr = mesh->cones + off; 382209015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 382309015e70SStefano Zampini } else { 382409015e70SStefano Zampini const PetscSection s = mesh->supportSection; 382509015e70SStefano Zampini const PetscInt ps = p - s->pStart; 382609015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 382709015e70SStefano Zampini 382809015e70SStefano Zampini *size = s->atlasDof[ps]; 382909015e70SStefano Zampini *arr = mesh->supports + off; 383009015e70SStefano Zampini } 383109015e70SStefano Zampini } 383209015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 383309015e70SStefano Zampini } 383409015e70SStefano Zampini 383509015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 383609015e70SStefano Zampini { 383709015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 383809015e70SStefano Zampini 383909015e70SStefano Zampini PetscFunctionBeginHot; 384009015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 384109015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 384209015e70SStefano Zampini } 384309015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 384409015e70SStefano Zampini } 384509015e70SStefano Zampini 3846d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3847d71ae5a4SJacob Faibussowitsch { 3848b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3849b5a892a1SMatthew G. Knepley PetscInt *closure; 3850b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3851b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3852b5a892a1SMatthew G. Knepley 3853b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3854b5a892a1SMatthew G. Knepley if (ornt) { 38559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3856476787b7SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN; 3857b5a892a1SMatthew G. Knepley } 3858b5a892a1SMatthew G. Knepley if (*points) { 3859b5a892a1SMatthew G. Knepley closure = *points; 3860b5a892a1SMatthew G. Knepley } else { 3861b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 38629566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 38639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3864b5a892a1SMatthew G. Knepley } 386509015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3866b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3867b5a892a1SMatthew G. Knepley closure[off++] = p; 3868b5a892a1SMatthew G. Knepley closure[off++] = 0; 3869b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3870b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3871b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3872b5a892a1SMatthew G. Knepley } 3873b5a892a1SMatthew G. Knepley } else { 387485036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt); 3875b5a892a1SMatthew G. Knepley 3876b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3877b5a892a1SMatthew G. Knepley closure[off++] = p; 3878b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3879b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3880b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3881b5a892a1SMatthew G. Knepley 38829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3883b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3884b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3885b5a892a1SMatthew G. Knepley } 3886b5a892a1SMatthew G. Knepley } 388709015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3888b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3889b5a892a1SMatthew G. Knepley if (points) *points = closure; 38903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3891b5a892a1SMatthew G. Knepley } 3892b5a892a1SMatthew G. Knepley 3893d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3894d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3895d71ae5a4SJacob Faibussowitsch { 389685036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o); 3897b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3898b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3899b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3900b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3901b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3902b5a892a1SMatthew G. Knepley 3903b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39049566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 390509015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 39069566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3907b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3908b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3909b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39109371c9d4SSatish Balay if (*points) { 39119371c9d4SSatish Balay pts = *points; 39129371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3913b5a892a1SMatthew G. Knepley c = 0; 3914b5a892a1SMatthew G. Knepley pts[c++] = point; 3915b5a892a1SMatthew G. Knepley pts[c++] = o; 39169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 39179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 39189371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39199371c9d4SSatish Balay pts[c++] = closure[cl]; 39209371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39219371c9d4SSatish Balay } 39229566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 39239371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39249371c9d4SSatish Balay pts[c++] = closure[cl]; 39259371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39269371c9d4SSatish Balay } 39279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3928b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 39299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3930b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3931b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3932b5a892a1SMatthew G. Knepley } 393309015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 3934b5a892a1SMatthew G. Knepley if (dim >= 3) { 3935b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3936b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3937b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3938b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3939b5a892a1SMatthew G. Knepley 39409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 394185036b15SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 394209015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3943b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3944b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3945b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3946b5a892a1SMatthew G. Knepley 39479371c9d4SSatish Balay for (i = 0; i < c; i += 2) 39489371c9d4SSatish Balay if (pts[i] == cp) break; 3949b5a892a1SMatthew G. Knepley if (i == c) { 39509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3951b5a892a1SMatthew G. Knepley pts[c++] = cp; 3952b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3953b5a892a1SMatthew G. Knepley } 3954b5a892a1SMatthew G. Knepley } 395509015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3956b5a892a1SMatthew G. Knepley } 3957b5a892a1SMatthew G. Knepley } 3958b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3959b5a892a1SMatthew G. Knepley *points = pts; 39603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3961b5a892a1SMatthew G. Knepley } 3962b5a892a1SMatthew G. Knepley 3963d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3964d71ae5a4SJacob Faibussowitsch { 3965b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3966b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3967b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3968b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3969b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3970b5a892a1SMatthew G. Knepley 3971b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3973b5a892a1SMatthew G. Knepley if (depth == 1) { 39749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 39753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3976b5a892a1SMatthew G. Knepley } 39779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3978476787b7SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN; 3979c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 39809566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 39813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3982b5a892a1SMatthew G. Knepley } 39839566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3984b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3985b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3986b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39879566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 39889371c9d4SSatish Balay if (*points) { 39899371c9d4SSatish Balay closure = *points; 39909371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3991b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3992b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3993b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3994b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3995b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3996b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3997b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3998b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3999b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 4000b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 400185036b15SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangement(qt, o); 400209015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 4003b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 4004b5a892a1SMatthew G. Knepley 4005b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 400685036b15SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2; 400763a3b9bcSJacob Faibussowitsch PetscCheck(!o || !(o >= nO || o < -nO), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ") for %s %" PetscInt_FMT, o, -nO, nO, DMPolytopeTypes[qt], q); 4008b5a892a1SMatthew G. Knepley } 400909015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4010b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4011b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 4012b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 4013b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 40149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 4015b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 4016b5a892a1SMatthew G. Knepley PetscInt c; 4017b5a892a1SMatthew G. Knepley 4018b5a892a1SMatthew G. Knepley /* Check for duplicate */ 4019b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 4020b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 4021b5a892a1SMatthew G. Knepley } 4022b5a892a1SMatthew G. Knepley if (c == closureSize) { 4023b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 4024b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 4025b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 4026b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 4027b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4028b5a892a1SMatthew G. Knepley } 4029b5a892a1SMatthew G. Knepley } 403009015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4031b5a892a1SMatthew G. Knepley } 40329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 4033b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4034b5a892a1SMatthew G. Knepley if (points) *points = closure; 40353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4036b5a892a1SMatthew G. Knepley } 4037b5a892a1SMatthew G. Knepley 4038552f7358SJed Brown /*@C 4039eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4040552f7358SJed Brown 4041a1cb98faSBarry Smith Not Collective 4042552f7358SJed Brown 4043552f7358SJed Brown Input Parameters: 4044a1cb98faSBarry Smith + dm - The `DMPLEX` 4045b5a892a1SMatthew G. Knepley . p - The mesh point 4046a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 4047552f7358SJed Brown 40486b867d5aSJose E. Roman Input/Output Parameter: 40496b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 405020f4b53cSBarry Smith if `NULL` on input, internal storage will be returned, otherwise the provided array is used 40516b867d5aSJose E. Roman 40526b867d5aSJose E. Roman Output Parameter: 405320f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4054552f7358SJed Brown 4055a1cb98faSBarry Smith Level: beginner 4056a1cb98faSBarry Smith 4057552f7358SJed Brown Note: 405820f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4059552f7358SJed Brown 406060225df5SJacob Faibussowitsch Fortran Notes: 406120f4b53cSBarry Smith The `numPoints` argument is not present in the Fortran binding since it is internal to the array. 40623813dfbdSMatthew G Knepley 40631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4064552f7358SJed Brown @*/ 4065d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4066d71ae5a4SJacob Faibussowitsch { 4067b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4068552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40694f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 40704f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 40719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 40723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40739bf0dad6SMatthew G. Knepley } 40749bf0dad6SMatthew G. Knepley 4075552f7358SJed Brown /*@C 4076eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4077552f7358SJed Brown 4078a1cb98faSBarry Smith Not Collective 4079552f7358SJed Brown 4080552f7358SJed Brown Input Parameters: 4081a1cb98faSBarry Smith + dm - The `DMPLEX` 4082b5a892a1SMatthew G. Knepley . p - The mesh point 4083a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 408420f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4085b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4086552f7358SJed Brown 4087a1cb98faSBarry Smith Level: beginner 4088a1cb98faSBarry Smith 4089552f7358SJed Brown Note: 409020f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4091552f7358SJed Brown 40921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4093552f7358SJed Brown @*/ 4094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4095d71ae5a4SJacob Faibussowitsch { 4096b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4097552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40984ff43b2cSJed Brown if (numPoints) *numPoints = 0; 40999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 41003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4101552f7358SJed Brown } 4102552f7358SJed Brown 4103552f7358SJed Brown /*@ 4104eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4105552f7358SJed Brown 4106a1cb98faSBarry Smith Not Collective 4107552f7358SJed Brown 4108552f7358SJed Brown Input Parameter: 410960225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4110552f7358SJed Brown 4111552f7358SJed Brown Output Parameters: 4112552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4113552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4114552f7358SJed Brown 4115552f7358SJed Brown Level: beginner 4116552f7358SJed Brown 41171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4118552f7358SJed Brown @*/ 4119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 4120d71ae5a4SJacob Faibussowitsch { 4121552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4122552f7358SJed Brown 4123552f7358SJed Brown PetscFunctionBegin; 4124552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41251baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 41261baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 41273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4128552f7358SJed Brown } 4129552f7358SJed Brown 4130d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4131d71ae5a4SJacob Faibussowitsch { 4132552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 41336302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4134552f7358SJed Brown 4135552f7358SJed Brown PetscFunctionBegin; 4136552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 41389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 41399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 41409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 41416302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41426302a7fbSVaclav Hapla if (maxSupportSize) { 41439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 41449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 41459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4146552f7358SJed Brown } 41473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4148552f7358SJed Brown } 4149552f7358SJed Brown 4150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4151d71ae5a4SJacob Faibussowitsch { 4152552f7358SJed Brown PetscFunctionBegin; 41539566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 4154dd072f5fSMatthew G. Knepley PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm)); 4155ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4156736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 415795602cf2SAlexis Marboeuf PetscSF sfNatural; 4158f94b4a02SBlaise Bourdin 41593dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 41609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 416195602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4162c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4163f94b4a02SBlaise Bourdin } 41643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4165552f7358SJed Brown } 4166552f7358SJed Brown 4167d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4168d71ae5a4SJacob Faibussowitsch { 41693dcd263cSBlaise Bourdin PetscInt i = 0; 41702adcc780SMatthew G. Knepley 41712adcc780SMatthew G. Knepley PetscFunctionBegin; 41729566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 41739566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4174c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 41753dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 41763dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 417795602cf2SAlexis Marboeuf PetscSF sfNatural; 41783dcd263cSBlaise Bourdin 41793dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 41809566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4181c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 418295602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4183c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 41843dcd263cSBlaise Bourdin break; 41853dcd263cSBlaise Bourdin } 41863dcd263cSBlaise Bourdin } 41873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41882adcc780SMatthew G. Knepley } 41892adcc780SMatthew G. Knepley 4190552f7358SJed Brown /*@ 4191eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4192552f7358SJed Brown 4193a1cb98faSBarry Smith Not Collective 4194552f7358SJed Brown 4195552f7358SJed Brown Input Parameter: 419660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4197552f7358SJed Brown 4198552f7358SJed Brown Level: beginner 4199552f7358SJed Brown 4200a1cb98faSBarry Smith Note: 4201a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4202a1cb98faSBarry Smith 42031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4204552f7358SJed Brown @*/ 4205d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4206d71ae5a4SJacob Faibussowitsch { 4207552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4208552f7358SJed Brown PetscInt *offsets; 4209552f7358SJed Brown PetscInt supportSize; 4210552f7358SJed Brown PetscInt pStart, pEnd, p; 4211552f7358SJed Brown 4212552f7358SJed Brown PetscFunctionBegin; 4213552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 421428b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 42159566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4216552f7358SJed Brown /* Calculate support sizes */ 42179566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4218552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4219552f7358SJed Brown PetscInt dof, off, c; 4220552f7358SJed Brown 42219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 422348a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4224552f7358SJed Brown } 42259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4226552f7358SJed Brown /* Calculate supports */ 42279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 42289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 42299566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4230552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4231552f7358SJed Brown PetscInt dof, off, c; 4232552f7358SJed Brown 42339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4235552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4236552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4237552f7358SJed Brown PetscInt offS; 4238552f7358SJed Brown 42399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 42400d644c17SKarl Rupp 4241552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4242552f7358SJed Brown ++offsets[q]; 4243552f7358SJed Brown } 4244552f7358SJed Brown } 42459566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 42469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 42473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4248552f7358SJed Brown } 4249552f7358SJed Brown 4250d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4251d71ae5a4SJacob Faibussowitsch { 4252277ea44aSLisandro Dalcin IS stratumIS; 4253277ea44aSLisandro Dalcin 4254277ea44aSLisandro Dalcin PetscFunctionBegin; 42553ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 425676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4257277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4258277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 42599566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4260277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 42619566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 42629371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 42639371c9d4SSatish Balay overlap = PETSC_TRUE; 42649371c9d4SSatish Balay break; 42659371c9d4SSatish Balay } 4266277ea44aSLisandro Dalcin } 426763a3b9bcSJacob Faibussowitsch PetscCheck(!overlap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ") overlaps with depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ")", depth, pStart, pEnd, level, qStart, qEnd); 4268277ea44aSLisandro Dalcin } 42699566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 42709566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 42719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 42723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4273277ea44aSLisandro Dalcin } 4274277ea44aSLisandro Dalcin 4275e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4276e91fa0a1SMatthew G. Knepley { 4277e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4278e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4279e91fa0a1SMatthew G. Knepley PetscInt dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT; 4280e91fa0a1SMatthew G. Knepley 4281e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4282e91fa0a1SMatthew G. Knepley { 4283e91fa0a1SMatthew G. Knepley DMLabel label2; 4284e91fa0a1SMatthew G. Knepley 4285e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4286e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4287e91fa0a1SMatthew G. Knepley } 4288e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4289e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4290e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4291e91fa0a1SMatthew G. Knepley 4292e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4293e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4294e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4295e91fa0a1SMatthew G. Knepley } 4296e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4297e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4298e91fa0a1SMatthew G. Knepley pMin[d] = PETSC_MAX_INT; 4299e91fa0a1SMatthew G. Knepley pMax[d] = PETSC_MIN_INT; 4300e91fa0a1SMatthew G. Knepley } 4301e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4302e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4303e91fa0a1SMatthew G. Knepley PetscInt d; 4304e91fa0a1SMatthew G. Knepley 4305e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4306e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4307e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4308e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4309e91fa0a1SMatthew G. Knepley } 4310e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4311e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4312e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4313e91fa0a1SMatthew G. Knepley } 4314e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4315e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4316e91fa0a1SMatthew G. Knepley } 4317e91fa0a1SMatthew G. Knepley 4318e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4319e91fa0a1SMatthew G. Knepley { 4320e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4321e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4322e91fa0a1SMatthew G. Knepley 4323e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4324e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4325e91fa0a1SMatthew G. Knepley { 4326e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 4327e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4328e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4329e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4330e91fa0a1SMatthew G. Knepley 4331e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4332e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4333e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4334e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4335e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4336e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4337e91fa0a1SMatthew G. Knepley ++numRoots; 4338e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4339e91fa0a1SMatthew G. Knepley ++numLeaves; 4340e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4341e91fa0a1SMatthew G. Knepley /* Isolated points */ 4342e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4343e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4344e91fa0a1SMatthew G. Knepley } 4345e91fa0a1SMatthew G. Knepley } 4346e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4347e91fa0a1SMatthew G. Knepley } 4348e91fa0a1SMatthew G. Knepley 4349e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 4350e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4351e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4352e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4353e91fa0a1SMatthew G. Knepley 4354e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4355e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4356e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4357e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4358e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4359e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4360e91fa0a1SMatthew G. Knepley } 4361e91fa0a1SMatthew G. Knepley } 4362e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4363e91fa0a1SMatthew G. Knepley } else { 4364e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4365e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4366e91fa0a1SMatthew G. Knepley 4367e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4368e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 4369e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4370e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4371e91fa0a1SMatthew G. Knepley 4372e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4373e91fa0a1SMatthew G. Knepley const PetscInt *support; 4374e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4375e91fa0a1SMatthew G. Knepley 4376e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4377e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4378e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4379e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4380e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4381e91fa0a1SMatthew G. Knepley } 4382e91fa0a1SMatthew G. Knepley } 4383e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4384e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4385e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4386e91fa0a1SMatthew G. Knepley } 4387e91fa0a1SMatthew G. Knepley } 4388e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4389e91fa0a1SMatthew G. Knepley } 4390e91fa0a1SMatthew G. Knepley 4391552f7358SJed Brown /*@ 4392a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4393552f7358SJed Brown 439420f4b53cSBarry Smith Collective 4395552f7358SJed Brown 4396552f7358SJed Brown Input Parameter: 439760225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4398552f7358SJed Brown 4399a1cb98faSBarry Smith Level: beginner 4400552f7358SJed Brown 4401552f7358SJed Brown Notes: 4402a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4403a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4404a4e35b19SJacob Faibussowitsch 4405a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4406a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4407a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4408b1bb481bSMatthew 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 4409a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4410a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4411a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4412552f7358SJed Brown 4413b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4414b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4415b1bb481bSMatthew 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 4416b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4417a1cb98faSBarry Smith .vb 4418a1cb98faSBarry Smith cone(c0) = {e0, v2} 4419a1cb98faSBarry Smith cone(e0) = {v0, v1} 4420a1cb98faSBarry Smith .ve 4421a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4422a1cb98faSBarry Smith .vb 4423a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4424a1cb98faSBarry Smith depth 1 = {e0, c0} 4425a1cb98faSBarry Smith .ve 4426b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4427b1bb481bSMatthew Knepley 4428a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4429552f7358SJed Brown 44301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4431552f7358SJed Brown @*/ 4432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4433d71ae5a4SJacob Faibussowitsch { 4434df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4435aa50250dSMatthew G. Knepley DMLabel label; 4436e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4437552f7358SJed Brown 4438552f7358SJed Brown PetscFunctionBegin; 4439552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 44409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4441277ea44aSLisandro Dalcin 4442e91fa0a1SMatthew G. Knepley // Create depth label 44439566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 44449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4445277ea44aSLisandro Dalcin 4446e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4447e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4448e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4449552f7358SJed Brown 4450bf4602e4SToby Isaac { /* just in case there is an empty process */ 4451bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4452bf4602e4SToby Isaac 44539566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4454712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 445548a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4456bf4602e4SToby Isaac } 44579566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 44589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 44593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4460552f7358SJed Brown } 4461552f7358SJed Brown 4462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4463d71ae5a4SJacob Faibussowitsch { 4464412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4465412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4466ba2698f1SMatthew G. Knepley 4467412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 44689566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 44699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 44709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4471ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4472ba2698f1SMatthew G. Knepley if (depth <= 1) { 4473ba2698f1SMatthew G. Knepley switch (pdepth) { 4474d71ae5a4SJacob Faibussowitsch case 0: 4475d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4476d71ae5a4SJacob Faibussowitsch break; 4477ba2698f1SMatthew G. Knepley case 1: 4478ba2698f1SMatthew G. Knepley switch (coneSize) { 4479d71ae5a4SJacob Faibussowitsch case 2: 4480d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4481d71ae5a4SJacob Faibussowitsch break; 4482d71ae5a4SJacob Faibussowitsch case 3: 4483d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4484d71ae5a4SJacob Faibussowitsch break; 4485ba2698f1SMatthew G. Knepley case 4: 4486ba2698f1SMatthew G. Knepley switch (dim) { 4487d71ae5a4SJacob Faibussowitsch case 2: 4488d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4489d71ae5a4SJacob Faibussowitsch break; 4490d71ae5a4SJacob Faibussowitsch case 3: 4491d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4492d71ae5a4SJacob Faibussowitsch break; 4493d71ae5a4SJacob Faibussowitsch default: 4494d71ae5a4SJacob Faibussowitsch break; 4495ba2698f1SMatthew G. Knepley } 4496ba2698f1SMatthew G. Knepley break; 4497d71ae5a4SJacob Faibussowitsch case 5: 4498d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4499d71ae5a4SJacob Faibussowitsch break; 4500d71ae5a4SJacob Faibussowitsch case 6: 4501d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4502d71ae5a4SJacob Faibussowitsch break; 4503d71ae5a4SJacob Faibussowitsch case 8: 4504d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4505d71ae5a4SJacob Faibussowitsch break; 4506d71ae5a4SJacob Faibussowitsch default: 4507d71ae5a4SJacob Faibussowitsch break; 4508ba2698f1SMatthew G. Knepley } 4509ba2698f1SMatthew G. Knepley } 4510ba2698f1SMatthew G. Knepley } else { 4511ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4512ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4513ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4514ba2698f1SMatthew G. Knepley switch (dim) { 4515ba2698f1SMatthew G. Knepley case 1: 4516ba2698f1SMatthew G. Knepley switch (coneSize) { 4517d71ae5a4SJacob Faibussowitsch case 2: 4518d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4519d71ae5a4SJacob Faibussowitsch break; 4520d71ae5a4SJacob Faibussowitsch default: 4521d71ae5a4SJacob Faibussowitsch break; 4522ba2698f1SMatthew G. Knepley } 4523ba2698f1SMatthew G. Knepley break; 4524ba2698f1SMatthew G. Knepley case 2: 4525ba2698f1SMatthew G. Knepley switch (coneSize) { 4526d71ae5a4SJacob Faibussowitsch case 3: 4527d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4528d71ae5a4SJacob Faibussowitsch break; 4529d71ae5a4SJacob Faibussowitsch case 4: 4530d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4531d71ae5a4SJacob Faibussowitsch break; 4532d71ae5a4SJacob Faibussowitsch default: 4533d71ae5a4SJacob Faibussowitsch break; 4534ba2698f1SMatthew G. Knepley } 4535ba2698f1SMatthew G. Knepley break; 4536ba2698f1SMatthew G. Knepley case 3: 4537ba2698f1SMatthew G. Knepley switch (coneSize) { 4538d71ae5a4SJacob Faibussowitsch case 4: 4539d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4540d71ae5a4SJacob Faibussowitsch break; 45419371c9d4SSatish Balay case 5: { 4542da9060c4SMatthew G. Knepley const PetscInt *cone; 4543da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4544da9060c4SMatthew G. Knepley 45459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 45469566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4547da9060c4SMatthew G. Knepley switch (faceConeSize) { 4548d71ae5a4SJacob Faibussowitsch case 3: 4549d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4550d71ae5a4SJacob Faibussowitsch break; 4551d71ae5a4SJacob Faibussowitsch case 4: 4552d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4553d71ae5a4SJacob Faibussowitsch break; 4554da9060c4SMatthew G. Knepley } 45559371c9d4SSatish Balay } break; 4556d71ae5a4SJacob Faibussowitsch case 6: 4557d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4558d71ae5a4SJacob Faibussowitsch break; 4559d71ae5a4SJacob Faibussowitsch default: 4560d71ae5a4SJacob Faibussowitsch break; 4561ba2698f1SMatthew G. Knepley } 4562ba2698f1SMatthew G. Knepley break; 4563d71ae5a4SJacob Faibussowitsch default: 4564d71ae5a4SJacob Faibussowitsch break; 4565ba2698f1SMatthew G. Knepley } 4566ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4567ba2698f1SMatthew G. Knepley switch (coneSize) { 4568d71ae5a4SJacob Faibussowitsch case 2: 4569d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4570d71ae5a4SJacob Faibussowitsch break; 4571d71ae5a4SJacob Faibussowitsch case 3: 4572d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4573d71ae5a4SJacob Faibussowitsch break; 4574d71ae5a4SJacob Faibussowitsch case 4: 4575d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4576d71ae5a4SJacob Faibussowitsch break; 4577d71ae5a4SJacob Faibussowitsch default: 4578d71ae5a4SJacob Faibussowitsch break; 4579ba2698f1SMatthew G. Knepley } 4580ba2698f1SMatthew G. Knepley } 4581ba2698f1SMatthew G. Knepley } 4582412e9a14SMatthew G. Knepley *pt = ct; 45833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4584ba2698f1SMatthew G. Knepley } 4585412e9a14SMatthew G. Knepley 4586412e9a14SMatthew G. Knepley /*@ 4587412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4588412e9a14SMatthew G. Knepley 458920f4b53cSBarry Smith Collective 4590412e9a14SMatthew G. Knepley 4591412e9a14SMatthew G. Knepley Input Parameter: 459260225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4593412e9a14SMatthew G. Knepley 4594412e9a14SMatthew G. Knepley Level: developer 4595412e9a14SMatthew G. Knepley 4596a1cb98faSBarry Smith Note: 4597a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4598a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4599a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4600412e9a14SMatthew G. Knepley 4601a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4602a1cb98faSBarry Smith 46031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4604412e9a14SMatthew G. Knepley @*/ 4605d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4606d71ae5a4SJacob Faibussowitsch { 4607412e9a14SMatthew G. Knepley DM_Plex *mesh; 4608412e9a14SMatthew G. Knepley DMLabel ctLabel; 4609412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4610412e9a14SMatthew G. Knepley 4611412e9a14SMatthew G. Knepley PetscFunctionBegin; 4612412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4613412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 46149566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 46159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 46169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 461721027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 461821027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4619412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4620327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4621412e9a14SMatthew G. Knepley PetscInt pdepth; 4622412e9a14SMatthew G. Knepley 46239566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 46249566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4625476787b7SMatthew G. Knepley PetscCheck(ct != DM_POLYTOPE_UNKNOWN && ct != DM_POLYTOPE_UNKNOWN_CELL && ct != DM_POLYTOPE_UNKNOWN_FACE, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 46269566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 462721027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = ct; 4628412e9a14SMatthew G. Knepley } 46299566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 46309566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 46313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4632ba2698f1SMatthew G. Knepley } 4633ba2698f1SMatthew G. Knepley 4634552f7358SJed Brown /*@C 4635552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4636552f7358SJed Brown 4637552f7358SJed Brown Not Collective 4638552f7358SJed Brown 4639552f7358SJed Brown Input Parameters: 4640a1cb98faSBarry Smith + dm - The `DMPLEX` object 4641552f7358SJed Brown . numPoints - The number of input points for the join 4642552f7358SJed Brown - points - The input points 4643552f7358SJed Brown 4644552f7358SJed Brown Output Parameters: 4645552f7358SJed Brown + numCoveredPoints - The number of points in the join 4646552f7358SJed Brown - coveredPoints - The points in the join 4647552f7358SJed Brown 4648552f7358SJed Brown Level: intermediate 4649552f7358SJed Brown 4650a1cb98faSBarry Smith Note: 4651a1cb98faSBarry Smith Currently, this is restricted to a single level join 4652552f7358SJed Brown 465360225df5SJacob Faibussowitsch Fortran Notes: 465420f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 46553813dfbdSMatthew G Knepley 46561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4657552f7358SJed Brown @*/ 4658d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4659d71ae5a4SJacob Faibussowitsch { 4660552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4661552f7358SJed Brown PetscInt *join[2]; 4662552f7358SJed Brown PetscInt joinSize, i = 0; 4663552f7358SJed Brown PetscInt dof, off, p, c, m; 46646302a7fbSVaclav Hapla PetscInt maxSupportSize; 4665552f7358SJed Brown 4666552f7358SJed Brown PetscFunctionBegin; 4667552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46684f572ea9SToby Isaac PetscAssertPointer(points, 3); 46694f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 46704f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46716302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 46726302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 46736302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4674552f7358SJed Brown /* Copy in support of first point */ 46759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 46769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4677ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4678552f7358SJed Brown /* Check each successive support */ 4679552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4680552f7358SJed Brown PetscInt newJoinSize = 0; 4681552f7358SJed Brown 46829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 46839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4684552f7358SJed Brown for (c = 0; c < dof; ++c) { 4685552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4686552f7358SJed Brown 4687552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4688552f7358SJed Brown if (point == join[i][m]) { 4689552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4690552f7358SJed Brown break; 4691552f7358SJed Brown } 4692552f7358SJed Brown } 4693552f7358SJed Brown } 4694552f7358SJed Brown joinSize = newJoinSize; 4695552f7358SJed Brown i = 1 - i; 4696552f7358SJed Brown } 4697552f7358SJed Brown *numCoveredPoints = joinSize; 4698552f7358SJed Brown *coveredPoints = join[i]; 46996302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 47003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4701552f7358SJed Brown } 4702552f7358SJed Brown 4703552f7358SJed Brown /*@C 4704552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4705552f7358SJed Brown 4706552f7358SJed Brown Not Collective 4707552f7358SJed Brown 4708552f7358SJed Brown Input Parameters: 4709a1cb98faSBarry Smith + dm - The `DMPLEX` object 4710552f7358SJed Brown . numPoints - The number of input points for the join 4711552f7358SJed Brown - points - The input points 4712552f7358SJed Brown 4713552f7358SJed Brown Output Parameters: 4714552f7358SJed Brown + numCoveredPoints - The number of points in the join 4715552f7358SJed Brown - coveredPoints - The points in the join 4716552f7358SJed Brown 4717552f7358SJed Brown Level: intermediate 4718552f7358SJed Brown 471960225df5SJacob Faibussowitsch Fortran Notes: 472020f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4721a1cb98faSBarry Smith 47221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4723552f7358SJed Brown @*/ 4724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4725d71ae5a4SJacob Faibussowitsch { 4726552f7358SJed Brown PetscFunctionBegin; 4727552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47284f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 47294f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 47304f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 47319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4732d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 47333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4734552f7358SJed Brown } 4735552f7358SJed Brown 4736552f7358SJed Brown /*@C 4737552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4738552f7358SJed Brown 4739552f7358SJed Brown Not Collective 4740552f7358SJed Brown 4741552f7358SJed Brown Input Parameters: 4742a1cb98faSBarry Smith + dm - The `DMPLEX` object 4743552f7358SJed Brown . numPoints - The number of input points for the join 4744552f7358SJed Brown - points - The input points 4745552f7358SJed Brown 4746552f7358SJed Brown Output Parameters: 4747552f7358SJed Brown + numCoveredPoints - The number of points in the join 4748552f7358SJed Brown - coveredPoints - The points in the join 4749552f7358SJed Brown 4750552f7358SJed Brown Level: intermediate 4751552f7358SJed Brown 475260225df5SJacob Faibussowitsch Fortran Notes: 475320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4754a1cb98faSBarry Smith 47551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4756552f7358SJed Brown @*/ 4757d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4758d71ae5a4SJacob Faibussowitsch { 4759552f7358SJed Brown PetscInt *offsets, **closures; 4760552f7358SJed Brown PetscInt *join[2]; 4761552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 476224c766afSToby Isaac PetscInt p, d, c, m, ms; 4763552f7358SJed Brown 4764552f7358SJed Brown PetscFunctionBegin; 4765552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47664f572ea9SToby Isaac PetscAssertPointer(points, 3); 47674f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 47684f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4769552f7358SJed Brown 47709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 47719566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 47729566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 47736302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 477424c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 47759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 47769566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4777552f7358SJed Brown 4778552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4779552f7358SJed Brown PetscInt closureSize; 4780552f7358SJed Brown 47819566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 47820d644c17SKarl Rupp 4783552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4784552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4785552f7358SJed Brown PetscInt pStart, pEnd, i; 4786552f7358SJed Brown 47879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4788552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4789552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4790552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4791552f7358SJed Brown break; 4792552f7358SJed Brown } 4793552f7358SJed Brown } 4794552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4795552f7358SJed Brown } 479663a3b9bcSJacob Faibussowitsch PetscCheck(offsets[p * (depth + 2) + depth + 1] == closureSize, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[p * (depth + 2) + depth + 1], closureSize); 4797552f7358SJed Brown } 4798552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4799552f7358SJed Brown PetscInt dof; 4800552f7358SJed Brown 4801552f7358SJed Brown /* Copy in support of first point */ 4802552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4803ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4804552f7358SJed Brown /* Check each successive cone */ 4805552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4806552f7358SJed Brown PetscInt newJoinSize = 0; 4807552f7358SJed Brown 4808552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4809552f7358SJed Brown for (c = 0; c < dof; ++c) { 4810552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4811552f7358SJed Brown 4812552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4813552f7358SJed Brown if (point == join[i][m]) { 4814552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4815552f7358SJed Brown break; 4816552f7358SJed Brown } 4817552f7358SJed Brown } 4818552f7358SJed Brown } 4819552f7358SJed Brown joinSize = newJoinSize; 4820552f7358SJed Brown i = 1 - i; 4821552f7358SJed Brown } 4822552f7358SJed Brown if (joinSize) break; 4823552f7358SJed Brown } 4824552f7358SJed Brown *numCoveredPoints = joinSize; 4825552f7358SJed Brown *coveredPoints = join[i]; 482648a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 48279566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 48289566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 48296302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 48303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4831552f7358SJed Brown } 4832552f7358SJed Brown 4833552f7358SJed Brown /*@C 4834552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4835552f7358SJed Brown 4836552f7358SJed Brown Not Collective 4837552f7358SJed Brown 4838552f7358SJed Brown Input Parameters: 4839a1cb98faSBarry Smith + dm - The `DMPLEX` object 4840552f7358SJed Brown . numPoints - The number of input points for the meet 4841552f7358SJed Brown - points - The input points 4842552f7358SJed Brown 4843552f7358SJed Brown Output Parameters: 484460225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 484560225df5SJacob Faibussowitsch - coveringPoints - The points in the meet 4846552f7358SJed Brown 4847552f7358SJed Brown Level: intermediate 4848552f7358SJed Brown 4849a1cb98faSBarry Smith Note: 4850a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4851552f7358SJed Brown 48523813dfbdSMatthew G Knepley Fortran Notes: 485320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48543813dfbdSMatthew G Knepley 48551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4856552f7358SJed Brown @*/ 4857d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4858d71ae5a4SJacob Faibussowitsch { 4859552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4860552f7358SJed Brown PetscInt *meet[2]; 4861552f7358SJed Brown PetscInt meetSize, i = 0; 4862552f7358SJed Brown PetscInt dof, off, p, c, m; 48636302a7fbSVaclav Hapla PetscInt maxConeSize; 4864552f7358SJed Brown 4865552f7358SJed Brown PetscFunctionBegin; 4866552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48674f572ea9SToby Isaac PetscAssertPointer(points, 3); 48684f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 48694f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 48706302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 48716302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 48726302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4873552f7358SJed Brown /* Copy in cone of first point */ 48749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 48759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4876ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4877552f7358SJed Brown /* Check each successive cone */ 4878552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4879552f7358SJed Brown PetscInt newMeetSize = 0; 4880552f7358SJed Brown 48819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 48829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4883552f7358SJed Brown for (c = 0; c < dof; ++c) { 4884552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4885552f7358SJed Brown 4886552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4887552f7358SJed Brown if (point == meet[i][m]) { 4888552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4889552f7358SJed Brown break; 4890552f7358SJed Brown } 4891552f7358SJed Brown } 4892552f7358SJed Brown } 4893552f7358SJed Brown meetSize = newMeetSize; 4894552f7358SJed Brown i = 1 - i; 4895552f7358SJed Brown } 4896552f7358SJed Brown *numCoveringPoints = meetSize; 4897552f7358SJed Brown *coveringPoints = meet[i]; 48986302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 48993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4900552f7358SJed Brown } 4901552f7358SJed Brown 4902552f7358SJed Brown /*@C 4903552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4904552f7358SJed Brown 4905552f7358SJed Brown Not Collective 4906552f7358SJed Brown 4907552f7358SJed Brown Input Parameters: 4908a1cb98faSBarry Smith + dm - The `DMPLEX` object 4909552f7358SJed Brown . numPoints - The number of input points for the meet 4910552f7358SJed Brown - points - The input points 4911552f7358SJed Brown 4912552f7358SJed Brown Output Parameters: 4913552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4914552f7358SJed Brown - coveredPoints - The points in the meet 4915552f7358SJed Brown 4916552f7358SJed Brown Level: intermediate 4917552f7358SJed Brown 491860225df5SJacob Faibussowitsch Fortran Notes: 491920f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49203813dfbdSMatthew G Knepley 49211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4922552f7358SJed Brown @*/ 4923d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4924d71ae5a4SJacob Faibussowitsch { 4925552f7358SJed Brown PetscFunctionBegin; 4926552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49274f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 49284f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 49294f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 49309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4931d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 49323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4933552f7358SJed Brown } 4934552f7358SJed Brown 4935552f7358SJed Brown /*@C 4936552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4937552f7358SJed Brown 4938552f7358SJed Brown Not Collective 4939552f7358SJed Brown 4940552f7358SJed Brown Input Parameters: 4941a1cb98faSBarry Smith + dm - The `DMPLEX` object 4942552f7358SJed Brown . numPoints - The number of input points for the meet 4943552f7358SJed Brown - points - The input points 4944552f7358SJed Brown 4945552f7358SJed Brown Output Parameters: 4946552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4947552f7358SJed Brown - coveredPoints - The points in the meet 4948552f7358SJed Brown 4949552f7358SJed Brown Level: intermediate 4950552f7358SJed Brown 495160225df5SJacob Faibussowitsch Fortran Notes: 495220f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49533813dfbdSMatthew G Knepley 49541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4955552f7358SJed Brown @*/ 4956d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4957d71ae5a4SJacob Faibussowitsch { 4958552f7358SJed Brown PetscInt *offsets, **closures; 4959552f7358SJed Brown PetscInt *meet[2]; 4960552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 496124c766afSToby Isaac PetscInt p, h, c, m, mc; 4962552f7358SJed Brown 4963552f7358SJed Brown PetscFunctionBegin; 4964552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49654f572ea9SToby Isaac PetscAssertPointer(points, 3); 49664f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 49674f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4968552f7358SJed Brown 49699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 49709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 49719566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 49726302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 497324c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 49749566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 49759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4976552f7358SJed Brown 4977552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4978552f7358SJed Brown PetscInt closureSize; 4979552f7358SJed Brown 49809566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 49810d644c17SKarl Rupp 4982552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4983552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4984552f7358SJed Brown PetscInt pStart, pEnd, i; 4985552f7358SJed Brown 49869566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4987552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4988552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4989552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4990552f7358SJed Brown break; 4991552f7358SJed Brown } 4992552f7358SJed Brown } 4993552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4994552f7358SJed Brown } 499563a3b9bcSJacob Faibussowitsch PetscCheck(offsets[p * (height + 2) + height + 1] == closureSize, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[p * (height + 2) + height + 1], closureSize); 4996552f7358SJed Brown } 4997552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4998552f7358SJed Brown PetscInt dof; 4999552f7358SJed Brown 5000552f7358SJed Brown /* Copy in cone of first point */ 5001552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 5002ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 5003552f7358SJed Brown /* Check each successive cone */ 5004552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 5005552f7358SJed Brown PetscInt newMeetSize = 0; 5006552f7358SJed Brown 5007552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 5008552f7358SJed Brown for (c = 0; c < dof; ++c) { 5009552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 5010552f7358SJed Brown 5011552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5012552f7358SJed Brown if (point == meet[i][m]) { 5013552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5014552f7358SJed Brown break; 5015552f7358SJed Brown } 5016552f7358SJed Brown } 5017552f7358SJed Brown } 5018552f7358SJed Brown meetSize = newMeetSize; 5019552f7358SJed Brown i = 1 - i; 5020552f7358SJed Brown } 5021552f7358SJed Brown if (meetSize) break; 5022552f7358SJed Brown } 5023552f7358SJed Brown *numCoveredPoints = meetSize; 5024552f7358SJed Brown *coveredPoints = meet[i]; 502548a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 50269566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 50279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 50286302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 50293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5030552f7358SJed Brown } 5031552f7358SJed Brown 50324e3744c5SMatthew G. Knepley /*@C 5033a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 50344e3744c5SMatthew G. Knepley 50354e3744c5SMatthew G. Knepley Not Collective 50364e3744c5SMatthew G. Knepley 50374e3744c5SMatthew G. Knepley Input Parameters: 5038a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5039a1cb98faSBarry Smith - dmB - A `DMPLEX` object 50404e3744c5SMatthew G. Knepley 50412fe279fdSBarry Smith Output Parameter: 5042a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 50434e3744c5SMatthew G. Knepley 50444e3744c5SMatthew G. Knepley Level: intermediate 50454e3744c5SMatthew G. Knepley 5046a1cb98faSBarry Smith Note: 50473c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 50484e3744c5SMatthew G. Knepley 50491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 50504e3744c5SMatthew G. Knepley @*/ 5051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5052d71ae5a4SJacob Faibussowitsch { 50534e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 50544e3744c5SMatthew G. Knepley 50554e3744c5SMatthew G. Knepley PetscFunctionBegin; 50564e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 50574e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 50584f572ea9SToby Isaac PetscAssertPointer(equal, 3); 50594e3744c5SMatthew G. Knepley 50604e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 50619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 50629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 50633ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 50649566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 50659566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 50663ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 50674e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 50684e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 50694e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 50704e3744c5SMatthew G. Knepley 50719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 50729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 50739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 50749566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 50759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 50769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 50773ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50784e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 50793ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50803ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50814e3744c5SMatthew G. Knepley } 50829566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 50839566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 50849566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 50859566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 50863ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50874e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 50883ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 50894e3744c5SMatthew G. Knepley } 50904e3744c5SMatthew G. Knepley } 50914e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 50923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50934e3744c5SMatthew G. Knepley } 50944e3744c5SMatthew G. Knepley 50957cd05799SMatthew G. Knepley /*@C 50967cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 50977cd05799SMatthew G. Knepley 50987cd05799SMatthew G. Knepley Not Collective 50997cd05799SMatthew G. Knepley 51007cd05799SMatthew G. Knepley Input Parameters: 5101a1cb98faSBarry Smith + dm - The `DMPLEX` 51027cd05799SMatthew G. Knepley . cellDim - The cell dimension 51037cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 51047cd05799SMatthew G. Knepley 51052fe279fdSBarry Smith Output Parameter: 51067cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 51077cd05799SMatthew G. Knepley 51087cd05799SMatthew G. Knepley Level: developer 51097cd05799SMatthew G. Knepley 5110a1cb98faSBarry Smith Note: 51117cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 51127cd05799SMatthew G. Knepley 51131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 51147cd05799SMatthew G. Knepley @*/ 5115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5116d71ae5a4SJacob Faibussowitsch { 511782f516ccSBarry Smith MPI_Comm comm; 5118552f7358SJed Brown 5119552f7358SJed Brown PetscFunctionBegin; 51209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 51214f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5122552f7358SJed Brown switch (cellDim) { 5123d71ae5a4SJacob Faibussowitsch case 0: 5124d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5125d71ae5a4SJacob Faibussowitsch break; 5126d71ae5a4SJacob Faibussowitsch case 1: 5127d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5128d71ae5a4SJacob Faibussowitsch break; 5129552f7358SJed Brown case 2: 5130552f7358SJed Brown switch (numCorners) { 513119436ca2SJed Brown case 3: /* triangle */ 513219436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5133552f7358SJed Brown break; 513419436ca2SJed Brown case 4: /* quadrilateral */ 513519436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5136552f7358SJed Brown break; 513719436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 513819436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5139552f7358SJed Brown break; 514019436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 514119436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5142552f7358SJed Brown break; 5143d71ae5a4SJacob Faibussowitsch default: 5144d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5145552f7358SJed Brown } 5146552f7358SJed Brown break; 5147552f7358SJed Brown case 3: 5148552f7358SJed Brown switch (numCorners) { 514919436ca2SJed Brown case 4: /* tetradehdron */ 515019436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5151552f7358SJed Brown break; 515219436ca2SJed Brown case 6: /* tet cohesive cells */ 515319436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5154552f7358SJed Brown break; 515519436ca2SJed Brown case 8: /* hexahedron */ 515619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5157552f7358SJed Brown break; 515819436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 515919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5160552f7358SJed Brown break; 516119436ca2SJed Brown case 10: /* quadratic tetrahedron */ 516219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5163552f7358SJed Brown break; 516419436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 516519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5166552f7358SJed Brown break; 516719436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 516819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5169552f7358SJed Brown break; 517019436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 517119436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5172552f7358SJed Brown break; 5173d71ae5a4SJacob Faibussowitsch default: 5174d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5175552f7358SJed Brown } 5176552f7358SJed Brown break; 5177d71ae5a4SJacob Faibussowitsch default: 5178d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5179552f7358SJed Brown } 51803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5181552f7358SJed Brown } 5182552f7358SJed Brown 5183552f7358SJed Brown /*@ 5184a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5185552f7358SJed Brown 5186552f7358SJed Brown Not Collective 5187552f7358SJed Brown 5188aa50250dSMatthew G. Knepley Input Parameter: 5189a1cb98faSBarry Smith . dm - The `DMPLEX` object 5190552f7358SJed Brown 5191aa50250dSMatthew G. Knepley Output Parameter: 5192a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5193552f7358SJed Brown 5194552f7358SJed Brown Level: developer 5195552f7358SJed Brown 51961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5197aa50250dSMatthew G. Knepley @*/ 5198d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5199d71ae5a4SJacob Faibussowitsch { 5200aa50250dSMatthew G. Knepley PetscFunctionBegin; 5201aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52024f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5203c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 52043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5205aa50250dSMatthew G. Knepley } 5206aa50250dSMatthew G. Knepley 5207aa50250dSMatthew G. Knepley /*@ 5208aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5209aa50250dSMatthew G. Knepley 5210aa50250dSMatthew G. Knepley Not Collective 5211aa50250dSMatthew G. Knepley 5212aa50250dSMatthew G. Knepley Input Parameter: 5213a1cb98faSBarry Smith . dm - The `DMPLEX` object 5214aa50250dSMatthew G. Knepley 5215aa50250dSMatthew G. Knepley Output Parameter: 5216aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5217aa50250dSMatthew G. Knepley 5218aa50250dSMatthew G. Knepley Level: developer 5219552f7358SJed Brown 5220b1bb481bSMatthew Knepley Notes: 5221a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5222a1cb98faSBarry Smith 5223a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5224a1cb98faSBarry Smith 5225dc287ab2SVaclav Hapla An empty mesh gives -1. 5226b1bb481bSMatthew Knepley 52271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5228552f7358SJed Brown @*/ 5229d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5230d71ae5a4SJacob Faibussowitsch { 52319f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5232aa50250dSMatthew G. Knepley DMLabel label; 5233aa50250dSMatthew G. Knepley PetscInt d = 0; 5234552f7358SJed Brown 5235552f7358SJed Brown PetscFunctionBegin; 5236552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52374f572ea9SToby Isaac PetscAssertPointer(depth, 2); 52389f4ada15SMatthew G. Knepley if (mesh->tr) { 52399f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 52409f4ada15SMatthew G. Knepley } else { 52419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52429566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 5243552f7358SJed Brown *depth = d - 1; 52449f4ada15SMatthew G. Knepley } 52453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5246552f7358SJed Brown } 5247552f7358SJed Brown 5248552f7358SJed Brown /*@ 524920f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5250552f7358SJed Brown 5251552f7358SJed Brown Not Collective 5252552f7358SJed Brown 5253552f7358SJed Brown Input Parameters: 5254a1cb98faSBarry Smith + dm - The `DMPLEX` object 5255570fa34dSVaclav Hapla - depth - The requested depth 5256552f7358SJed Brown 5257552f7358SJed Brown Output Parameters: 525820f4b53cSBarry Smith + start - The first point at this `depth` 525920f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5260552f7358SJed Brown 5261552f7358SJed Brown Level: developer 5262552f7358SJed Brown 5263a1cb98faSBarry Smith Notes: 5264a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5265a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5266a1cb98faSBarry Smith higher dimension, e.g., "edges". 5267a1cb98faSBarry Smith 52682827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5269552f7358SJed Brown @*/ 5270d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5271d71ae5a4SJacob Faibussowitsch { 52729f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5273aa50250dSMatthew G. Knepley DMLabel label; 527463d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5275552f7358SJed Brown 5276552f7358SJed Brown PetscFunctionBegin; 5277552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52789371c9d4SSatish Balay if (start) { 52794f572ea9SToby Isaac PetscAssertPointer(start, 3); 52809371c9d4SSatish Balay *start = 0; 52819371c9d4SSatish Balay } 52829371c9d4SSatish Balay if (end) { 52834f572ea9SToby Isaac PetscAssertPointer(end, 4); 52849371c9d4SSatish Balay *end = 0; 52859371c9d4SSatish Balay } 52869566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 52873ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5288570fa34dSVaclav Hapla if (depth < 0) { 528963d1a920SMatthew G. Knepley if (start) *start = pStart; 529063d1a920SMatthew G. Knepley if (end) *end = pEnd; 52913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5292552f7358SJed Brown } 52939f4ada15SMatthew G. Knepley if (mesh->tr) { 52949f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 52959f4ada15SMatthew G. Knepley } else { 52969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 529728b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5298570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 52999f4ada15SMatthew G. Knepley } 53003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5301552f7358SJed Brown } 5302552f7358SJed Brown 5303552f7358SJed Brown /*@ 530420f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5305552f7358SJed Brown 5306552f7358SJed Brown Not Collective 5307552f7358SJed Brown 5308552f7358SJed Brown Input Parameters: 5309a1cb98faSBarry Smith + dm - The `DMPLEX` object 5310570fa34dSVaclav Hapla - height - The requested height 5311552f7358SJed Brown 5312552f7358SJed Brown Output Parameters: 531320f4b53cSBarry Smith + start - The first point at this `height` 531420f4b53cSBarry Smith - end - One beyond the last point at this `height` 5315552f7358SJed Brown 5316552f7358SJed Brown Level: developer 5317552f7358SJed Brown 5318a1cb98faSBarry Smith Notes: 5319a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5320a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5321a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5322a1cb98faSBarry Smith 53232827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5324552f7358SJed Brown @*/ 5325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5326d71ae5a4SJacob Faibussowitsch { 5327aa50250dSMatthew G. Knepley DMLabel label; 532863d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5329552f7358SJed Brown 5330552f7358SJed Brown PetscFunctionBegin; 5331552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53329371c9d4SSatish Balay if (start) { 53334f572ea9SToby Isaac PetscAssertPointer(start, 3); 53349371c9d4SSatish Balay *start = 0; 53359371c9d4SSatish Balay } 53369371c9d4SSatish Balay if (end) { 53374f572ea9SToby Isaac PetscAssertPointer(end, 4); 53389371c9d4SSatish Balay *end = 0; 53399371c9d4SSatish Balay } 53409566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 53413ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5342570fa34dSVaclav Hapla if (height < 0) { 534363d1a920SMatthew G. Knepley if (start) *start = pStart; 534463d1a920SMatthew G. Knepley if (end) *end = pEnd; 53453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5346552f7358SJed Brown } 53479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 534859e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 534959e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 535059e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 535159e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 53523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5353552f7358SJed Brown } 5354552f7358SJed Brown 5355ba2698f1SMatthew G. Knepley /*@ 535620f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5357ba2698f1SMatthew G. Knepley 5358ba2698f1SMatthew G. Knepley Not Collective 5359ba2698f1SMatthew G. Knepley 5360d8d19677SJose E. Roman Input Parameters: 5361a1cb98faSBarry Smith + dm - The `DMPLEX` object 5362ba2698f1SMatthew G. Knepley - point - The point 5363ba2698f1SMatthew G. Knepley 5364ba2698f1SMatthew G. Knepley Output Parameter: 536520f4b53cSBarry Smith . depth - The depth of the `point` 5366ba2698f1SMatthew G. Knepley 5367ba2698f1SMatthew G. Knepley Level: intermediate 5368ba2698f1SMatthew G. Knepley 53691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5370ba2698f1SMatthew G. Knepley @*/ 5371d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5372d71ae5a4SJacob Faibussowitsch { 5373ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5374ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53754f572ea9SToby Isaac PetscAssertPointer(depth, 3); 53769566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 53773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5378ba2698f1SMatthew G. Knepley } 5379ba2698f1SMatthew G. Knepley 5380ba2698f1SMatthew G. Knepley /*@ 538120f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 53820c0a32dcSVaclav Hapla 53830c0a32dcSVaclav Hapla Not Collective 53840c0a32dcSVaclav Hapla 5385d8d19677SJose E. Roman Input Parameters: 5386a1cb98faSBarry Smith + dm - The `DMPLEX` object 53870c0a32dcSVaclav Hapla - point - The point 53880c0a32dcSVaclav Hapla 53890c0a32dcSVaclav Hapla Output Parameter: 539020f4b53cSBarry Smith . height - The height of the `point` 53910c0a32dcSVaclav Hapla 53920c0a32dcSVaclav Hapla Level: intermediate 53930c0a32dcSVaclav Hapla 53941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 53950c0a32dcSVaclav Hapla @*/ 5396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5397d71ae5a4SJacob Faibussowitsch { 53980c0a32dcSVaclav Hapla PetscInt n, pDepth; 53990c0a32dcSVaclav Hapla 54000c0a32dcSVaclav Hapla PetscFunctionBegin; 54010c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54024f572ea9SToby Isaac PetscAssertPointer(height, 3); 54039566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 54049566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 54050c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 54063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54070c0a32dcSVaclav Hapla } 54080c0a32dcSVaclav Hapla 54090c0a32dcSVaclav Hapla /*@ 5410a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5411ba2698f1SMatthew G. Knepley 5412ba2698f1SMatthew G. Knepley Not Collective 5413ba2698f1SMatthew G. Knepley 5414ba2698f1SMatthew G. Knepley Input Parameter: 5415a1cb98faSBarry Smith . dm - The `DMPLEX` object 5416ba2698f1SMatthew G. Knepley 5417ba2698f1SMatthew G. Knepley Output Parameter: 5418a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5419412e9a14SMatthew G. Knepley 5420ba2698f1SMatthew G. Knepley Level: developer 5421ba2698f1SMatthew G. Knepley 5422a1cb98faSBarry Smith Note: 5423a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5424a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5425a1cb98faSBarry Smith 54261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5427ba2698f1SMatthew G. Knepley @*/ 5428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5429d71ae5a4SJacob Faibussowitsch { 5430ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5431ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54324f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 54339566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5434ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 54353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5436ba2698f1SMatthew G. Knepley } 5437ba2698f1SMatthew G. Knepley 5438ba2698f1SMatthew G. Knepley /*@ 5439ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5440ba2698f1SMatthew G. Knepley 5441ba2698f1SMatthew G. Knepley Not Collective 5442ba2698f1SMatthew G. Knepley 5443d8d19677SJose E. Roman Input Parameters: 5444a1cb98faSBarry Smith + dm - The `DMPLEX` object 5445ba2698f1SMatthew G. Knepley - cell - The cell 5446ba2698f1SMatthew G. Knepley 5447ba2698f1SMatthew G. Knepley Output Parameter: 5448ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5449ba2698f1SMatthew G. Knepley 5450ba2698f1SMatthew G. Knepley Level: intermediate 5451ba2698f1SMatthew G. Knepley 54521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5453ba2698f1SMatthew G. Knepley @*/ 5454d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5455d71ae5a4SJacob Faibussowitsch { 54569f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5457ba2698f1SMatthew G. Knepley DMLabel label; 5458ba2698f1SMatthew G. Knepley PetscInt ct; 5459ba2698f1SMatthew G. Knepley 5460ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5461ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54624f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 54639f4ada15SMatthew G. Knepley if (mesh->tr) { 54649f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 54659f4ada15SMatthew G. Knepley } else { 546621027e53SStefano Zampini PetscInt pStart, pEnd; 546721027e53SStefano Zampini 546821027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 546921027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 547021027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 547121027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 547221027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 547321027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 547421027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 547521027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct; 547621027e53SStefano Zampini } 547721027e53SStefano Zampini } 547821027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 547921027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 54809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 54819566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 548263a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5483936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 548421027e53SStefano Zampini } 54859f4ada15SMatthew G. Knepley } 54863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5487ba2698f1SMatthew G. Knepley } 5488ba2698f1SMatthew G. Knepley 5489412e9a14SMatthew G. Knepley /*@ 5490412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5491412e9a14SMatthew G. Knepley 5492412e9a14SMatthew G. Knepley Not Collective 5493412e9a14SMatthew G. Knepley 5494412e9a14SMatthew G. Knepley Input Parameters: 5495a1cb98faSBarry Smith + dm - The `DMPLEX` object 5496412e9a14SMatthew G. Knepley . cell - The cell 5497412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5498412e9a14SMatthew G. Knepley 5499a1cb98faSBarry Smith Level: advanced 5500a1cb98faSBarry Smith 5501a1cb98faSBarry Smith Note: 5502a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5503412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5504412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5505db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5506412e9a14SMatthew G. Knepley 55071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5508412e9a14SMatthew G. Knepley @*/ 5509d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5510d71ae5a4SJacob Faibussowitsch { 551121027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5512412e9a14SMatthew G. Knepley DMLabel label; 551321027e53SStefano Zampini PetscInt pStart, pEnd; 5514412e9a14SMatthew G. Knepley 5515412e9a14SMatthew G. Knepley PetscFunctionBegin; 5516412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 551721027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 55189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 55199566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 552021027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 552121027e53SStefano Zampini mesh->cellTypes[cell - pStart].value_as_uint8 = celltype; 55223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5523412e9a14SMatthew G. Knepley } 5524412e9a14SMatthew G. Knepley 5525d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5526d71ae5a4SJacob Faibussowitsch { 5527*c789d87fSToby Isaac PetscSection section; 55283e922f36SToby Isaac PetscInt maxHeight; 5529dd4c3f67SMatthew G. Knepley const char *prefix; 5530552f7358SJed Brown 5531552f7358SJed Brown PetscFunctionBegin; 55329566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5533dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5534dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5535dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 55369566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 55379566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 55389566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 55399566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 55409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 55418f4c458bSMatthew G. Knepley 55429566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 55439566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5544dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5545dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 55463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5547552f7358SJed Brown } 5548552f7358SJed Brown 5549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5550d71ae5a4SJacob Faibussowitsch { 55516858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 55526858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5553f19dbd58SToby Isaac 5554f19dbd58SToby Isaac PetscFunctionBegin; 5555f19dbd58SToby Isaac *field = NULL; 55569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 55579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 55586858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 55596858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5560f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 55616858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 55626858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5563f19dbd58SToby Isaac } 55643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5565f19dbd58SToby Isaac } 5566f19dbd58SToby Isaac 55677cd05799SMatthew G. Knepley /*@C 55687cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 55697cd05799SMatthew G. Knepley 55707cd05799SMatthew G. Knepley Not Collective 55717cd05799SMatthew G. Knepley 55722fe279fdSBarry Smith Input Parameter: 5573a1cb98faSBarry Smith . dm - The `DMPLEX` object 55747cd05799SMatthew G. Knepley 55757cd05799SMatthew G. Knepley Output Parameter: 5576a1cb98faSBarry Smith . section - The `PetscSection` object 55777cd05799SMatthew G. Knepley 55787cd05799SMatthew G. Knepley Level: developer 55797cd05799SMatthew G. Knepley 55801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 55817cd05799SMatthew G. Knepley @*/ 5582d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5583d71ae5a4SJacob Faibussowitsch { 5584552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5585552f7358SJed Brown 5586552f7358SJed Brown PetscFunctionBegin; 5587552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5588552f7358SJed Brown if (section) *section = mesh->coneSection; 55893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5590552f7358SJed Brown } 5591552f7358SJed Brown 55927cd05799SMatthew G. Knepley /*@C 55937cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 55947cd05799SMatthew G. Knepley 55957cd05799SMatthew G. Knepley Not Collective 55967cd05799SMatthew G. Knepley 55972fe279fdSBarry Smith Input Parameter: 5598a1cb98faSBarry Smith . dm - The `DMPLEX` object 55997cd05799SMatthew G. Knepley 56007cd05799SMatthew G. Knepley Output Parameter: 5601a1cb98faSBarry Smith . section - The `PetscSection` object 56027cd05799SMatthew G. Knepley 56037cd05799SMatthew G. Knepley Level: developer 56047cd05799SMatthew G. Knepley 56051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 56067cd05799SMatthew G. Knepley @*/ 5607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5608d71ae5a4SJacob Faibussowitsch { 56098cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 56108cb4d582SMatthew G. Knepley 56118cb4d582SMatthew G. Knepley PetscFunctionBegin; 56128cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56138cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 56143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56158cb4d582SMatthew G. Knepley } 56168cb4d582SMatthew G. Knepley 56177cd05799SMatthew G. Knepley /*@C 56187cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 56197cd05799SMatthew G. Knepley 56207cd05799SMatthew G. Knepley Not Collective 56217cd05799SMatthew G. Knepley 56222fe279fdSBarry Smith Input Parameter: 5623a1cb98faSBarry Smith . dm - The `DMPLEX` object 56247cd05799SMatthew G. Knepley 56257cd05799SMatthew G. Knepley Output Parameter: 56267cd05799SMatthew G. Knepley . cones - The cone for each point 56277cd05799SMatthew G. Knepley 56287cd05799SMatthew G. Knepley Level: developer 56297cd05799SMatthew G. Knepley 56301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 56317cd05799SMatthew G. Knepley @*/ 5632d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5633d71ae5a4SJacob Faibussowitsch { 5634552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5635552f7358SJed Brown 5636552f7358SJed Brown PetscFunctionBegin; 5637552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5638552f7358SJed Brown if (cones) *cones = mesh->cones; 56393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5640552f7358SJed Brown } 5641552f7358SJed Brown 56427cd05799SMatthew G. Knepley /*@C 56437cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 56447cd05799SMatthew G. Knepley 56457cd05799SMatthew G. Knepley Not Collective 56467cd05799SMatthew G. Knepley 56472fe279fdSBarry Smith Input Parameter: 5648a1cb98faSBarry Smith . dm - The `DMPLEX` object 56497cd05799SMatthew G. Knepley 56507cd05799SMatthew G. Knepley Output Parameter: 5651b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 56527cd05799SMatthew G. Knepley 56537cd05799SMatthew G. Knepley Level: developer 56547cd05799SMatthew G. Knepley 5655b5a892a1SMatthew G. Knepley Notes: 5656a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5657b5a892a1SMatthew G. Knepley 5658a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5659b5a892a1SMatthew G. Knepley 56601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 56617cd05799SMatthew G. Knepley @*/ 5662d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5663d71ae5a4SJacob Faibussowitsch { 5664552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5665552f7358SJed Brown 5666552f7358SJed Brown PetscFunctionBegin; 5667552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5668552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 56693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5670552f7358SJed Brown } 5671552f7358SJed Brown 5672552f7358SJed Brown /******************************** FEM Support **********************************/ 5673552f7358SJed Brown 5674d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5675d2b2dc1eSMatthew G. Knepley { 5676d2b2dc1eSMatthew G. Knepley PetscInt depth; 5677d2b2dc1eSMatthew G. Knepley 5678d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5679d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5680d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5681d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5682d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5683d2b2dc1eSMatthew G. Knepley } 5684d2b2dc1eSMatthew G. Knepley 56855962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 56865962854dSMatthew G. Knepley { 56875962854dSMatthew G. Knepley PetscInt depth; 56885962854dSMatthew G. Knepley 56895962854dSMatthew G. Knepley PetscFunctionBegin; 56905962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 56915962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 56925962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 56935962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 56945962854dSMatthew G. Knepley } 56955962854dSMatthew G. Knepley 56969e8305c2SJed Brown /* 56979e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 56989e8305c2SJed Brown representing a line in the section. 56999e8305c2SJed Brown */ 57005f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor) 5701d71ae5a4SJacob Faibussowitsch { 5702e327e467SRezgar Shakeri PetscObject obj; 5703e327e467SRezgar Shakeri PetscClassId id; 5704e327e467SRezgar Shakeri PetscFE fe = NULL; 5705e327e467SRezgar Shakeri 57069e8305c2SJed Brown PetscFunctionBeginHot; 57079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5708e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5709e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5710e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5711e327e467SRezgar Shakeri 5712e327e467SRezgar Shakeri if (!fe) { 5713e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 57149e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 57159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 57169e8305c2SJed Brown *k = *k / *Nc + 1; 5717e327e467SRezgar Shakeri } else { 5718e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 57195f82726aSMatthew G. Knepley PetscDualSpace dsp; 57205f82726aSMatthew G. Knepley 5721e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 57225f82726aSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &dsp)); 57235f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size)); 5724e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 57255f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous)); 57265f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor)); 57275f82726aSMatthew G. Knepley } 57285f82726aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 57295f82726aSMatthew G. Knepley } 57305f82726aSMatthew G. Knepley 57315f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof) 57325f82726aSMatthew G. Knepley { 57335f82726aSMatthew G. Knepley PetscFunctionBeginHot; 57345f82726aSMatthew G. Knepley if (tensor) { 57355f82726aSMatthew G. Knepley *dof = PetscPowInt(k + 1, dim); 57365f82726aSMatthew G. Knepley } else { 57375f82726aSMatthew G. Knepley switch (dim) { 57385f82726aSMatthew G. Knepley case 1: 57395f82726aSMatthew G. Knepley *dof = k + 1; 57405f82726aSMatthew G. Knepley break; 57415f82726aSMatthew G. Knepley case 2: 57425f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2)) / 2; 57435f82726aSMatthew G. Knepley break; 57445f82726aSMatthew G. Knepley case 3: 57455f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2) * (k + 3)) / 6; 57465f82726aSMatthew G. Knepley break; 57475f82726aSMatthew G. Knepley default: 57485f82726aSMatthew G. Knepley *dof = 0; 57495f82726aSMatthew G. Knepley } 57509e8305c2SJed Brown } 57513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57529e8305c2SJed Brown } 57539e8305c2SJed Brown 5754a4355906SMatthew Knepley /*@ 5755bc1eb3faSJed Brown 5756bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5757bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 575820f4b53cSBarry Smith section provided (or the section of the `DM`). 5759a4355906SMatthew Knepley 5760a4355906SMatthew Knepley Input Parameters: 576120f4b53cSBarry Smith + dm - The `DM` 576220f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 576320f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5764a4355906SMatthew Knepley 5765bc1eb3faSJed Brown Example: 5766bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5767bc1eb3faSJed Brown .vb 5768bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5769bc1eb3faSJed Brown 5770bc1eb3faSJed Brown v4 -- e6 -- v3 5771bc1eb3faSJed Brown | | 5772bc1eb3faSJed Brown e7 c0 e8 5773bc1eb3faSJed Brown | | 5774bc1eb3faSJed Brown v1 -- e5 -- v2 5775bc1eb3faSJed Brown .ve 5776bc1eb3faSJed Brown 5777bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5778bc1eb3faSJed Brown dofs in the order of points, e.g., 5779bc1eb3faSJed Brown .vb 5780bc1eb3faSJed Brown c0 -> [0,1,2,3] 5781bc1eb3faSJed Brown v1 -> [4] 5782bc1eb3faSJed Brown ... 5783bc1eb3faSJed Brown e5 -> [8, 9] 5784bc1eb3faSJed Brown .ve 5785bc1eb3faSJed Brown 5786bc1eb3faSJed Brown which corresponds to the dofs 5787bc1eb3faSJed Brown .vb 5788bc1eb3faSJed Brown 6 10 11 7 5789bc1eb3faSJed Brown 13 2 3 15 5790bc1eb3faSJed Brown 12 0 1 14 5791bc1eb3faSJed Brown 4 8 9 5 5792bc1eb3faSJed Brown .ve 5793bc1eb3faSJed Brown 5794bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5795bc1eb3faSJed Brown .vb 5796bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5797bc1eb3faSJed Brown .ve 5798bc1eb3faSJed Brown 5799bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5800bc1eb3faSJed Brown .vb 5801bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5802bc1eb3faSJed Brown .ve 5803bc1eb3faSJed Brown 5804a4355906SMatthew Knepley Level: developer 5805a4355906SMatthew Knepley 5806da9ac489SAlbert Cowie Notes: 5807a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5808a1cb98faSBarry Smith degree of the basis. 5809a1cb98faSBarry Smith 5810da9ac489SAlbert Cowie This is required to run with libCEED. 5811da9ac489SAlbert Cowie 58121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5813a4355906SMatthew Knepley @*/ 5814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5815d71ae5a4SJacob Faibussowitsch { 58167391a63aSMatthew G. Knepley DMLabel label; 5817bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 58185f82726aSMatthew G. Knepley PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE; 58193194fc30SMatthew G. Knepley 58203194fc30SMatthew G. Knepley PetscFunctionBegin; 58219566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 58223ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5823a433471fSStefano Zampini if (point < 0) { 5824a433471fSStefano Zampini PetscInt sStart, sEnd; 5825a433471fSStefano Zampini 58269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5827a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5828a433471fSStefano Zampini } 58299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 58309566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 58319566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 58329371c9d4SSatish Balay if (depth == 1) { 58339371c9d4SSatish Balay eStart = point; 58349371c9d4SSatish Balay } else if (depth == dim) { 58357391a63aSMatthew G. Knepley const PetscInt *cone; 58367391a63aSMatthew G. Knepley 58379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5838d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5839d4e6627bSStefano Zampini else if (dim == 3) { 5840d4e6627bSStefano Zampini const PetscInt *cone2; 58419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5842d4e6627bSStefano Zampini eStart = cone2[0]; 584363a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " of depth %" PetscInt_FMT " cannot be used to bootstrap spectral ordering for dim %" PetscInt_FMT, point, depth, dim); 584463a3b9bcSJacob Faibussowitsch } else PetscCheck(depth < 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " of depth %" PetscInt_FMT " cannot be used to bootstrap spectral ordering for dim %" PetscInt_FMT, point, depth, dim); 5845e327e467SRezgar Shakeri 58469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5847bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5848bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5849bb197d40SJed Brown PetscInt *perm; 5850bb197d40SJed Brown 58513194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 58525f82726aSMatthew G. Knepley PetscInt dof; 58535f82726aSMatthew G. Knepley 58545f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58555f82726aSMatthew G. Knepley PetscCheck(dim == 1 || tensor || !continuous, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Continuous field %" PetscInt_FMT " must have a tensor product discretization", f); 58565f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58575f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58585f82726aSMatthew G. Knepley size += dof * Nc; 58593194fc30SMatthew G. Knepley } 58609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 58613194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5862bb197d40SJed Brown switch (d) { 5863babf31e0SJed Brown case 1: 58645f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58655f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 5866babf31e0SJed Brown /* 5867babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5868babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5869babf31e0SJed Brown */ 5870e327e467SRezgar Shakeri if (continuous) { 5871babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 58729371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 58739371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5874babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5875babf31e0SJed Brown foffset = offset; 5876e327e467SRezgar Shakeri } else { 58775f82726aSMatthew G. Knepley PetscInt dof; 58785f82726aSMatthew G. Knepley 58795f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58805f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 58815f82726aSMatthew G. Knepley foffset = offset; 5882e327e467SRezgar Shakeri } 5883babf31e0SJed Brown break; 588489eabcffSMatthew G. Knepley case 2: 58853194fc30SMatthew 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} */ 58865f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58875f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58883194fc30SMatthew G. Knepley /* The SEM order is 58893194fc30SMatthew G. Knepley 58903194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 589189eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 58923194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 58933194fc30SMatthew G. Knepley */ 5894e327e467SRezgar Shakeri if (continuous) { 58953194fc30SMatthew G. Knepley const PetscInt of = 0; 58963194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 58973194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 58983194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 58993194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 59003194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 59013194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 59023194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 59033194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 59043194fc30SMatthew G. Knepley PetscInt o; 59053194fc30SMatthew G. Knepley 59063194fc30SMatthew G. Knepley /* bottom */ 59073194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 59089371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 59099371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59103194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 59113194fc30SMatthew G. Knepley /* middle */ 59123194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 59133194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 59149371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 59159371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59163194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 59173194fc30SMatthew G. Knepley } 59183194fc30SMatthew G. Knepley /* top */ 59193194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 59209371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 59219371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59223194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 59233194fc30SMatthew G. Knepley foffset = offset; 5924e327e467SRezgar Shakeri } else { 59255f82726aSMatthew G. Knepley PetscInt dof; 59265f82726aSMatthew G. Knepley 59275f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 59285f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 59295f82726aSMatthew G. Knepley foffset = offset; 59303194fc30SMatthew G. Knepley } 593189eabcffSMatthew G. Knepley break; 593289eabcffSMatthew G. Knepley case 3: 593389eabcffSMatthew G. Knepley /* The original hex closure is 593489eabcffSMatthew G. Knepley 593589eabcffSMatthew G. Knepley {c, 593689eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 593789eabcffSMatthew 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, 593889eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 593989eabcffSMatthew G. Knepley */ 59405f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 59415f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 594289eabcffSMatthew G. Knepley /* The SEM order is 594389eabcffSMatthew G. Knepley Bottom Slice 594489eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 594589eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 594689eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 594789eabcffSMatthew G. Knepley 594889eabcffSMatthew G. Knepley Middle Slice (j) 594989eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 595089eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 595189eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 595289eabcffSMatthew G. Knepley 595389eabcffSMatthew G. Knepley Top Slice 595489eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 595589eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 595689eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 595789eabcffSMatthew G. Knepley */ 5958e327e467SRezgar Shakeri if (continuous) { 595989eabcffSMatthew G. Knepley const PetscInt oc = 0; 596089eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 596189eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 596289eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 596389eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 596489eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 596589eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 596689eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 596789eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 596889eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 596989eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 597089eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 597189eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 597289eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 597389eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 597489eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 597589eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 597689eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 597789eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 597889eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 597989eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 598089eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 598189eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 598289eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 598389eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 598489eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 598589eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 598689eabcffSMatthew G. Knepley PetscInt o, n; 598789eabcffSMatthew G. Knepley 598889eabcffSMatthew G. Knepley /* Bottom Slice */ 598989eabcffSMatthew G. Knepley /* bottom */ 599089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 59919371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 59929371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 599389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 599489eabcffSMatthew G. Knepley /* middle */ 599589eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 599689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 59979371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 59989371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 59999371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 60009371c9d4SSatish Balay } 600189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 60023194fc30SMatthew G. Knepley } 600389eabcffSMatthew G. Knepley /* top */ 600489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 60059371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 60069371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 600789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 600889eabcffSMatthew G. Knepley 600989eabcffSMatthew G. Knepley /* Middle Slice */ 601089eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 601189eabcffSMatthew G. Knepley /* bottom */ 601289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 60139371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 60149371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 601589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 601689eabcffSMatthew G. Knepley /* middle */ 601789eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 601889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 60199371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60209371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 602189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 602289eabcffSMatthew G. Knepley } 602389eabcffSMatthew G. Knepley /* top */ 602489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 60259371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 60269371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 602789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 602889eabcffSMatthew G. Knepley } 602989eabcffSMatthew G. Knepley 603089eabcffSMatthew G. Knepley /* Top Slice */ 603189eabcffSMatthew G. Knepley /* bottom */ 603289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 60339371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 60349371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 603589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 603689eabcffSMatthew G. Knepley /* middle */ 603789eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 603889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 60399371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60409371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 604189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 604289eabcffSMatthew G. Knepley } 604389eabcffSMatthew G. Knepley /* top */ 604489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 60459371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 60469371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 604789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 604889eabcffSMatthew G. Knepley 604989eabcffSMatthew G. Knepley foffset = offset; 6050e327e467SRezgar Shakeri } else { 60515f82726aSMatthew G. Knepley PetscInt dof; 60525f82726aSMatthew G. Knepley 60535f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60545f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 60555f82726aSMatthew G. Knepley foffset = offset; 605689eabcffSMatthew G. Knepley } 605789eabcffSMatthew G. Knepley break; 6058d71ae5a4SJacob Faibussowitsch default: 6059d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 606089eabcffSMatthew G. Knepley } 606189eabcffSMatthew G. Knepley } 606263a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 60633194fc30SMatthew G. Knepley /* Check permutation */ 60643194fc30SMatthew G. Knepley { 60653194fc30SMatthew G. Knepley PetscInt *check; 60663194fc30SMatthew G. Knepley 60679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 60681dca8a05SBarry Smith for (i = 0; i < size; ++i) { 60691dca8a05SBarry Smith check[i] = -1; 60701dca8a05SBarry Smith PetscCheck(perm[i] >= 0 && perm[i] < size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid permutation index p[%" PetscInt_FMT "] = %" PetscInt_FMT, i, perm[i]); 60711dca8a05SBarry Smith } 60723194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 60731dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 60749566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 60753194fc30SMatthew G. Knepley } 60769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6077a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6078a05c9aa3SJed Brown PetscInt *loc_perm; 60799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6080a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6081a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6082a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6083a05c9aa3SJed Brown } 60849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6085a05c9aa3SJed Brown } 6086bb197d40SJed Brown } 60873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60883194fc30SMatthew G. Knepley } 60893194fc30SMatthew G. Knepley 6090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6091d71ae5a4SJacob Faibussowitsch { 6092e071409bSToby Isaac PetscDS prob; 6093e071409bSToby Isaac PetscInt depth, Nf, h; 6094e071409bSToby Isaac DMLabel label; 6095e071409bSToby Isaac 6096e071409bSToby Isaac PetscFunctionBeginHot; 60979566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6098e071409bSToby Isaac Nf = prob->Nf; 6099e071409bSToby Isaac label = dm->depthLabel; 6100e071409bSToby Isaac *dspace = NULL; 6101e071409bSToby Isaac if (field < Nf) { 6102e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6103e071409bSToby Isaac 6104e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6105e071409bSToby Isaac PetscDualSpace dsp; 6106e071409bSToby Isaac 61079566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 61089566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 61099566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6110e071409bSToby Isaac h = depth - 1 - h; 6111e071409bSToby Isaac if (h) { 61129566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6113e071409bSToby Isaac } else { 6114e071409bSToby Isaac *dspace = dsp; 6115e071409bSToby Isaac } 6116e071409bSToby Isaac } 6117e071409bSToby Isaac } 61183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6119e071409bSToby Isaac } 6120e071409bSToby Isaac 6121d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6122d71ae5a4SJacob Faibussowitsch { 612328351e22SJed Brown PetscScalar *array; 612428351e22SJed Brown const PetscScalar *vArray; 6125d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 61261a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6127552f7358SJed Brown 61281b406b76SMatthew G. Knepley PetscFunctionBeginHot; 61299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 61309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 61319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 61329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 61333f7cbbe7SMatthew G. Knepley if (!values || !*values) { 61349df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61359df71ca4SMatthew G. Knepley PetscInt dof; 6136d9917b9dSMatthew G. Knepley 61379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61389df71ca4SMatthew G. Knepley size += dof; 61399df71ca4SMatthew G. Knepley } 61409df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61419df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61422a3aaacfSMatthew G. Knepley PetscInt dof; 61435a1bb5cfSMatthew G. Knepley 61445a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61465a1bb5cfSMatthew G. Knepley size += dof; 61475a1bb5cfSMatthew G. Knepley } 61483f7cbbe7SMatthew G. Knepley if (!values) { 61493f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 61503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61513f7cbbe7SMatthew G. Knepley } 61529566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6153982e9ed1SMatthew G. Knepley } else { 6154982e9ed1SMatthew G. Knepley array = *values; 6155982e9ed1SMatthew G. Knepley } 61569df71ca4SMatthew G. Knepley size = 0; 615728351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 61589df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61599df71ca4SMatthew G. Knepley PetscInt dof, off, d; 616028351e22SJed Brown const PetscScalar *varr; 6161d9917b9dSMatthew G. Knepley 61629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 61648e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 6165ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61669df71ca4SMatthew G. Knepley size += dof; 61679df71ca4SMatthew G. Knepley } 61689df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61699df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61709df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 61715a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 617228351e22SJed Brown const PetscScalar *varr; 61735a1bb5cfSMatthew G. Knepley 617452ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 61778e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 61785a1bb5cfSMatthew G. Knepley if (o >= 0) { 6179ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61805a1bb5cfSMatthew G. Knepley } else { 6181ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 61825a1bb5cfSMatthew G. Knepley } 61839df71ca4SMatthew G. Knepley size += dof; 61845a1bb5cfSMatthew G. Knepley } 618528351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 61869df71ca4SMatthew G. Knepley if (!*values) { 61875a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 61885a1bb5cfSMatthew G. Knepley *values = array; 61899df71ca4SMatthew G. Knepley } else { 619063a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 61918c312ff3SMatthew G. Knepley *csize = size; 61929df71ca4SMatthew G. Knepley } 61933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61945a1bb5cfSMatthew G. Knepley } 6195d9917b9dSMatthew G. Knepley 619627f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6197d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6198d71ae5a4SJacob Faibussowitsch { 619927f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 620027f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 620127f02ce8SMatthew G. Knepley 62029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 620327f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 620427f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 620527f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 620627f02ce8SMatthew G. Knepley points[q * 2] = r; 620727f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 620827f02ce8SMatthew G. Knepley ++q; 620927f02ce8SMatthew G. Knepley } 621027f02ce8SMatthew G. Knepley } 621127f02ce8SMatthew G. Knepley *numPoints = q; 62123ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 621327f02ce8SMatthew G. Knepley } 621427f02ce8SMatthew G. Knepley 621597529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 621607218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6217d71ae5a4SJacob Faibussowitsch { 621827f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6219923c78e0SToby Isaac PetscInt np, *pts = NULL; 6220923c78e0SToby Isaac 6221923c78e0SToby Isaac PetscFunctionBeginHot; 62229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 622307218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6224923c78e0SToby Isaac PetscInt dof, off; 6225923c78e0SToby Isaac 62269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 62279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 62289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6229923c78e0SToby Isaac np = dof / 2; 62308e3a54c0SPierre Jolivet pts = PetscSafePointerPlusOffset((PetscInt *)cla, off); 623127f02ce8SMatthew G. Knepley } else { 623207218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 62339566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6234923c78e0SToby Isaac } 6235923c78e0SToby Isaac *numPoints = np; 6236923c78e0SToby Isaac *points = pts; 6237923c78e0SToby Isaac *clp = cla; 62383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6239923c78e0SToby Isaac } 6240923c78e0SToby Isaac 6241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6242d71ae5a4SJacob Faibussowitsch { 6243923c78e0SToby Isaac PetscFunctionBeginHot; 6244923c78e0SToby Isaac if (!*clPoints) { 62459566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6246923c78e0SToby Isaac } else { 62479566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6248923c78e0SToby Isaac } 6249923c78e0SToby Isaac *numPoints = 0; 6250923c78e0SToby Isaac *points = NULL; 6251923c78e0SToby Isaac *clSec = NULL; 6252923c78e0SToby Isaac *clPoints = NULL; 6253923c78e0SToby Isaac *clp = NULL; 62543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6255923c78e0SToby Isaac } 6256923c78e0SToby Isaac 6257d71ae5a4SJacob 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[]) 6258d71ae5a4SJacob Faibussowitsch { 62591a271a75SMatthew G. Knepley PetscInt offset = 0, p; 626097e99dd9SToby Isaac const PetscInt **perms = NULL; 626197e99dd9SToby Isaac const PetscScalar **flips = NULL; 62621a271a75SMatthew G. Knepley 62631a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6264fe02ba77SJed Brown *size = 0; 62659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 626697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 626797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 626897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 626997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 62701a271a75SMatthew G. Knepley PetscInt dof, off, d; 62711a271a75SMatthew G. Knepley const PetscScalar *varr; 62721a271a75SMatthew G. Knepley 62739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 62749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 62758e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 627697e99dd9SToby Isaac if (clperm) { 627797e99dd9SToby Isaac if (perm) { 627897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 62791a271a75SMatthew G. Knepley } else { 628097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 628197e99dd9SToby Isaac } 628297e99dd9SToby Isaac if (flip) { 628397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 628497e99dd9SToby Isaac } 628597e99dd9SToby Isaac } else { 628697e99dd9SToby Isaac if (perm) { 628797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 628897e99dd9SToby Isaac } else { 628997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 629097e99dd9SToby Isaac } 629197e99dd9SToby Isaac if (flip) { 629297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 62931a271a75SMatthew G. Knepley } 62941a271a75SMatthew G. Knepley } 629597e99dd9SToby Isaac offset += dof; 629697e99dd9SToby Isaac } 62979566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 62981a271a75SMatthew G. Knepley *size = offset; 62993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63001a271a75SMatthew G. Knepley } 63011a271a75SMatthew G. Knepley 6302d71ae5a4SJacob 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[]) 6303d71ae5a4SJacob Faibussowitsch { 63041a271a75SMatthew G. Knepley PetscInt offset = 0, f; 63051a271a75SMatthew G. Knepley 63061a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6307fe02ba77SJed Brown *size = 0; 63081a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 630997e99dd9SToby Isaac PetscInt p; 631097e99dd9SToby Isaac const PetscInt **perms = NULL; 631197e99dd9SToby Isaac const PetscScalar **flips = NULL; 63121a271a75SMatthew G. Knepley 63139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 631497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 631597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 631697e99dd9SToby Isaac PetscInt fdof, foff, b; 63171a271a75SMatthew G. Knepley const PetscScalar *varr; 631897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 631997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63201a271a75SMatthew G. Knepley 63219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 63229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 63231a271a75SMatthew G. Knepley varr = &vArray[foff]; 632497e99dd9SToby Isaac if (clperm) { 63259371c9d4SSatish Balay if (perm) { 6326ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 63271a271a75SMatthew G. Knepley } else { 6328ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 63299371c9d4SSatish Balay } 63309371c9d4SSatish Balay if (flip) { 6331ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 63329371c9d4SSatish Balay } 63339371c9d4SSatish Balay } else { 63349371c9d4SSatish Balay if (perm) { 6335ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 63369371c9d4SSatish Balay } else { 6337ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 63389371c9d4SSatish Balay } 63399371c9d4SSatish Balay if (flip) { 6340ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 63419371c9d4SSatish Balay } 63421a271a75SMatthew G. Knepley } 634397e99dd9SToby Isaac offset += fdof; 63441a271a75SMatthew G. Knepley } 63459566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 63461a271a75SMatthew G. Knepley } 63471a271a75SMatthew G. Knepley *size = offset; 63483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63491a271a75SMatthew G. Knepley } 63501a271a75SMatthew G. Knepley 6351e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 635207218a29SMatthew G. Knepley { 635307218a29SMatthew G. Knepley PetscSection clSection; 635407218a29SMatthew G. Knepley IS clPoints; 635507218a29SMatthew G. Knepley PetscInt *points = NULL; 6356e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 635707218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 635807218a29SMatthew G. Knepley 635907218a29SMatthew G. Knepley PetscFunctionBeginHot; 636007218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 636107218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 636207218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6363e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 636407218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 636507218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 636607218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 636707218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 636807218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 636907218a29SMatthew G. Knepley } 637007218a29SMatthew G. Knepley /* Get points */ 637107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 637207218a29SMatthew G. Knepley /* Get sizes */ 637307218a29SMatthew G. Knepley asize = 0; 637407218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 637507218a29SMatthew G. Knepley PetscInt dof; 637607218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 637707218a29SMatthew G. Knepley asize += dof; 637807218a29SMatthew G. Knepley } 637907218a29SMatthew G. Knepley if (values) { 638007218a29SMatthew G. Knepley const PetscScalar *vArray; 638107218a29SMatthew G. Knepley PetscInt size; 638207218a29SMatthew G. Knepley 638307218a29SMatthew G. Knepley if (*values) { 638407218a29SMatthew G. Knepley PetscCheck(*csize >= asize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %" PetscInt_FMT " not sufficient to hold closure size %" PetscInt_FMT, *csize, asize); 638507218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6386e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 638707218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 638807218a29SMatthew G. Knepley /* Get values */ 638907218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 639007218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 639107218a29SMatthew G. Knepley PetscCheck(asize == size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size); 639207218a29SMatthew G. Knepley /* Cleanup array */ 639307218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 639407218a29SMatthew G. Knepley } 639507218a29SMatthew G. Knepley if (csize) *csize = asize; 639607218a29SMatthew G. Knepley /* Cleanup points */ 639707218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 639807218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 639907218a29SMatthew G. Knepley } 640007218a29SMatthew G. Knepley 6401552f7358SJed Brown /*@C 6402552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6403552f7358SJed Brown 6404552f7358SJed Brown Not collective 6405552f7358SJed Brown 6406552f7358SJed Brown Input Parameters: 6407a1cb98faSBarry Smith + dm - The `DM` 640820f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6409552f7358SJed Brown . v - The local vector 6410a1cb98faSBarry Smith - point - The point in the `DM` 6411552f7358SJed Brown 64126b867d5aSJose E. Roman Input/Output Parameters: 641320f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 641420f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically; 641520f4b53cSBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed 641622c1ee49SMatthew G. Knepley 6417552f7358SJed Brown Level: intermediate 6418552f7358SJed Brown 6419a1cb98faSBarry Smith Notes: 642020f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6421a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6422a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6423a1cb98faSBarry Smith 6424a1cb98faSBarry Smith A typical use could be 6425a1cb98faSBarry Smith .vb 6426a1cb98faSBarry Smith values = NULL; 6427a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6428a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6429a1cb98faSBarry Smith <Compute on closure> 6430a1cb98faSBarry Smith } 6431a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6432a1cb98faSBarry Smith .ve 6433a1cb98faSBarry Smith or 6434a1cb98faSBarry Smith .vb 6435a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6436a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6437a1cb98faSBarry Smith clSize = clMaxSize; 6438a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6439a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6440a1cb98faSBarry Smith <Compute on closure> 6441a1cb98faSBarry Smith } 6442a1cb98faSBarry Smith } 6443a1cb98faSBarry Smith PetscFree(values); 6444a1cb98faSBarry Smith .ve 6445a1cb98faSBarry Smith 644660225df5SJacob Faibussowitsch Fortran Notes: 644720f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6448a1cb98faSBarry Smith 64491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6450552f7358SJed Brown @*/ 6451d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6452d71ae5a4SJacob Faibussowitsch { 6453d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6454e8e188d2SZach Atkins PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 64553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6456552f7358SJed Brown } 6457552f7358SJed Brown 6458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6459d71ae5a4SJacob Faibussowitsch { 6460e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6461e5c487bfSMatthew G. Knepley PetscSection clSection; 6462e5c487bfSMatthew G. Knepley IS clPoints; 6463e5c487bfSMatthew G. Knepley PetscScalar *array; 6464e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6465e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6466c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6467c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6468e5c487bfSMatthew G. Knepley 6469e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6470e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64719566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6472e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6473e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 64759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 64769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6477e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 64789566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 64793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6480e5c487bfSMatthew G. Knepley } 6481e5c487bfSMatthew G. Knepley /* Get points */ 648207218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6483c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6484c459fbc1SJed Brown PetscInt dof; 64859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6486c459fbc1SJed Brown clsize += dof; 6487c459fbc1SJed Brown } 64889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6489e5c487bfSMatthew G. Knepley /* Filter points */ 6490e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6491e5c487bfSMatthew G. Knepley PetscInt dep; 6492e5c487bfSMatthew G. Knepley 64939566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6494e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6495e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6496e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6497e5c487bfSMatthew G. Knepley ++Np; 6498e5c487bfSMatthew G. Knepley } 6499e5c487bfSMatthew G. Knepley /* Get array */ 6500e5c487bfSMatthew G. Knepley if (!values || !*values) { 6501e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6502e5c487bfSMatthew G. Knepley 6503e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 65049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6505e5c487bfSMatthew G. Knepley asize += dof; 6506e5c487bfSMatthew G. Knepley } 6507e5c487bfSMatthew G. Knepley if (!values) { 65089566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6509e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 65103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6511e5c487bfSMatthew G. Knepley } 65129566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6513e5c487bfSMatthew G. Knepley } else { 6514e5c487bfSMatthew G. Knepley array = *values; 6515e5c487bfSMatthew G. Knepley } 65169566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6517e5c487bfSMatthew G. Knepley /* Get values */ 65189566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 65199566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6520e5c487bfSMatthew G. Knepley /* Cleanup points */ 65219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6522e5c487bfSMatthew G. Knepley /* Cleanup array */ 65239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6524e5c487bfSMatthew G. Knepley if (!*values) { 6525e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6526e5c487bfSMatthew G. Knepley *values = array; 6527e5c487bfSMatthew G. Knepley } else { 652863a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6529e5c487bfSMatthew G. Knepley *csize = size; 6530e5c487bfSMatthew G. Knepley } 65313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6532e5c487bfSMatthew G. Knepley } 6533e5c487bfSMatthew G. Knepley 6534552f7358SJed Brown /*@C 6535552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6536552f7358SJed Brown 6537552f7358SJed Brown Not collective 6538552f7358SJed Brown 6539552f7358SJed Brown Input Parameters: 6540a1cb98faSBarry Smith + dm - The `DM` 654120f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6542552f7358SJed Brown . v - The local vector 6543a1cb98faSBarry Smith . point - The point in the `DM` 654420f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6545552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6546552f7358SJed Brown 6547552f7358SJed Brown Level: intermediate 6548552f7358SJed Brown 6549a1cb98faSBarry Smith Note: 655020f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6551a1cb98faSBarry Smith 655260225df5SJacob Faibussowitsch Fortran Notes: 655320f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6554a1cb98faSBarry Smith 65551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6556552f7358SJed Brown @*/ 6557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6558d71ae5a4SJacob Faibussowitsch { 6559552f7358SJed Brown PetscInt size = 0; 6560552f7358SJed Brown 6561552f7358SJed Brown PetscFunctionBegin; 6562552f7358SJed Brown /* Should work without recalculating size */ 65639566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6564c9fdaa05SMatthew G. Knepley *values = NULL; 65653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6566552f7358SJed Brown } 6567552f7358SJed Brown 6568d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6569d71ae5a4SJacob Faibussowitsch { 65709371c9d4SSatish Balay *x += y; 65719371c9d4SSatish Balay } 6572d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6573d71ae5a4SJacob Faibussowitsch { 65749371c9d4SSatish Balay *x = y; 65759371c9d4SSatish Balay } 6576552f7358SJed Brown 6577d71ae5a4SJacob 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[]) 6578d71ae5a4SJacob Faibussowitsch { 6579552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6580552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6581552f7358SJed Brown PetscScalar *a; 6582552f7358SJed Brown PetscInt off, cind = 0, k; 6583552f7358SJed Brown 6584552f7358SJed Brown PetscFunctionBegin; 65859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 65869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6587552f7358SJed Brown a = &array[off]; 6588552f7358SJed Brown if (!cdof || setBC) { 658997e99dd9SToby Isaac if (clperm) { 65909371c9d4SSatish Balay if (perm) { 6591ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6592552f7358SJed Brown } else { 6593ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 65949371c9d4SSatish Balay } 65959371c9d4SSatish Balay } else { 65969371c9d4SSatish Balay if (perm) { 6597ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 65989371c9d4SSatish Balay } else { 6599ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 66009371c9d4SSatish Balay } 6601552f7358SJed Brown } 6602552f7358SJed Brown } else { 66039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 660497e99dd9SToby Isaac if (clperm) { 66059371c9d4SSatish Balay if (perm) { 66069371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 66079371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66089371c9d4SSatish Balay ++cind; 66099371c9d4SSatish Balay continue; 66109371c9d4SSatish Balay } 661197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6612552f7358SJed Brown } 6613552f7358SJed Brown } else { 6614552f7358SJed Brown for (k = 0; k < dof; ++k) { 66159371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66169371c9d4SSatish Balay ++cind; 66179371c9d4SSatish Balay continue; 66189371c9d4SSatish Balay } 661997e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 662097e99dd9SToby Isaac } 662197e99dd9SToby Isaac } 662297e99dd9SToby Isaac } else { 662397e99dd9SToby Isaac if (perm) { 662497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66259371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66269371c9d4SSatish Balay ++cind; 66279371c9d4SSatish Balay continue; 66289371c9d4SSatish Balay } 662997e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 663097e99dd9SToby Isaac } 663197e99dd9SToby Isaac } else { 663297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66339371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66349371c9d4SSatish Balay ++cind; 66359371c9d4SSatish Balay continue; 66369371c9d4SSatish Balay } 663797e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 663897e99dd9SToby Isaac } 6639552f7358SJed Brown } 6640552f7358SJed Brown } 6641552f7358SJed Brown } 66423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6643552f7358SJed Brown } 6644552f7358SJed Brown 6645d71ae5a4SJacob 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[]) 6646d71ae5a4SJacob Faibussowitsch { 6647a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6648a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6649a5e93ea8SMatthew G. Knepley PetscScalar *a; 6650a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6651a5e93ea8SMatthew G. Knepley 6652a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 66539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 66549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6655a5e93ea8SMatthew G. Knepley a = &array[off]; 6656a5e93ea8SMatthew G. Knepley if (cdof) { 66579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 665897e99dd9SToby Isaac if (clperm) { 665997e99dd9SToby Isaac if (perm) { 6660a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6661a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 666297e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 666397e99dd9SToby Isaac cind++; 6664a5e93ea8SMatthew G. Knepley } 6665a5e93ea8SMatthew G. Knepley } 6666a5e93ea8SMatthew G. Knepley } else { 6667a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6668a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 666997e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 667097e99dd9SToby Isaac cind++; 667197e99dd9SToby Isaac } 667297e99dd9SToby Isaac } 667397e99dd9SToby Isaac } 667497e99dd9SToby Isaac } else { 667597e99dd9SToby Isaac if (perm) { 667697e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 667797e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 667897e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 667997e99dd9SToby Isaac cind++; 668097e99dd9SToby Isaac } 668197e99dd9SToby Isaac } 668297e99dd9SToby Isaac } else { 668397e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 668497e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 668597e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 668697e99dd9SToby Isaac cind++; 668797e99dd9SToby Isaac } 6688a5e93ea8SMatthew G. Knepley } 6689a5e93ea8SMatthew G. Knepley } 6690a5e93ea8SMatthew G. Knepley } 6691a5e93ea8SMatthew G. Knepley } 66923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6693a5e93ea8SMatthew G. Knepley } 6694a5e93ea8SMatthew G. Knepley 6695d71ae5a4SJacob 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[]) 6696d71ae5a4SJacob Faibussowitsch { 6697552f7358SJed Brown PetscScalar *a; 66981a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 66991a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 670097e99dd9SToby Isaac PetscInt cind = 0, b; 6701552f7358SJed Brown 6702552f7358SJed Brown PetscFunctionBegin; 67039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67061a271a75SMatthew G. Knepley a = &array[foff]; 6707552f7358SJed Brown if (!fcdof || setBC) { 670897e99dd9SToby Isaac if (clperm) { 67099371c9d4SSatish Balay if (perm) { 6710ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6711552f7358SJed Brown } else { 6712ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 67139371c9d4SSatish Balay } 67149371c9d4SSatish Balay } else { 67159371c9d4SSatish Balay if (perm) { 6716ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 67179371c9d4SSatish Balay } else { 6718ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 67199371c9d4SSatish Balay } 6720552f7358SJed Brown } 6721552f7358SJed Brown } else { 67229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 672397e99dd9SToby Isaac if (clperm) { 672497e99dd9SToby Isaac if (perm) { 672597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67269371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67279371c9d4SSatish Balay ++cind; 67289371c9d4SSatish Balay continue; 67299371c9d4SSatish Balay } 673097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6731552f7358SJed Brown } 6732552f7358SJed Brown } else { 673397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67349371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67359371c9d4SSatish Balay ++cind; 67369371c9d4SSatish Balay continue; 67379371c9d4SSatish Balay } 673897e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 673997e99dd9SToby Isaac } 674097e99dd9SToby Isaac } 674197e99dd9SToby Isaac } else { 674297e99dd9SToby Isaac if (perm) { 674397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67449371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67459371c9d4SSatish Balay ++cind; 67469371c9d4SSatish Balay continue; 67479371c9d4SSatish Balay } 674897e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 674997e99dd9SToby Isaac } 675097e99dd9SToby Isaac } else { 675197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67529371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67539371c9d4SSatish Balay ++cind; 67549371c9d4SSatish Balay continue; 67559371c9d4SSatish Balay } 675697e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6757552f7358SJed Brown } 6758552f7358SJed Brown } 6759552f7358SJed Brown } 6760552f7358SJed Brown } 67611a271a75SMatthew G. Knepley *offset += fdof; 67623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6763552f7358SJed Brown } 6764552f7358SJed Brown 6765d71ae5a4SJacob 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[]) 6766d71ae5a4SJacob Faibussowitsch { 6767a5e93ea8SMatthew G. Knepley PetscScalar *a; 67681a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 67691a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67705da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6771ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6772a5e93ea8SMatthew G. Knepley 6773a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 67749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 67759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67781a271a75SMatthew G. Knepley a = &array[foff]; 6779a5e93ea8SMatthew G. Knepley if (fcdof) { 6780ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 67819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 678297e99dd9SToby Isaac if (clperm) { 678397e99dd9SToby Isaac if (perm) { 6784ba322698SMatthew G. Knepley if (comps) { 6785ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6786ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67879371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67889371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67899371c9d4SSatish Balay ncSet = PETSC_TRUE; 67909371c9d4SSatish Balay } 67919371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67929371c9d4SSatish Balay ++cind; 67939371c9d4SSatish Balay fcSet = PETSC_TRUE; 67949371c9d4SSatish Balay } 6795ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6796ba322698SMatthew G. Knepley } 6797ba322698SMatthew G. Knepley } else { 679897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 679997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 680097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6801a5e93ea8SMatthew G. Knepley ++cind; 6802a5e93ea8SMatthew G. Knepley } 6803a5e93ea8SMatthew G. Knepley } 6804ba322698SMatthew G. Knepley } 6805ba322698SMatthew G. Knepley } else { 6806ba322698SMatthew G. Knepley if (comps) { 6807ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6808ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68099371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68109371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68119371c9d4SSatish Balay ncSet = PETSC_TRUE; 68129371c9d4SSatish Balay } 68139371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68149371c9d4SSatish Balay ++cind; 68159371c9d4SSatish Balay fcSet = PETSC_TRUE; 68169371c9d4SSatish Balay } 6817ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6818ba322698SMatthew G. Knepley } 6819a5e93ea8SMatthew G. Knepley } else { 682097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 682197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 682297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 682397e99dd9SToby Isaac ++cind; 682497e99dd9SToby Isaac } 682597e99dd9SToby Isaac } 682697e99dd9SToby Isaac } 6827ba322698SMatthew G. Knepley } 682897e99dd9SToby Isaac } else { 682997e99dd9SToby Isaac if (perm) { 6830ba322698SMatthew G. Knepley if (comps) { 6831ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6832ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68339371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68349371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68359371c9d4SSatish Balay ncSet = PETSC_TRUE; 68369371c9d4SSatish Balay } 68379371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68389371c9d4SSatish Balay ++cind; 68399371c9d4SSatish Balay fcSet = PETSC_TRUE; 68409371c9d4SSatish Balay } 6841ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6842ba322698SMatthew G. Knepley } 6843ba322698SMatthew G. Knepley } else { 684497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 684597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 684697e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 684797e99dd9SToby Isaac ++cind; 684897e99dd9SToby Isaac } 684997e99dd9SToby Isaac } 6850ba322698SMatthew G. Knepley } 6851ba322698SMatthew G. Knepley } else { 6852ba322698SMatthew G. Knepley if (comps) { 6853ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6854ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68559371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68569371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68579371c9d4SSatish Balay ncSet = PETSC_TRUE; 68589371c9d4SSatish Balay } 68599371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68609371c9d4SSatish Balay ++cind; 68619371c9d4SSatish Balay fcSet = PETSC_TRUE; 68629371c9d4SSatish Balay } 6863ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6864ba322698SMatthew G. Knepley } 686597e99dd9SToby Isaac } else { 686697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 686797e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 686897e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6869a5e93ea8SMatthew G. Knepley ++cind; 6870a5e93ea8SMatthew G. Knepley } 6871a5e93ea8SMatthew G. Knepley } 6872a5e93ea8SMatthew G. Knepley } 6873a5e93ea8SMatthew G. Knepley } 6874a5e93ea8SMatthew G. Knepley } 6875ba322698SMatthew G. Knepley } 68761a271a75SMatthew G. Knepley *offset += fdof; 68773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6878a5e93ea8SMatthew G. Knepley } 6879a5e93ea8SMatthew G. Knepley 6880d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6881d71ae5a4SJacob Faibussowitsch { 6882552f7358SJed Brown PetscScalar *array; 68831b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 68841b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6885552f7358SJed Brown 68861b406b76SMatthew G. Knepley PetscFunctionBeginHot; 68879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 68889566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 68899566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 68909566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 68919566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6892b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6893b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6894b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6895b6ebb6e6SMatthew G. Knepley 68969371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 68979371c9d4SSatish Balay dof = 0; 68989371c9d4SSatish Balay continue; 68999371c9d4SSatish Balay } 69009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6901b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6902b6ebb6e6SMatthew G. Knepley { 6903b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6904b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6905b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6906b6ebb6e6SMatthew G. Knepley 69079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 69089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6909b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6910b6ebb6e6SMatthew G. Knepley if (!cdof) { 6911b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6912ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6913b6ebb6e6SMatthew G. Knepley } else { 6914ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6915b6ebb6e6SMatthew G. Knepley } 6916b6ebb6e6SMatthew G. Knepley } else { 69179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6918b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6919b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69209371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69219371c9d4SSatish Balay ++cind; 69229371c9d4SSatish Balay continue; 69239371c9d4SSatish Balay } 6924b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6925b6ebb6e6SMatthew G. Knepley } 6926b6ebb6e6SMatthew G. Knepley } else { 6927b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69289371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69299371c9d4SSatish Balay ++cind; 69309371c9d4SSatish Balay continue; 69319371c9d4SSatish Balay } 6932b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6933b6ebb6e6SMatthew G. Knepley } 6934b6ebb6e6SMatthew G. Knepley } 6935b6ebb6e6SMatthew G. Knepley } 6936b6ebb6e6SMatthew G. Knepley } 6937b6ebb6e6SMatthew G. Knepley } 69389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 69393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6940b6ebb6e6SMatthew G. Knepley } 69411b406b76SMatthew G. Knepley 69421b406b76SMatthew G. Knepley /*@C 694320f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 69441b406b76SMatthew G. Knepley 69451b406b76SMatthew G. Knepley Not collective 69461b406b76SMatthew G. Knepley 69471b406b76SMatthew G. Knepley Input Parameters: 6948a1cb98faSBarry Smith + dm - The `DM` 694920f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 69501b406b76SMatthew G. Knepley . v - The local vector 695120f4b53cSBarry Smith . point - The point in the `DM` 69521b406b76SMatthew G. Knepley . values - The array of values 6953a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6954a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 69551b406b76SMatthew G. Knepley 69561b406b76SMatthew G. Knepley Level: intermediate 69571b406b76SMatthew G. Knepley 69581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 69591b406b76SMatthew G. Knepley @*/ 6960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6961d71ae5a4SJacob Faibussowitsch { 69621b406b76SMatthew G. Knepley PetscSection clSection; 69631b406b76SMatthew G. Knepley IS clPoints; 69641b406b76SMatthew G. Knepley PetscScalar *array; 69651b406b76SMatthew G. Knepley PetscInt *points = NULL; 696627f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6967c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 69681b406b76SMatthew G. Knepley 69691a271a75SMatthew G. Knepley PetscFunctionBeginHot; 69701b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 69719566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 69721a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 69731a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 69749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 69759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 69761b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 69779566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 69783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69791b406b76SMatthew G. Knepley } 69801a271a75SMatthew G. Knepley /* Get points */ 698107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6982c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6983c459fbc1SJed Brown PetscInt dof; 69849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6985c459fbc1SJed Brown clsize += dof; 6986c459fbc1SJed Brown } 69879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 69881a271a75SMatthew G. Knepley /* Get array */ 69899566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 69901a271a75SMatthew G. Knepley /* Get values */ 6991ef90cfe2SMatthew G. Knepley if (numFields > 0) { 699297e99dd9SToby Isaac PetscInt offset = 0, f; 6993552f7358SJed Brown for (f = 0; f < numFields; ++f) { 699497e99dd9SToby Isaac const PetscInt **perms = NULL; 699597e99dd9SToby Isaac const PetscScalar **flips = NULL; 699697e99dd9SToby Isaac 69979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6998552f7358SJed Brown switch (mode) { 6999552f7358SJed Brown case INSERT_VALUES: 700097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 700197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 700297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 700397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70043ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 70059371c9d4SSatish Balay } 70069371c9d4SSatish Balay break; 7007552f7358SJed Brown case INSERT_ALL_VALUES: 700897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 700997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 701097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 701197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70123ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 70139371c9d4SSatish Balay } 70149371c9d4SSatish Balay break; 7015a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 701697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 701797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 701897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 701997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70203ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 70219371c9d4SSatish Balay } 70229371c9d4SSatish Balay break; 7023552f7358SJed Brown case ADD_VALUES: 702497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 702597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 702697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 702797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70283ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 70299371c9d4SSatish Balay } 70309371c9d4SSatish Balay break; 7031552f7358SJed Brown case ADD_ALL_VALUES: 703297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 703397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 703497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 703597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70363ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 70379371c9d4SSatish Balay } 70389371c9d4SSatish Balay break; 7039304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 704097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 704197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 704297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 704397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70443ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 70459371c9d4SSatish Balay } 70469371c9d4SSatish Balay break; 7047d71ae5a4SJacob Faibussowitsch default: 7048d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7049552f7358SJed Brown } 70509566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 70511a271a75SMatthew G. Knepley } 7052552f7358SJed Brown } else { 70531a271a75SMatthew G. Knepley PetscInt dof, off; 705497e99dd9SToby Isaac const PetscInt **perms = NULL; 705597e99dd9SToby Isaac const PetscScalar **flips = NULL; 70561a271a75SMatthew G. Knepley 70579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 7058552f7358SJed Brown switch (mode) { 7059552f7358SJed Brown case INSERT_VALUES: 706097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 706197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 706297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 706397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70653ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70669371c9d4SSatish Balay } 70679371c9d4SSatish Balay break; 7068552f7358SJed Brown case INSERT_ALL_VALUES: 706997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 707097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 707197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 707297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70743ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 70759371c9d4SSatish Balay } 70769371c9d4SSatish Balay break; 7077a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 707897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 707997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 708097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 708197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70833ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 70849371c9d4SSatish Balay } 70859371c9d4SSatish Balay break; 7086552f7358SJed Brown case ADD_VALUES: 708797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 708897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 708997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 709097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70923ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70939371c9d4SSatish Balay } 70949371c9d4SSatish Balay break; 7095552f7358SJed Brown case ADD_ALL_VALUES: 709697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 709797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 709897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 709997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71013ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 71029371c9d4SSatish Balay } 71039371c9d4SSatish Balay break; 7104304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 710597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 710697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 710797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 710897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71103ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 71119371c9d4SSatish Balay } 71129371c9d4SSatish Balay break; 7113d71ae5a4SJacob Faibussowitsch default: 7114d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7115552f7358SJed Brown } 71169566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7117552f7358SJed Brown } 71181a271a75SMatthew G. Knepley /* Cleanup points */ 71199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 71201a271a75SMatthew G. Knepley /* Cleanup array */ 71219566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 71223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7123552f7358SJed Brown } 7124552f7358SJed Brown 71255f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7126d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7127d71ae5a4SJacob Faibussowitsch { 71285f790a90SMatthew G. Knepley PetscFunctionBegin; 712911cc89d2SBarry Smith *contains = PETSC_TRUE; 71305f790a90SMatthew G. Knepley if (label) { 7131d6177c40SToby Isaac PetscInt fdof; 71325f790a90SMatthew G. Knepley 713311cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 713411cc89d2SBarry Smith if (!*contains) { 71359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 71365f790a90SMatthew G. Knepley *offset += fdof; 71373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71385f790a90SMatthew G. Knepley } 71395f790a90SMatthew G. Knepley } 71403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71415f790a90SMatthew G. Knepley } 71425f790a90SMatthew G. Knepley 714397529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7144d71ae5a4SJacob Faibussowitsch 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) 7145d71ae5a4SJacob Faibussowitsch { 7146e07394fbSMatthew G. Knepley PetscSection clSection; 7147e07394fbSMatthew G. Knepley IS clPoints; 7148e07394fbSMatthew G. Knepley PetscScalar *array; 7149e07394fbSMatthew G. Knepley PetscInt *points = NULL; 715097529cf3SJed Brown const PetscInt *clp; 7151e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 715297e99dd9SToby Isaac PetscInt offset = 0, f; 7153e07394fbSMatthew G. Knepley 7154e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7155e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 71569566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7157e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7158e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 71599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7160e07394fbSMatthew G. Knepley /* Get points */ 716107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7162e07394fbSMatthew G. Knepley /* Get array */ 71639566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7164e07394fbSMatthew G. Knepley /* Get values */ 7165e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 716697e99dd9SToby Isaac const PetscInt **perms = NULL; 716797e99dd9SToby Isaac const PetscScalar **flips = NULL; 716811cc89d2SBarry Smith PetscBool contains; 716997e99dd9SToby Isaac 7170e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7171e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7172e07394fbSMatthew G. Knepley PetscInt fdof; 71739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7174e07394fbSMatthew G. Knepley offset += fdof; 7175e07394fbSMatthew G. Knepley } 7176e07394fbSMatthew G. Knepley continue; 7177e07394fbSMatthew G. Knepley } 71789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7179e07394fbSMatthew G. Knepley switch (mode) { 7180e07394fbSMatthew G. Knepley case INSERT_VALUES: 718197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 718297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 718397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 718497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 718511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 718611cc89d2SBarry Smith if (!contains) continue; 71879566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 71889371c9d4SSatish Balay } 71899371c9d4SSatish Balay break; 7190e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 719197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 719297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 719397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 719497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 719511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 719611cc89d2SBarry Smith if (!contains) continue; 71979566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 71989371c9d4SSatish Balay } 71999371c9d4SSatish Balay break; 7200e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 720197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 720297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 720397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 720497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 720511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 720611cc89d2SBarry Smith if (!contains) continue; 72079566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 72089371c9d4SSatish Balay } 72099371c9d4SSatish Balay break; 7210e07394fbSMatthew G. Knepley case ADD_VALUES: 721197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 721297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 721397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 721497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 721511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 721611cc89d2SBarry Smith if (!contains) continue; 72179566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 72189371c9d4SSatish Balay } 72199371c9d4SSatish Balay break; 7220e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 722197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 722297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 722397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 722497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 722511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 722611cc89d2SBarry Smith if (!contains) continue; 72279566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 72289371c9d4SSatish Balay } 72299371c9d4SSatish Balay break; 7230d71ae5a4SJacob Faibussowitsch default: 7231d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7232e07394fbSMatthew G. Knepley } 72339566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7234e07394fbSMatthew G. Knepley } 7235e07394fbSMatthew G. Knepley /* Cleanup points */ 72369566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7237e07394fbSMatthew G. Knepley /* Cleanup array */ 72389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 72393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7240e07394fbSMatthew G. Knepley } 7241e07394fbSMatthew G. Knepley 7242d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7243d71ae5a4SJacob Faibussowitsch { 7244552f7358SJed Brown PetscMPIInt rank; 7245552f7358SJed Brown PetscInt i, j; 7246552f7358SJed Brown 7247552f7358SJed Brown PetscFunctionBegin; 72489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 724963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 725063a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 725163a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7252b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 72533ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7254b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 72559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7256b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7257519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 72589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7259552f7358SJed Brown #else 72609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7261552f7358SJed Brown #endif 7262552f7358SJed Brown } 72639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7264552f7358SJed Brown } 72653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7266552f7358SJed Brown } 7267552f7358SJed Brown 726805586334SMatthew G. Knepley /* 726905586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 727005586334SMatthew G. Knepley 727105586334SMatthew G. Knepley Input Parameters: 727205586334SMatthew G. Knepley + section - The section for this data layout 727336fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 727405586334SMatthew G. Knepley . point - The point contributing dofs with these indices 727505586334SMatthew G. Knepley . off - The global offset of this point 727605586334SMatthew G. Knepley . loff - The local offset of each field 7277a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 727805586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 727905586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 728005586334SMatthew G. Knepley 728105586334SMatthew G. Knepley Output Parameter: 728205586334SMatthew G. Knepley . indices - Indices for dofs on this point 728305586334SMatthew G. Knepley 728405586334SMatthew G. Knepley Level: developer 728505586334SMatthew G. Knepley 728605586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 728705586334SMatthew G. Knepley */ 7288d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7289d71ae5a4SJacob Faibussowitsch { 7290e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7291552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7292552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7293552f7358SJed Brown PetscInt cind = 0, k; 7294552f7358SJed Brown 7295552f7358SJed Brown PetscFunctionBegin; 729608401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 72979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7299552f7358SJed Brown if (!cdof || setBC) { 730005586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 730105586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 730205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 730305586334SMatthew G. Knepley 730405586334SMatthew G. Knepley indices[ind] = off + k; 7305552f7358SJed Brown } 7306552f7358SJed Brown } else { 73079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 73084acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 730905586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 731005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 731105586334SMatthew G. Knepley 73124acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 73134acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 731405586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 73154acb8e1eSToby Isaac ++cind; 73164acb8e1eSToby Isaac } else { 731736fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7318552f7358SJed Brown } 7319552f7358SJed Brown } 7320552f7358SJed Brown } 7321e6ccafaeSMatthew G Knepley *loff += dof; 73223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7323552f7358SJed Brown } 7324552f7358SJed Brown 73257e29afd2SMatthew G. Knepley /* 732636fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 73277e29afd2SMatthew G. Knepley 732836fa2b79SJed Brown Input Parameters: 732936fa2b79SJed Brown + section - a section (global or local) 733020f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 733136fa2b79SJed Brown . point - point within section 733236fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 733336fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 733436fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 733536fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 733636fa2b79SJed Brown . permsoff - offset 733736fa2b79SJed Brown - indperm - index permutation 733836fa2b79SJed Brown 733936fa2b79SJed Brown Output Parameter: 734036fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 734136fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 734236fa2b79SJed Brown 734336fa2b79SJed Brown Notes: 734436fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 734536fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 734636fa2b79SJed Brown in the local vector. 734736fa2b79SJed Brown 734836fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 734936fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 735036fa2b79SJed Brown 735136fa2b79SJed Brown Developer Note: 735236fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 735336fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 735436fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 735536fa2b79SJed Brown 735636fa2b79SJed Brown Example: 735736fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 735836fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 735936fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 736036fa2b79SJed 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. 736136fa2b79SJed Brown 736236fa2b79SJed Brown Level: developer 73637e29afd2SMatthew G. Knepley */ 7364d71ae5a4SJacob Faibussowitsch 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[]) 7365d71ae5a4SJacob Faibussowitsch { 7366552f7358SJed Brown PetscInt numFields, foff, f; 7367552f7358SJed Brown 7368552f7358SJed Brown PetscFunctionBegin; 736908401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7371552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 73724acb8e1eSToby Isaac PetscInt fdof, cfdof; 7373552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 73744acb8e1eSToby Isaac PetscInt cind = 0, b; 73754acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7376552f7358SJed Brown 73779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 73789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7379552f7358SJed Brown if (!cfdof || setBC) { 738005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 738105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 738205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 738305586334SMatthew G. Knepley 738405586334SMatthew G. Knepley indices[ind] = off + foff + b; 738505586334SMatthew G. Knepley } 7386552f7358SJed Brown } else { 73879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 738805586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 738905586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 739005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 739105586334SMatthew G. Knepley 73924acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 739305586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7394552f7358SJed Brown ++cind; 7395552f7358SJed Brown } else { 739636fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7397552f7358SJed Brown } 7398552f7358SJed Brown } 7399552f7358SJed Brown } 740036fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7401552f7358SJed Brown foffs[f] += fdof; 7402552f7358SJed Brown } 74033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7404552f7358SJed Brown } 7405552f7358SJed Brown 74067e29afd2SMatthew G. Knepley /* 74077e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 74087e29afd2SMatthew G. Knepley 74097e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7410645102dcSJed Brown 7411645102dcSJed Brown Notes: 7412645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7413645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 74147e29afd2SMatthew G. Knepley */ 7415d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7416d71ae5a4SJacob Faibussowitsch { 74177e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 74187e29afd2SMatthew G. Knepley 74197e29afd2SMatthew G. Knepley PetscFunctionBegin; 74209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 74217e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 74227e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 74237e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 74247e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 74257e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 74267e29afd2SMatthew G. Knepley 74279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 74289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 74299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7430645102dcSJed Brown if (!cfdof) { 743105586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 743205586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 743305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 743405586334SMatthew G. Knepley 743505586334SMatthew G. Knepley indices[ind] = foff + b; 743605586334SMatthew G. Knepley } 74377e29afd2SMatthew G. Knepley } else { 74389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 743905586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 744005586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 744105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 744205586334SMatthew G. Knepley 74437e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 744405586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 74457e29afd2SMatthew G. Knepley ++cind; 74467e29afd2SMatthew G. Knepley } else { 744705586334SMatthew G. Knepley indices[ind] = foff + b - cind; 74487e29afd2SMatthew G. Knepley } 74497e29afd2SMatthew G. Knepley } 74507e29afd2SMatthew G. Knepley } 74517e29afd2SMatthew G. Knepley foffs[f] += fdof; 74527e29afd2SMatthew G. Knepley } 74533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74547e29afd2SMatthew G. Knepley } 74557e29afd2SMatthew G. Knepley 7456*c789d87fSToby Isaac static PetscErrorCode DMPlexAnchorsGetSubMatIndices(PetscInt nPoints, const PetscInt pnts[], PetscSection section, PetscSection cSec, PetscInt tmpIndices[], PetscInt fieldOffsets[], PetscInt indices[], const PetscInt ***perms) 7457*c789d87fSToby Isaac { 7458*c789d87fSToby Isaac PetscInt numFields, sStart, sEnd, cStart, cEnd; 7459*c789d87fSToby Isaac 7460*c789d87fSToby Isaac PetscFunctionBegin; 7461*c789d87fSToby Isaac PetscCall(PetscSectionGetNumFields(section, &numFields)); 7462*c789d87fSToby Isaac PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7463*c789d87fSToby Isaac PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7464*c789d87fSToby Isaac for (PetscInt p = 0; p < nPoints; p++) { 7465*c789d87fSToby Isaac PetscInt b = pnts[2 * p]; 7466*c789d87fSToby Isaac PetscInt bSecDof = 0, bOff; 7467*c789d87fSToby Isaac PetscInt cSecDof = 0; 7468*c789d87fSToby Isaac PetscSection indices_section; 7469*c789d87fSToby Isaac 7470*c789d87fSToby Isaac if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7471*c789d87fSToby Isaac if (!bSecDof) continue; 7472*c789d87fSToby Isaac if (b >= cStart && b < cEnd) PetscCall(PetscSectionGetDof(cSec, b, &cSecDof)); 7473*c789d87fSToby Isaac indices_section = cSecDof > 0 ? cSec : section; 7474*c789d87fSToby Isaac if (numFields) { 7475*c789d87fSToby Isaac PetscInt fStart[32], fEnd[32]; 7476*c789d87fSToby Isaac 7477*c789d87fSToby Isaac fStart[0] = 0; 7478*c789d87fSToby Isaac fEnd[0] = 0; 7479*c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7480*c789d87fSToby Isaac PetscInt fDof = 0; 7481*c789d87fSToby Isaac 7482*c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(indices_section, b, f, &fDof)); 7483*c789d87fSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7484*c789d87fSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7485*c789d87fSToby Isaac } 7486*c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7487*c789d87fSToby Isaac // only apply permutations on one side 7488*c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPointFields_Internal(indices_section, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, perms ? p : -1, NULL, tmpIndices)); 7489*c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7490*c789d87fSToby Isaac for (PetscInt i = fStart[f]; i < fEnd[f]; i++) { indices[fieldOffsets[f]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); } 7491*c789d87fSToby Isaac } 7492*c789d87fSToby Isaac } else { 7493*c789d87fSToby Isaac PetscInt bEnd = 0; 7494*c789d87fSToby Isaac 7495*c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7496*c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPoint_Internal(indices_section, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, tmpIndices)); 7497*c789d87fSToby Isaac 7498*c789d87fSToby Isaac for (PetscInt i = 0; i < bEnd; i++) indices[fieldOffsets[0]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); 7499*c789d87fSToby Isaac } 7500*c789d87fSToby Isaac } 7501*c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7502*c789d87fSToby Isaac } 7503*c789d87fSToby Isaac 7504*c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsGetSubMatModification(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscInt offsets[], PetscScalar *outMat[]) 7505d71ae5a4SJacob Faibussowitsch { 7506d3d1a6afSToby Isaac Mat cMat; 7507d3d1a6afSToby Isaac PetscSection aSec, cSec; 7508d3d1a6afSToby Isaac IS aIS; 7509d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7510a19ea1e9SMatthew G. Knepley PetscInt sStart = -1, sEnd = -1; 7511a19ea1e9SMatthew G. Knepley PetscInt cStart = -1, cEnd = -1; 7512d3d1a6afSToby Isaac const PetscInt *anchors; 7513*c789d87fSToby Isaac PetscInt numFields, f, p; 7514d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7515*c789d87fSToby Isaac PetscInt *newPoints, *indices, *newIndices, *tmpIndices, *tmpNewIndices; 7516*c789d87fSToby Isaac PetscInt oldOffsets[32]; 7517d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7518*c789d87fSToby Isaac PetscInt oldOffsetsCopy[32]; 7519*c789d87fSToby Isaac PetscInt newOffsetsCopy[32]; 7520*c789d87fSToby Isaac PetscScalar *modMat = NULL; 7521d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7522d3d1a6afSToby Isaac 7523d3d1a6afSToby Isaac PetscFunctionBegin; 7524d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7525d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 75269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7527d3d1a6afSToby Isaac 75289566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7529d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7530d3d1a6afSToby Isaac if (aSec) { 75319566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 7532*c789d87fSToby Isaac PetscCall(PetscArrayzero(oldOffsets, 32)); 75339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 75349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7535a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7536d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7537d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7538d3d1a6afSToby Isaac * into the global matrix anyway) */ 7539d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7540d3d1a6afSToby Isaac PetscInt b = points[p]; 7541a19ea1e9SMatthew G. Knepley PetscInt bDof = 0, bSecDof = 0; 7542d3d1a6afSToby Isaac 7543a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7544ad540459SPierre Jolivet if (!bSecDof) continue; 7545*c789d87fSToby Isaac 7546*c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7547*c789d87fSToby Isaac PetscInt fDof = 0; 7548*c789d87fSToby Isaac 7549*c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7550*c789d87fSToby Isaac oldOffsets[f + 1] += fDof; 7551*c789d87fSToby Isaac } 755248a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7553d3d1a6afSToby Isaac if (bDof) { 7554d3d1a6afSToby Isaac /* this point is constrained */ 7555d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7556d3d1a6afSToby Isaac PetscInt bOff, q; 7557d3d1a6afSToby Isaac 75589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7559d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7560d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7561a19ea1e9SMatthew G. Knepley PetscInt aDof = 0; 7562d3d1a6afSToby Isaac 7563a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7564*c789d87fSToby Isaac if (aDof) { 7565*c789d87fSToby Isaac anyConstrained = PETSC_TRUE; 7566*c789d87fSToby Isaac newNumPoints += 1; 7567*c789d87fSToby Isaac } 7568d3d1a6afSToby Isaac newNumIndices += aDof; 7569d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7570a19ea1e9SMatthew G. Knepley PetscInt fDof = 0; 7571d3d1a6afSToby Isaac 7572a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7573d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7574d3d1a6afSToby Isaac } 7575d3d1a6afSToby Isaac } 75769371c9d4SSatish Balay } else { 7577d3d1a6afSToby Isaac /* this point is not constrained */ 7578d3d1a6afSToby Isaac newNumPoints++; 75794b2f2278SToby Isaac newNumIndices += bSecDof; 7580d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7581d3d1a6afSToby Isaac PetscInt fDof; 7582d3d1a6afSToby Isaac 75839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7584d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7585d3d1a6afSToby Isaac } 7586d3d1a6afSToby Isaac } 7587d3d1a6afSToby Isaac } 7588d3d1a6afSToby Isaac } 7589d3d1a6afSToby Isaac if (!anyConstrained) { 759072b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 759172b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 759272b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 7593*c789d87fSToby Isaac if (outMat) *outMat = NULL; 75949566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 75953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7596d3d1a6afSToby Isaac } 7597d3d1a6afSToby Isaac 75986ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 75996ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 76006ecaa68aSToby Isaac 7601f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7602*c789d87fSToby Isaac for (f = 0; f < numFields; ++f) oldOffsets[f + 1] += oldOffsets[f]; 7603d3d1a6afSToby Isaac 7604*c789d87fSToby Isaac if (!outPoints && !outMat) { 76056ecaa68aSToby Isaac if (offsets) { 7606ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 76076ecaa68aSToby Isaac } 76089566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 76093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 76106ecaa68aSToby Isaac } 76116ecaa68aSToby Isaac 76121dca8a05SBarry Smith PetscCheck(!numFields || newOffsets[numFields] == newNumIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, newOffsets[numFields], newNumIndices); 7613*c789d87fSToby Isaac PetscCheck(!numFields || oldOffsets[numFields] == numIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, oldOffsets[numFields], numIndices); 7614d3d1a6afSToby Isaac 76159566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7616a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7617d3d1a6afSToby Isaac 7618*c789d87fSToby Isaac /* output arrays */ 7619*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 7620*c789d87fSToby Isaac PetscCall(PetscArrayzero(newPoints, 2 * newNumPoints)); 7621d3d1a6afSToby Isaac 7622*c789d87fSToby Isaac // get the new Points 7623*c789d87fSToby Isaac for (PetscInt p = 0, newP = 0; p < numPoints; p++) { 7624d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7625*c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 7626d3d1a6afSToby Isaac 7627a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7628*c789d87fSToby Isaac if (!bSecDof) continue; 762948a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7630d3d1a6afSToby Isaac if (bDof) { 76319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7632*c789d87fSToby Isaac for (PetscInt q = 0; q < bDof; q++) { 7633a19ea1e9SMatthew G. Knepley PetscInt a = anchors[bOff + q], aDof = 0; 7634d3d1a6afSToby Isaac 7635a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7636*c789d87fSToby Isaac if (aDof) { 7637*c789d87fSToby Isaac newPoints[2 * newP] = a; 7638*c789d87fSToby Isaac newPoints[2 * newP + 1] = 0; // orientations are accounted for in constructing the matrix, newly added points are in default orientation 7639d3d1a6afSToby Isaac newP++; 7640d3d1a6afSToby Isaac } 7641d3d1a6afSToby Isaac } 7642d3d1a6afSToby Isaac } else { 7643d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7644*c789d87fSToby Isaac newPoints[2 * newP + 1] = points[2 * p + 1]; 7645d3d1a6afSToby Isaac newP++; 7646d3d1a6afSToby Isaac } 7647d3d1a6afSToby Isaac } 7648d3d1a6afSToby Isaac 7649*c789d87fSToby Isaac if (outMat) { 7650*c789d87fSToby Isaac PetscScalar *tmpMat; 7651*c789d87fSToby Isaac PetscCall(PetscArraycpy(oldOffsetsCopy, oldOffsets, 32)); 7652*c789d87fSToby Isaac PetscCall(PetscArraycpy(newOffsetsCopy, newOffsets, 32)); 7653*c789d87fSToby Isaac 7654*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &indices)); 7655*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 7656*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 7657*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 7658*c789d87fSToby Isaac 7659*c789d87fSToby Isaac for (PetscInt i = 0; i < numIndices; i++) indices[i] = -1; 7660*c789d87fSToby Isaac for (PetscInt i = 0; i < newNumIndices; i++) newIndices[i] = -1; 7661*c789d87fSToby Isaac 7662*c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(numPoints, points, section, cSec, tmpIndices, oldOffsetsCopy, indices, perms)); 7663*c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(newNumPoints, newPoints, section, section, tmpNewIndices, newOffsetsCopy, newIndices, NULL)); 7664*c789d87fSToby Isaac 7665*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 7666*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 7667*c789d87fSToby Isaac PetscCall(PetscArrayzero(modMat, newNumIndices * numIndices)); 7668*c789d87fSToby Isaac // for each field, insert the anchor modification into modMat 7669*c789d87fSToby Isaac for (PetscInt f = 0; f < PetscMax(1, numFields); f++) { 7670*c789d87fSToby Isaac PetscInt fStart = oldOffsets[f]; 7671*c789d87fSToby Isaac PetscInt fNewStart = newOffsets[f]; 7672*c789d87fSToby Isaac for (PetscInt p = 0, newP = 0, o = fStart, oNew = fNewStart; p < numPoints; p++) { 7673*c789d87fSToby Isaac PetscInt b = points[2 * p]; 7674*c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 7675*c789d87fSToby Isaac 7676*c789d87fSToby Isaac if (b >= sStart && b < sEnd) { 7677d3d1a6afSToby Isaac if (numFields) { 7678*c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &bSecDof)); 76799371c9d4SSatish Balay } else { 7680*c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7681d3d1a6afSToby Isaac } 7682d3d1a6afSToby Isaac } 7683*c789d87fSToby Isaac if (!bSecDof) continue; 7684*c789d87fSToby Isaac if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7685*c789d87fSToby Isaac if (bDof) { 7686*c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7687*c789d87fSToby Isaac for (PetscInt q = 0; q < bDof; q++, newP++) { 7688*c789d87fSToby Isaac PetscInt a = anchors[bOff + q], aDof = 0; 7689d3d1a6afSToby Isaac 7690*c789d87fSToby Isaac if (a >= sStart && a < sEnd) { 7691d3d1a6afSToby Isaac if (numFields) { 7692*c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 7693*c789d87fSToby Isaac } else { 7694*c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, a, &aDof)); 7695d3d1a6afSToby Isaac } 7696d3d1a6afSToby Isaac } 7697*c789d87fSToby Isaac if (aDof) { 7698*c789d87fSToby Isaac PetscCall(MatGetValues(cMat, bSecDof, &indices[o], aDof, &newIndices[oNew], tmpMat)); 7699*c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) { 7700*c789d87fSToby Isaac for (PetscInt e = 0; e < aDof; e++) modMat[(o + d) * newNumIndices + oNew + e] = tmpMat[d * aDof + e]; 7701*c789d87fSToby Isaac } 7702*c789d87fSToby Isaac } 7703*c789d87fSToby Isaac oNew += aDof; 7704*c789d87fSToby Isaac } 77059371c9d4SSatish Balay } else { 7706*c789d87fSToby Isaac // Insert the identity matrix in this block 7707*c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) modMat[(o + d) * newNumIndices + oNew + d] = 1; 7708*c789d87fSToby Isaac oNew += bSecDof; 7709*c789d87fSToby Isaac newP++; 7710d3d1a6afSToby Isaac } 7711*c789d87fSToby Isaac o += bSecDof; 7712d3d1a6afSToby Isaac } 7713d3d1a6afSToby Isaac } 7714d3d1a6afSToby Isaac 7715*c789d87fSToby Isaac *outMat = modMat; 77166ecaa68aSToby Isaac 7717*c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 7718*c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 7719*c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 7720*c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 7721*c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices)); 7722d3d1a6afSToby Isaac } 77239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7724d3d1a6afSToby Isaac 7725d3d1a6afSToby Isaac /* output */ 77266ecaa68aSToby Isaac if (outPoints) { 7727d3d1a6afSToby Isaac *outPoints = newPoints; 77289371c9d4SSatish Balay } else { 77299566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 77306ecaa68aSToby Isaac } 7731ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 77323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7733d3d1a6afSToby Isaac } 7734d3d1a6afSToby Isaac 7735*c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsModifyMat_Internal(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, PetscInt numRows, PetscInt numCols, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyRight, PetscBool multiplyLeft) 7736*c789d87fSToby Isaac { 7737*c789d87fSToby Isaac PetscScalar *modMat = NULL; 7738*c789d87fSToby Isaac PetscInt newNumIndices = -1; 77397cd05799SMatthew G. Knepley 7740*c789d87fSToby Isaac PetscFunctionBegin; 7741*c789d87fSToby Isaac /* If M is the matrix represented by values, get the matrix C such that we will add M * C (or, if multiplyLeft, C^T * M * C) into the global matrix. 7742*c789d87fSToby Isaac modMat is that matrix C */ 7743*c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatModification(dm, section, numPoints, numIndices, points, perms, outNumPoints, &newNumIndices, outPoints, offsets, outValues ? &modMat : NULL)); 7744*c789d87fSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 7745*c789d87fSToby Isaac if (modMat) { 7746*c789d87fSToby Isaac const PetscScalar *newValues = values; 77477cd05799SMatthew G. Knepley 7748*c789d87fSToby Isaac if (multiplyRight) { 7749*c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 7750*c789d87fSToby Isaac PetscBLASInt M = newNumIndices; 7751*c789d87fSToby Isaac PetscBLASInt N = numRows; 7752*c789d87fSToby Isaac PetscBLASInt K = numIndices; 7753*c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 77547cd05799SMatthew G. Knepley 7755*c789d87fSToby Isaac PetscCheck(numCols == numIndices, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "values matrix has the wrong number of columns: %" PetscInt_FMT ", expected %" PetscInt_FMT, numCols, numIndices); 77567cd05799SMatthew G. Knepley 7757*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numRows * newNumIndices, MPIU_SCALAR, &newNewValues)); 7758*c789d87fSToby Isaac // row-major to column-major conversion, right multiplication becomes left multiplication 7759*c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &M, &N, &K, &a, modMat, &M, newValues, &K, &b, newNewValues, &M)); 776036fa2b79SJed Brown 7761*c789d87fSToby Isaac numCols = newNumIndices; 7762*c789d87fSToby Isaac newValues = newNewValues; 7763*c789d87fSToby Isaac } 7764a1cb98faSBarry Smith 7765*c789d87fSToby Isaac if (multiplyLeft) { 7766*c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 7767*c789d87fSToby Isaac PetscBLASInt M = numCols; 7768*c789d87fSToby Isaac PetscBLASInt N = newNumIndices; 7769*c789d87fSToby Isaac PetscBLASInt K = numIndices; 7770*c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 77717cd05799SMatthew G. Knepley 7772*c789d87fSToby Isaac PetscCheck(numRows == numIndices, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "values matrix has the wrong number of rows: %" PetscInt_FMT ", expected %" PetscInt_FMT, numRows, numIndices); 7773*c789d87fSToby Isaac 7774*c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices * numCols, MPIU_SCALAR, &newNewValues)); 7775*c789d87fSToby Isaac // row-major to column-major conversion, left multiplication becomes right multiplication 7776*c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &M, &N, &K, &a, newValues, &M, modMat, &N, &b, newNewValues, &M)); 7777*c789d87fSToby Isaac if (newValues != values) PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &newValues)); 7778*c789d87fSToby Isaac newValues = newNewValues; 7779*c789d87fSToby Isaac } 7780*c789d87fSToby Isaac *outValues = (PetscScalar *)newValues; 7781*c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 7782*c789d87fSToby Isaac } 7783*c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7784*c789d87fSToby Isaac } 7785*c789d87fSToby Isaac 7786*c789d87fSToby Isaac PETSC_INTERN 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) 7787*c789d87fSToby Isaac { 7788*c789d87fSToby Isaac PetscFunctionBegin; 7789*c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, numPoints, numIndices, points, perms, numIndices, numIndices, values, outNumPoints, outNumIndices, outPoints, outValues, offsets, PETSC_TRUE, multiplyLeft)); 7790*c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7791*c789d87fSToby Isaac } 7792*c789d87fSToby Isaac 7793*c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndicesSize_Internal(DM dm, PetscSection section, PetscInt point, PetscInt *closureSize) 7794*c789d87fSToby Isaac { 7795*c789d87fSToby Isaac /* Closure ordering */ 7796*c789d87fSToby Isaac PetscSection clSection; 7797*c789d87fSToby Isaac IS clPoints; 7798*c789d87fSToby Isaac const PetscInt *clp; 7799*c789d87fSToby Isaac PetscInt *points; 7800*c789d87fSToby Isaac PetscInt Ncl, Ni = 0; 7801*c789d87fSToby Isaac 7802*c789d87fSToby Isaac PetscFunctionBeginHot; 7803*c789d87fSToby Isaac PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7804*c789d87fSToby Isaac for (PetscInt p = 0; p < Ncl * 2; p += 2) { 7805*c789d87fSToby Isaac PetscInt dof; 7806*c789d87fSToby Isaac 7807*c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, points[p], &dof)); 7808*c789d87fSToby Isaac Ni += dof; 7809*c789d87fSToby Isaac } 7810*c789d87fSToby Isaac PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7811*c789d87fSToby Isaac *closureSize = Ni; 7812*c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7813*c789d87fSToby Isaac } 7814*c789d87fSToby Isaac 7815*c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndices_Internal(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numRows, PetscInt *numCols, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[], PetscBool multiplyRight, PetscBool multiplyLeft) 7816d71ae5a4SJacob Faibussowitsch { 781771f0bbf9SMatthew G. Knepley /* Closure ordering */ 78187773e69fSMatthew G. Knepley PetscSection clSection; 78197773e69fSMatthew G. Knepley IS clPoints; 782071f0bbf9SMatthew G. Knepley const PetscInt *clp; 782171f0bbf9SMatthew G. Knepley PetscInt *points; 782271f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 782371f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 78244acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 782571f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 782671f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 782771f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 782871f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 782971f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 783071f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 783171f0bbf9SMatthew G. Knepley 783271f0bbf9SMatthew G. Knepley PetscInt *idx; 783371f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 783471f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 78357caea556SToby Isaac PetscInt idxStart, idxEnd; 7836*c789d87fSToby Isaac PetscInt nRows, nCols; 78377773e69fSMatthew G. Knepley 783871f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 78397773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 78407773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 784136fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7842*c789d87fSToby Isaac PetscAssertPointer(numRows, 6); 7843*c789d87fSToby Isaac PetscAssertPointer(numCols, 7); 7844*c789d87fSToby Isaac if (indices) PetscAssertPointer(indices, 8); 7845*c789d87fSToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 9); 7846*c789d87fSToby Isaac if (values) PetscAssertPointer(values, 10); 78479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 784863a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 78499566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 785071f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 785107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7852c459fbc1SJed Brown if (useClPerm) { 7853c459fbc1SJed Brown PetscInt depth, clsize; 78549566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7855c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7856c459fbc1SJed Brown PetscInt dof; 78579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7858c459fbc1SJed Brown clsize += dof; 7859c459fbc1SJed Brown } 78609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7861c459fbc1SJed Brown } 786271f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 786371f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 78647773e69fSMatthew G. Knepley PetscInt dof, fdof; 78657773e69fSMatthew G. Knepley 78669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 78677773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 78689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 78697773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 78707773e69fSMatthew G. Knepley } 787171f0bbf9SMatthew G. Knepley Ni += dof; 78727773e69fSMatthew G. Knepley } 7873*c789d87fSToby Isaac if (*numRows == -1) *numRows = Ni; 7874*c789d87fSToby Isaac if (*numCols == -1) *numCols = Ni; 7875*c789d87fSToby Isaac nRows = *numRows; 7876*c789d87fSToby Isaac nCols = *numCols; 78777773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 78781dca8a05SBarry Smith PetscCheck(!Nf || offsets[Nf] == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[Nf], Ni); 787971f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7880*c789d87fSToby Isaac if (multiplyRight) PetscCheck(nCols == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " columns, got %" PetscInt_FMT, Ni, nCols); 7881*c789d87fSToby Isaac if (multiplyLeft) PetscCheck(nRows == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " rows, got %" PetscInt_FMT, Ni, nRows); 788271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 78839566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 78849566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 788571f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 788671f0bbf9SMatthew G. Knepley if (values && flips[f]) { 788771f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 78886ecaa68aSToby Isaac 788971f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 789071f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 789171f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 789271f0bbf9SMatthew G. Knepley 78939566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 78949566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 789571f0bbf9SMatthew G. Knepley if (flip) { 789671f0bbf9SMatthew G. Knepley PetscInt i, j, k; 789771f0bbf9SMatthew G. Knepley 789871f0bbf9SMatthew G. Knepley if (!valCopy) { 78999566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 790071f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 790171f0bbf9SMatthew G. Knepley *values = valCopy; 790271f0bbf9SMatthew G. Knepley } 790371f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 790471f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 790571f0bbf9SMatthew G. Knepley 7906*c789d87fSToby Isaac if (multiplyRight) { 7907*c789d87fSToby Isaac for (k = 0; k < nRows; ++k) { valCopy[Ni * k + (foffset + i)] *= fval; } 7908*c789d87fSToby Isaac } 7909*c789d87fSToby Isaac if (multiplyLeft) { 7910*c789d87fSToby Isaac for (k = 0; k < nCols; ++k) { valCopy[nCols * (foffset + i) + k] *= fval; } 79116ecaa68aSToby Isaac } 79126ecaa68aSToby Isaac } 791371f0bbf9SMatthew G. Knepley } 791471f0bbf9SMatthew G. Knepley foffset += fdof; 791571f0bbf9SMatthew G. Knepley } 791671f0bbf9SMatthew G. Knepley } 791771f0bbf9SMatthew G. Knepley } 791871f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7919*c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, Ncl, Ni, points, perms, nRows, nCols, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, multiplyRight, multiplyLeft)); 792071f0bbf9SMatthew G. Knepley if (NclC) { 7921*c789d87fSToby Isaac if (multiplyRight) { *numCols = nCols = NiC; } 7922*c789d87fSToby Isaac if (multiplyLeft) { *numRows = nRows = NiC; } 79239566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 792471f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79259566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 79269566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 792771f0bbf9SMatthew G. Knepley } 792871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79299566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 79309566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 793171f0bbf9SMatthew G. Knepley } 79329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 793371f0bbf9SMatthew G. Knepley Ncl = NclC; 793471f0bbf9SMatthew G. Knepley Ni = NiC; 793571f0bbf9SMatthew G. Knepley points = pointsC; 793671f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 793771f0bbf9SMatthew G. Knepley } 793871f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 79399566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 79407caea556SToby Isaac PetscCall(PetscSectionGetChart(idxSection, &idxStart, &idxEnd)); 794171f0bbf9SMatthew G. Knepley if (Nf) { 794271f0bbf9SMatthew G. Knepley PetscInt idxOff; 794371f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 794471f0bbf9SMatthew G. Knepley 79459371c9d4SSatish Balay if (outOffsets) { 79469371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 79479371c9d4SSatish Balay } 79489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 794971f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 795071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 795171f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 795271f0bbf9SMatthew G. Knepley 79539566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 79547773e69fSMatthew G. Knepley } 79557773e69fSMatthew G. Knepley } else { 795671f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 795771f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 795871f0bbf9SMatthew G. Knepley 79597caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 79609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 796171f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 796271f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 796371f0bbf9SMatthew G. Knepley * global section. */ 79649566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 796571f0bbf9SMatthew G. Knepley } 796671f0bbf9SMatthew G. Knepley } 796771f0bbf9SMatthew G. Knepley } else { 796871f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 796971f0bbf9SMatthew G. Knepley 797071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 797171f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 79724acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 79734acb8e1eSToby Isaac 79747caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 79759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 797671f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 797771f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 79789566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 79797773e69fSMatthew G. Knepley } 79807773e69fSMatthew G. Knepley } 798171f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 798271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79839566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 79849566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 79854acb8e1eSToby Isaac } 798671f0bbf9SMatthew G. Knepley if (NclC) { 79879566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 79887773e69fSMatthew G. Knepley } else { 79899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 79907773e69fSMatthew G. Knepley } 799171f0bbf9SMatthew G. Knepley 799271f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 79933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79947773e69fSMatthew G. Knepley } 79957773e69fSMatthew G. Knepley 79967cd05799SMatthew G. Knepley /*@C 7997*c789d87fSToby Isaac DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7998*c789d87fSToby Isaac 7999*c789d87fSToby Isaac Not collective 8000*c789d87fSToby Isaac 8001*c789d87fSToby Isaac Input Parameters: 8002*c789d87fSToby Isaac + dm - The `DM` 8003*c789d87fSToby Isaac . section - The `PetscSection` describing the points (a local section) 8004*c789d87fSToby Isaac . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 8005*c789d87fSToby Isaac . point - The point defining the closure 8006*c789d87fSToby Isaac - useClPerm - Use the closure point permutation if available 8007*c789d87fSToby Isaac 8008*c789d87fSToby Isaac Output Parameters: 8009*c789d87fSToby Isaac + numIndices - The number of dof indices in the closure of point with the input sections 8010*c789d87fSToby Isaac . indices - The dof indices 8011*c789d87fSToby Isaac . outOffsets - Array to write the field offsets into, or `NULL` 8012*c789d87fSToby Isaac - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 8013*c789d87fSToby Isaac 8014*c789d87fSToby Isaac Level: advanced 8015*c789d87fSToby Isaac 8016*c789d87fSToby Isaac Notes: 8017*c789d87fSToby Isaac Must call `DMPlexRestoreClosureIndices()` to free allocated memory 8018*c789d87fSToby Isaac 8019*c789d87fSToby Isaac If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 8020*c789d87fSToby Isaac of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 8021*c789d87fSToby Isaac of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 8022*c789d87fSToby Isaac indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 8023*c789d87fSToby Isaac indices (with the above semantics) are implied. 8024*c789d87fSToby Isaac 8025*c789d87fSToby Isaac .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 8026*c789d87fSToby Isaac `PetscSection`, `DMGetGlobalSection()` 8027*c789d87fSToby Isaac @*/ 8028*c789d87fSToby Isaac PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8029*c789d87fSToby Isaac { 8030*c789d87fSToby Isaac PetscInt numRows = -1, numCols = -1; 8031*c789d87fSToby Isaac 8032*c789d87fSToby Isaac PetscFunctionBeginHot; 8033*c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dm, section, idxSection, point, useClPerm, &numRows, &numCols, indices, outOffsets, values, PETSC_TRUE, PETSC_TRUE)); 8034*c789d87fSToby Isaac PetscCheck(numRows == numCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Symmetric matrix transformation produces rectangular dimensions (%" PetscInt_FMT ", %" PetscInt_FMT ")", numRows, numCols); 8035*c789d87fSToby Isaac *numIndices = numRows; 8036*c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 8037*c789d87fSToby Isaac } 8038*c789d87fSToby Isaac 8039*c789d87fSToby Isaac /*@C 804071f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 80417cd05799SMatthew G. Knepley 80427cd05799SMatthew G. Knepley Not collective 80437cd05799SMatthew G. Knepley 80447cd05799SMatthew G. Knepley Input Parameters: 8045a1cb98faSBarry Smith + dm - The `DM` 8046a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8047a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 804871f0bbf9SMatthew G. Knepley . point - The point defining the closure 804971f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 805071f0bbf9SMatthew G. Knepley 805171f0bbf9SMatthew G. Knepley Output Parameters: 805271f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 805371f0bbf9SMatthew G. Knepley . indices - The dof indices 805420f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 805520f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 805671f0bbf9SMatthew G. Knepley 8057a1cb98faSBarry Smith Level: advanced 805871f0bbf9SMatthew G. Knepley 8059a1cb98faSBarry Smith Notes: 8060a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8061a1cb98faSBarry Smith 8062a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 806371f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 806471f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 806571f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 806671f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 80677cd05799SMatthew G. Knepley 80681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 80697cd05799SMatthew G. Knepley @*/ 8070d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8071d71ae5a4SJacob Faibussowitsch { 80727773e69fSMatthew G. Knepley PetscFunctionBegin; 80737773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80744f572ea9SToby Isaac PetscAssertPointer(indices, 7); 80759566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 80763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80777773e69fSMatthew G. Knepley } 80787773e69fSMatthew G. Knepley 8079e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8080d71ae5a4SJacob Faibussowitsch { 8081552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8082552f7358SJed Brown PetscInt *indices; 808371f0bbf9SMatthew G. Knepley PetscInt numIndices; 808471f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8085552f7358SJed Brown PetscErrorCode ierr; 8086552f7358SJed Brown 8087552f7358SJed Brown PetscFunctionBegin; 8088552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80899566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 80903dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 80919566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 80923dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8093e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8094552f7358SJed Brown 8095e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 80960d644c17SKarl Rupp 80979566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8098d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 80994a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8100552f7358SJed Brown if (ierr) { 8101552f7358SJed Brown PetscMPIInt rank; 8102552f7358SJed Brown 81039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 81049566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 81059566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 81069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81079566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8108c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8109552f7358SJed Brown } 81104a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 81114a1e0b3eSMatthew G. Knepley PetscInt i; 81129566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 811363a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 81149566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 81154a1e0b3eSMatthew G. Knepley } 811671f0bbf9SMatthew G. Knepley 81179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81189566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 81193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81204acb8e1eSToby Isaac } 812171f0bbf9SMatthew G. Knepley 81224a1e0b3eSMatthew G. Knepley /*@C 8123e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8124e8e188d2SZach Atkins 8125e8e188d2SZach Atkins Not collective 8126e8e188d2SZach Atkins 8127e8e188d2SZach Atkins Input Parameters: 8128e8e188d2SZach Atkins + dm - The `DM` 8129e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8130e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8131e8e188d2SZach Atkins . A - The matrix 8132e8e188d2SZach Atkins . point - The point in the `DM` 8133e8e188d2SZach Atkins . values - The array of values 8134e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8135e8e188d2SZach Atkins 8136e8e188d2SZach Atkins Level: intermediate 8137e8e188d2SZach Atkins 8138e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8139e8e188d2SZach Atkins @*/ 8140e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8141e8e188d2SZach Atkins { 8142e8e188d2SZach Atkins PetscFunctionBegin; 8143e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8144e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8145e8e188d2SZach Atkins } 8146e8e188d2SZach Atkins 8147e8e188d2SZach Atkins /*@C 814860225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 81494a1e0b3eSMatthew G. Knepley 81504a1e0b3eSMatthew G. Knepley Not collective 81514a1e0b3eSMatthew G. Knepley 81524a1e0b3eSMatthew G. Knepley Input Parameters: 8153a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 815420f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8155e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 815620f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8157a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 815820f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8159e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 816020f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 81614a1e0b3eSMatthew G. Knepley . A - The matrix 8162a1cb98faSBarry Smith . point - The point in the `DM` 81634a1e0b3eSMatthew G. Knepley . values - The array of values 8164a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 81654a1e0b3eSMatthew G. Knepley 81664a1e0b3eSMatthew G. Knepley Level: intermediate 81674a1e0b3eSMatthew G. Knepley 81681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 81694a1e0b3eSMatthew G. Knepley @*/ 8170e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, PetscBool useRowPerm, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, PetscBool useColPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8171d71ae5a4SJacob Faibussowitsch { 817271f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 817371f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 8174*c789d87fSToby Isaac PetscInt numIndicesRow = -1, numIndicesCol = -1; 81757caea556SToby Isaac const PetscScalar *valuesV0 = values, *valuesV1, *valuesV2; 8176*c789d87fSToby Isaac 817771f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 817871f0bbf9SMatthew G. Knepley 817971f0bbf9SMatthew G. Knepley PetscFunctionBegin; 818071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 81819566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 818271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 81839566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 818471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8185e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 81869566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8187e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 81889566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8189e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8190e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 819171f0bbf9SMatthew G. Knepley 8192*c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmRow, sectionRow, point, &numIndicesRow)); 8193*c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmCol, sectionCol, point, &numIndicesCol)); 81947caea556SToby Isaac valuesV1 = valuesV0; 8195*c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV1, PETSC_FALSE, PETSC_TRUE)); 81967caea556SToby Isaac valuesV2 = valuesV1; 8197*c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesRow, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2, PETSC_TRUE, PETSC_FALSE)); 819871f0bbf9SMatthew G. Knepley 8199*c789d87fSToby Isaac if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2)); 8200d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8201*c789d87fSToby Isaac ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2, mode); 820271f0bbf9SMatthew G. Knepley if (ierr) { 820371f0bbf9SMatthew G. Knepley PetscMPIInt rank; 820471f0bbf9SMatthew G. Knepley 82059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 82069566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 82079566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 82087caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV2)); 82097caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 82107caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 82117caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 8212d3d1a6afSToby Isaac } 821371f0bbf9SMatthew G. Knepley 82147caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2)); 82157caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 82167caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 82177caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 82183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8219552f7358SJed Brown } 8220552f7358SJed Brown 8221d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8222d71ae5a4SJacob Faibussowitsch { 8223de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8224de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8225de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8226de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 822717c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8228de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8229412e9a14SMatthew G. Knepley DMPolytopeType ct; 82304ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8231de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8232de41b84cSMatthew G. Knepley 8233de41b84cSMatthew G. Knepley PetscFunctionBegin; 8234de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8235de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 82369566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8237de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 82389566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8239de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 82409566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8241de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 82429566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8243de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8244de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 82459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 824663a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 82479566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 82489566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8249de41b84cSMatthew G. Knepley /* Column indices */ 82509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 82514ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8252de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8253de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 82549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8255de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8256de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8257de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8258de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8259de41b84cSMatthew G. Knepley ++q; 8260de41b84cSMatthew G. Knepley } 8261de41b84cSMatthew G. Knepley } 8262de41b84cSMatthew G. Knepley numCPoints = q; 8263de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8264de41b84cSMatthew G. Knepley PetscInt fdof; 8265de41b84cSMatthew G. Knepley 82669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 82674ca5e9f5SMatthew G. Knepley if (!dof) continue; 8268de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 82699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8270de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8271de41b84cSMatthew G. Knepley } 8272de41b84cSMatthew G. Knepley numCIndices += dof; 8273de41b84cSMatthew G. Knepley } 8274de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8275de41b84cSMatthew G. Knepley /* Row indices */ 82769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8277412e9a14SMatthew G. Knepley { 8278012bc364SMatthew G. Knepley DMPlexTransform tr; 8279012bc364SMatthew G. Knepley DMPolytopeType *rct; 8280012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8281012bc364SMatthew G. Knepley 82829566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 82839566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 82849566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8285012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 82869566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8287412e9a14SMatthew G. Knepley } 82889566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8289de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8290de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 82919566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8292de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 82939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8294de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8295de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 82969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 82974ca5e9f5SMatthew G. Knepley if (!dof) continue; 82989371c9d4SSatish Balay for (s = 0; s < q; ++s) 82999371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 83004ca5e9f5SMatthew G. Knepley if (s < q) continue; 8301de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8302de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8303de41b84cSMatthew G. Knepley ++q; 8304de41b84cSMatthew G. Knepley } 8305de41b84cSMatthew G. Knepley } 83069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8307de41b84cSMatthew G. Knepley } 8308de41b84cSMatthew G. Knepley numFPoints = q; 8309de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8310de41b84cSMatthew G. Knepley PetscInt fdof; 8311de41b84cSMatthew G. Knepley 83129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 83134ca5e9f5SMatthew G. Knepley if (!dof) continue; 8314de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8316de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8317de41b84cSMatthew G. Knepley } 8318de41b84cSMatthew G. Knepley numFIndices += dof; 8319de41b84cSMatthew G. Knepley } 8320de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8321de41b84cSMatthew G. Knepley 83221dca8a05SBarry Smith PetscCheck(!numFields || foffsets[numFields] == numFIndices, PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, foffsets[numFields], numFIndices); 83231dca8a05SBarry Smith PetscCheck(!numFields || coffsets[numFields] == numCIndices, PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, coffsets[numFields], numCIndices); 83249566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83259566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8326de41b84cSMatthew G. Knepley if (numFields) { 83274acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 83284acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 83294acb8e1eSToby Isaac 83304acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 83319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 83329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8333de41b84cSMatthew G. Knepley } 83344acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 83359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 83369566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 83374acb8e1eSToby Isaac } 83384acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 83399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 83409566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 83414acb8e1eSToby Isaac } 83424acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 83439566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 83449566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8345de41b84cSMatthew G. Knepley } 8346de41b84cSMatthew G. Knepley } else { 83474acb8e1eSToby Isaac const PetscInt **permsF = NULL; 83484acb8e1eSToby Isaac const PetscInt **permsC = NULL; 83494acb8e1eSToby Isaac 83509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 83519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 83524acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 83534acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 83544acb8e1eSToby Isaac 83559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 83569566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8357de41b84cSMatthew G. Knepley } 83584acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 83594acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 83604acb8e1eSToby Isaac 83619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 83629566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8363de41b84cSMatthew G. Knepley } 83649566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 83659566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8366de41b84cSMatthew G. Knepley } 83679566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 83684acb8e1eSToby Isaac /* TODO: flips */ 8369d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8370de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8371de41b84cSMatthew G. Knepley if (ierr) { 8372de41b84cSMatthew G. Knepley PetscMPIInt rank; 8373de41b84cSMatthew G. Knepley 83749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 83759566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 83769566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 83779566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83789566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8379de41b84cSMatthew G. Knepley } 83809566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 83819566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83829566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83839566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 83843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8385de41b84cSMatthew G. Knepley } 8386de41b84cSMatthew G. Knepley 8387d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8388d71ae5a4SJacob Faibussowitsch { 83897c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 83907c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 8391230af79eSStefano Zampini PetscInt foffsets[32] = {0}, coffsets[32] = {0}; 839217c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8393412e9a14SMatthew G. Knepley DMPolytopeType ct; 83947c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 83957c927364SMatthew G. Knepley 83967c927364SMatthew G. Knepley PetscFunctionBegin; 83977c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 83987c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 83999566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 84007c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 84019566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 84027c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 84039566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 84047c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 84059566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 84067c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 84079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 840863a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 84097c927364SMatthew G. Knepley /* Column indices */ 84109566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84117c927364SMatthew G. Knepley maxFPoints = numCPoints; 84127c927364SMatthew G. Knepley /* Compress out points not in the section */ 84137c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 84149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 84157c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 84167c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 84177c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 84187c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 84197c927364SMatthew G. Knepley ++q; 84207c927364SMatthew G. Knepley } 84217c927364SMatthew G. Knepley } 84227c927364SMatthew G. Knepley numCPoints = q; 84237c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 84247c927364SMatthew G. Knepley PetscInt fdof; 84257c927364SMatthew G. Knepley 84269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 84277c927364SMatthew G. Knepley if (!dof) continue; 84287c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 84307c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 84317c927364SMatthew G. Knepley } 84327c927364SMatthew G. Knepley numCIndices += dof; 84337c927364SMatthew G. Knepley } 84347c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 84357c927364SMatthew G. Knepley /* Row indices */ 84369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8437412e9a14SMatthew G. Knepley { 8438012bc364SMatthew G. Knepley DMPlexTransform tr; 8439012bc364SMatthew G. Knepley DMPolytopeType *rct; 8440012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8441012bc364SMatthew G. Knepley 84429566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 84439566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 84449566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8445012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 84469566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8447412e9a14SMatthew G. Knepley } 84489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 84497c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 84507c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 84519566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 84527c927364SMatthew G. Knepley /* Compress out points not in the section */ 84539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 84547c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 84557c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 84569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 84577c927364SMatthew G. Knepley if (!dof) continue; 84589371c9d4SSatish Balay for (s = 0; s < q; ++s) 84599371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 84607c927364SMatthew G. Knepley if (s < q) continue; 84617c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 84627c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 84637c927364SMatthew G. Knepley ++q; 84647c927364SMatthew G. Knepley } 84657c927364SMatthew G. Knepley } 84669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 84677c927364SMatthew G. Knepley } 84687c927364SMatthew G. Knepley numFPoints = q; 84697c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 84707c927364SMatthew G. Knepley PetscInt fdof; 84717c927364SMatthew G. Knepley 84729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 84737c927364SMatthew G. Knepley if (!dof) continue; 84747c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 84767c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 84777c927364SMatthew G. Knepley } 84787c927364SMatthew G. Knepley numFIndices += dof; 84797c927364SMatthew G. Knepley } 84807c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 84817c927364SMatthew G. Knepley 84821dca8a05SBarry Smith PetscCheck(!numFields || foffsets[numFields] == numFIndices, PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, foffsets[numFields], numFIndices); 84831dca8a05SBarry Smith PetscCheck(!numFields || coffsets[numFields] == numCIndices, PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, coffsets[numFields], numCIndices); 84847c927364SMatthew G. Knepley if (numFields) { 84854acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 84864acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 84874acb8e1eSToby Isaac 84884acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 84917c927364SMatthew G. Knepley } 84924acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 84939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84949566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 84954acb8e1eSToby Isaac } 84964acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 84979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84989566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 84994acb8e1eSToby Isaac } 85004acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85019566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85029566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85037c927364SMatthew G. Knepley } 85047c927364SMatthew G. Knepley } else { 85054acb8e1eSToby Isaac const PetscInt **permsF = NULL; 85064acb8e1eSToby Isaac const PetscInt **permsC = NULL; 85074acb8e1eSToby Isaac 85089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85104acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 85114acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 85124acb8e1eSToby Isaac 85139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85149566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 85157c927364SMatthew G. Knepley } 85164acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 85174acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 85184acb8e1eSToby Isaac 85199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85209566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 85217c927364SMatthew G. Knepley } 85229566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85239566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85247c927364SMatthew G. Knepley } 85259566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 85269566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 85273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 85287c927364SMatthew G. Knepley } 85297c927364SMatthew G. Knepley 85307cd05799SMatthew G. Knepley /*@C 85317cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 85327cd05799SMatthew G. Knepley 85337cd05799SMatthew G. Knepley Input Parameter: 8534a1cb98faSBarry Smith . dm - The `DMPLEX` object 85357cd05799SMatthew G. Knepley 85367cd05799SMatthew G. Knepley Output Parameter: 85377cd05799SMatthew G. Knepley . cellHeight - The height of a cell 85387cd05799SMatthew G. Knepley 85397cd05799SMatthew G. Knepley Level: developer 85407cd05799SMatthew G. Knepley 85411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 85427cd05799SMatthew G. Knepley @*/ 8543d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8544d71ae5a4SJacob Faibussowitsch { 8545552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8546552f7358SJed Brown 8547552f7358SJed Brown PetscFunctionBegin; 8548552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85494f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8550552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 85513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8552552f7358SJed Brown } 8553552f7358SJed Brown 85547cd05799SMatthew G. Knepley /*@C 85557cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 85567cd05799SMatthew G. Knepley 85577cd05799SMatthew G. Knepley Input Parameters: 8558a1cb98faSBarry Smith + dm - The `DMPLEX` object 85597cd05799SMatthew G. Knepley - cellHeight - The height of a cell 85607cd05799SMatthew G. Knepley 85617cd05799SMatthew G. Knepley Level: developer 85627cd05799SMatthew G. Knepley 85631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 85647cd05799SMatthew G. Knepley @*/ 8565d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8566d71ae5a4SJacob Faibussowitsch { 8567552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8568552f7358SJed Brown 8569552f7358SJed Brown PetscFunctionBegin; 8570552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8571552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 85723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8573552f7358SJed Brown } 8574552f7358SJed Brown 8575e6139122SMatthew G. Knepley /*@ 85762827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8577e6139122SMatthew G. Knepley 85782827ebadSStefano Zampini Input Parameters: 85792827ebadSStefano Zampini + dm - The `DMPLEX` object 85802827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8581e6139122SMatthew G. Knepley 8582e6139122SMatthew G. Knepley Output Parameters: 85832827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 85842827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8585e6139122SMatthew G. Knepley 85862a9f31c0SMatthew G. Knepley Level: advanced 8587e6139122SMatthew G. Knepley 85882827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8589e6139122SMatthew G. Knepley @*/ 85902827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8591d71ae5a4SJacob Faibussowitsch { 85922827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 85932827ebadSStefano Zampini DMLabel label; 85942827ebadSStefano Zampini PetscInt pStart, pEnd; 8595e6139122SMatthew G. Knepley 8596e6139122SMatthew G. Knepley PetscFunctionBegin; 8597e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85982827ebadSStefano Zampini if (start) { 85994f572ea9SToby Isaac PetscAssertPointer(start, 3); 86002827ebadSStefano Zampini *start = 0; 86012827ebadSStefano Zampini } 86022827ebadSStefano Zampini if (end) { 86034f572ea9SToby Isaac PetscAssertPointer(end, 4); 86042827ebadSStefano Zampini *end = 0; 86052827ebadSStefano Zampini } 86062827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86072827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 86082827ebadSStefano Zampini if (mesh->tr) { 86092827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 86102827ebadSStefano Zampini } else { 86112827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 86122827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 86132827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 86142827ebadSStefano Zampini } 86153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8616e6139122SMatthew G. Knepley } 8617e6139122SMatthew G. Knepley 8618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8619d71ae5a4SJacob Faibussowitsch { 8620552f7358SJed Brown PetscSection section, globalSection; 8621552f7358SJed Brown PetscInt *numbers, p; 8622552f7358SJed Brown 8623552f7358SJed Brown PetscFunctionBegin; 8624d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 86259566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 86269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 862748a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 86289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8629eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection)); 86309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8631552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 86329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8633ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8634ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8635552f7358SJed Brown } 86369566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8637ef48cebcSMatthew G. Knepley if (globalSize) { 8638ef48cebcSMatthew G. Knepley PetscLayout layout; 86399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 86409566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 86419566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8642ef48cebcSMatthew G. Knepley } 86439566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 86449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 86453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8646552f7358SJed Brown } 8647552f7358SJed Brown 8648d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8649d71ae5a4SJacob Faibussowitsch { 8650412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8651552f7358SJed Brown 8652552f7358SJed Brown PetscFunctionBegin; 86539566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 86549566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 86559566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 86569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 86573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8658552f7358SJed Brown } 865981ed3555SMatthew G. Knepley 86608dab3259SMatthew G. Knepley /*@ 86617cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 86627cd05799SMatthew G. Knepley 86637cd05799SMatthew G. Knepley Input Parameter: 8664a1cb98faSBarry Smith . dm - The `DMPLEX` object 86657cd05799SMatthew G. Knepley 86667cd05799SMatthew G. Knepley Output Parameter: 86677cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 86687cd05799SMatthew G. Knepley 86697cd05799SMatthew G. Knepley Level: developer 86707cd05799SMatthew G. Knepley 86711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 86727cd05799SMatthew G. Knepley @*/ 8673d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8674d71ae5a4SJacob Faibussowitsch { 867581ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 867681ed3555SMatthew G. Knepley 867781ed3555SMatthew G. Knepley PetscFunctionBegin; 867881ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86799566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8680552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 86813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8682552f7358SJed Brown } 8683552f7358SJed Brown 8684d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8685d71ae5a4SJacob Faibussowitsch { 8686412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 868781ed3555SMatthew G. Knepley 868881ed3555SMatthew G. Knepley PetscFunctionBegin; 868981ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86909566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 86919566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 86923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 869381ed3555SMatthew G. Knepley } 869481ed3555SMatthew G. Knepley 86958dab3259SMatthew G. Knepley /*@ 86966aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 86977cd05799SMatthew G. Knepley 86987cd05799SMatthew G. Knepley Input Parameter: 8699a1cb98faSBarry Smith . dm - The `DMPLEX` object 87007cd05799SMatthew G. Knepley 87017cd05799SMatthew G. Knepley Output Parameter: 87027cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 87037cd05799SMatthew G. Knepley 87047cd05799SMatthew G. Knepley Level: developer 87057cd05799SMatthew G. Knepley 87061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87077cd05799SMatthew G. Knepley @*/ 8708d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8709d71ae5a4SJacob Faibussowitsch { 8710552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8711552f7358SJed Brown 8712552f7358SJed Brown PetscFunctionBegin; 8713552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87149566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8715552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 87163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8717552f7358SJed Brown } 8718552f7358SJed Brown 87198dab3259SMatthew G. Knepley /*@ 8720966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8721966484cfSJed Brown 872220f4b53cSBarry Smith Collective 87237cd05799SMatthew G. Knepley 87247cd05799SMatthew G. Knepley Input Parameter: 8725a1cb98faSBarry Smith . dm - The `DMPLEX` object 87267cd05799SMatthew G. Knepley 87277cd05799SMatthew G. Knepley Output Parameter: 87287cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 87297cd05799SMatthew G. Knepley 8730a1cb98faSBarry Smith Level: developer 8731966484cfSJed Brown 8732a1cb98faSBarry Smith Notes: 8733a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8734966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8735966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8736966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8737966484cfSJed Brown 8738966484cfSJed Brown The partitioned mesh is 8739966484cfSJed Brown ``` 8740966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8741966484cfSJed Brown ``` 8742966484cfSJed Brown and its global numbering is 8743966484cfSJed Brown ``` 8744966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8745966484cfSJed Brown ``` 8746966484cfSJed Brown Then the global numbering is provided as 8747966484cfSJed Brown ``` 8748966484cfSJed Brown [0] Number of indices in set 5 8749966484cfSJed Brown [0] 0 0 8750966484cfSJed Brown [0] 1 1 8751966484cfSJed Brown [0] 2 3 8752966484cfSJed Brown [0] 3 4 8753966484cfSJed Brown [0] 4 -6 8754966484cfSJed Brown [1] Number of indices in set 3 8755966484cfSJed Brown [1] 0 2 8756966484cfSJed Brown [1] 1 5 8757966484cfSJed Brown [1] 2 6 8758966484cfSJed Brown ``` 8759966484cfSJed Brown 87601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87617cd05799SMatthew G. Knepley @*/ 8762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8763d71ae5a4SJacob Faibussowitsch { 8764ef48cebcSMatthew G. Knepley IS nums[4]; 8765862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8766ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 87670c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8768ef48cebcSMatthew G. Knepley 8769ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8770ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 87720c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 87739566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 87740c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8775862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8776862913ffSStefano Zampini PetscInt end; 8777862913ffSStefano Zampini 8778862913ffSStefano Zampini depths[d] = depth - d; 87799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 87800c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8781862913ffSStefano Zampini } 87820c15888dSMatthew G. Knepley if (empty) 87830c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 87840c15888dSMatthew G. Knepley depths[d] = -1; 87850c15888dSMatthew G. Knepley starts[d] = -1; 87860c15888dSMatthew G. Knepley } 87870c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 87881c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8789ad540459SPierre Jolivet for (d = 0; d <= depth; ++d) PetscCheck(starts[d] < 0 || depths[d] == gdepths[d], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected depth %" PetscInt_FMT ", found %" PetscInt_FMT, depths[d], gdepths[d]); 87900c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8791ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8792ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8793ef48cebcSMatthew G. Knepley 87949566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 87959566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8796ef48cebcSMatthew G. Knepley shift += gsize; 8797ef48cebcSMatthew G. Knepley } 8798d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 87999566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 88003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8801ef48cebcSMatthew G. Knepley } 8802ef48cebcSMatthew G. Knepley 880308a22f4bSMatthew G. Knepley /*@ 880408a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 880508a22f4bSMatthew G. Knepley 880608a22f4bSMatthew G. Knepley Input Parameter: 8807a1cb98faSBarry Smith . dm - The `DMPLEX` object 880808a22f4bSMatthew G. Knepley 880908a22f4bSMatthew G. Knepley Output Parameter: 881008a22f4bSMatthew G. Knepley . ranks - The rank field 881108a22f4bSMatthew G. Knepley 8812a1cb98faSBarry Smith Options Database Key: 881320f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 881408a22f4bSMatthew G. Knepley 881508a22f4bSMatthew G. Knepley Level: intermediate 881608a22f4bSMatthew G. Knepley 88171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 881808a22f4bSMatthew G. Knepley @*/ 8819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8820d71ae5a4SJacob Faibussowitsch { 882108a22f4bSMatthew G. Knepley DM rdm; 882208a22f4bSMatthew G. Knepley PetscFE fe; 882308a22f4bSMatthew G. Knepley PetscScalar *r; 882408a22f4bSMatthew G. Knepley PetscMPIInt rank; 8825a55f9a55SMatthew G. Knepley DMPolytopeType ct; 882608a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8827a55f9a55SMatthew G. Knepley PetscBool simplex; 882808a22f4bSMatthew G. Knepley 882908a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8830f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88314f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 88329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 88339566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 88349566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 88359566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 88369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8837a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 88389566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 88399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 88409566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 88419566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 88429566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 88439566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 88449566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 88459566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 884608a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 884708a22f4bSMatthew G. Knepley PetscScalar *lr; 884808a22f4bSMatthew G. Knepley 88499566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 885071f09efeSPierre Jolivet if (lr) *lr = rank; 885108a22f4bSMatthew G. Knepley } 88529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 88539566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 88543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 885508a22f4bSMatthew G. Knepley } 885608a22f4bSMatthew G. Knepley 8857ca8062c8SMatthew G. Knepley /*@ 8858acf3173eSStefano Zampini DMPlexCreateLabelField - Create a field whose value is the label value for that point 885918e14f0cSMatthew G. Knepley 886018e14f0cSMatthew G. Knepley Input Parameters: 886120f4b53cSBarry Smith + dm - The `DMPLEX` 886220f4b53cSBarry Smith - label - The `DMLabel` 886318e14f0cSMatthew G. Knepley 886418e14f0cSMatthew G. Knepley Output Parameter: 886518e14f0cSMatthew G. Knepley . val - The label value field 886618e14f0cSMatthew G. Knepley 886720f4b53cSBarry Smith Options Database Key: 886820f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 886918e14f0cSMatthew G. Knepley 887018e14f0cSMatthew G. Knepley Level: intermediate 887118e14f0cSMatthew G. Knepley 88721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 887318e14f0cSMatthew G. Knepley @*/ 8874d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8875d71ae5a4SJacob Faibussowitsch { 88761033741fSStefano Zampini DM rdm, plex; 8877acf3173eSStefano Zampini Vec lval; 8878acf3173eSStefano Zampini PetscSection section; 887918e14f0cSMatthew G. Knepley PetscFE fe; 888018e14f0cSMatthew G. Knepley PetscScalar *v; 8881acf3173eSStefano Zampini PetscInt dim, pStart, pEnd, p, cStart; 8882acf3173eSStefano Zampini DMPolytopeType ct; 8883acf3173eSStefano Zampini char name[PETSC_MAX_PATH_LEN]; 8884acf3173eSStefano Zampini const char *lname, *prefix; 888518e14f0cSMatthew G. Knepley 888618e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 888718e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88884f572ea9SToby Isaac PetscAssertPointer(label, 2); 88894f572ea9SToby Isaac PetscAssertPointer(val, 3); 88909566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 8891acf3173eSStefano Zampini PetscCall(DMConvert(rdm, DMPLEX, &plex)); 8892acf3173eSStefano Zampini PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL)); 8893acf3173eSStefano Zampini PetscCall(DMPlexGetCellType(plex, cStart, &ct)); 8894acf3173eSStefano Zampini PetscCall(DMDestroy(&plex)); 88959566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 8896acf3173eSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 8897acf3173eSStefano Zampini PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 8898acf3173eSStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname)); 8899acf3173eSStefano Zampini PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe)); 8900acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)fe, "")); 89019566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 89029566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 89039566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 89049566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 8905acf3173eSStefano Zampini PetscCall(DMCreateLocalVector(rdm, &lval)); 8906acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*val, lname)); 8907acf3173eSStefano Zampini PetscCall(DMGetLocalSection(rdm, §ion)); 8908acf3173eSStefano Zampini PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 8909acf3173eSStefano Zampini PetscCall(VecGetArray(lval, &v)); 8910acf3173eSStefano Zampini for (p = pStart; p < pEnd; ++p) { 8911acf3173eSStefano Zampini PetscInt cval, dof, off; 891218e14f0cSMatthew G. Knepley 8913acf3173eSStefano Zampini PetscCall(PetscSectionGetDof(section, p, &dof)); 8914acf3173eSStefano Zampini if (!dof) continue; 8915acf3173eSStefano Zampini PetscCall(DMLabelGetValue(label, p, &cval)); 8916acf3173eSStefano Zampini PetscCall(PetscSectionGetOffset(section, p, &off)); 8917acf3173eSStefano Zampini for (PetscInt d = 0; d < dof; d++) v[off + d] = cval; 891818e14f0cSMatthew G. Knepley } 8919acf3173eSStefano Zampini PetscCall(VecRestoreArray(lval, &v)); 8920acf3173eSStefano Zampini PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val)); 8921acf3173eSStefano Zampini PetscCall(VecDestroy(&lval)); 89229566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 892418e14f0cSMatthew G. Knepley } 892518e14f0cSMatthew G. Knepley 892618e14f0cSMatthew G. Knepley /*@ 8927ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8928ca8062c8SMatthew G. Knepley 892969916449SMatthew G. Knepley Input Parameter: 8930a1cb98faSBarry Smith . dm - The `DMPLEX` object 8931a1cb98faSBarry Smith 8932a1cb98faSBarry Smith Level: developer 8933ca8062c8SMatthew G. Knepley 893495eb5ee5SVaclav Hapla Notes: 893595eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 893695eb5ee5SVaclav Hapla 893720f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 8938ca8062c8SMatthew G. Knepley 89391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8940ca8062c8SMatthew G. Knepley @*/ 8941d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 8942d71ae5a4SJacob Faibussowitsch { 8943ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8944ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8945ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 894657beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 894757beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8948ca8062c8SMatthew G. Knepley 8949ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8950ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89519566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 89529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 89539566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8954ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 89559566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8956ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 89579566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 89589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8959ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 896042e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 896142e66dfaSMatthew G. Knepley PetscInt d; 896242e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 89639371c9d4SSatish Balay if (cone[c] == cone[d]) { 89649371c9d4SSatish Balay dup = PETSC_TRUE; 89659371c9d4SSatish Balay break; 89669371c9d4SSatish Balay } 896742e66dfaSMatthew G. Knepley } 89689566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 89699566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8970ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8971ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8972ca8062c8SMatthew G. Knepley } 897342e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 897463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 897548a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 89769566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 897763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 897848a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 89799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 898063a3b9bcSJacob Faibussowitsch PetscCheck(!dup, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not repeatedly found in support of repeated cone point %" PetscInt_FMT, p, cone[c]); 8981f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8982ca8062c8SMatthew G. Knepley } 898342e66dfaSMatthew G. Knepley } 89849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 89859371c9d4SSatish Balay if (p != pp) { 89869371c9d4SSatish Balay storagecheck = PETSC_FALSE; 89879371c9d4SSatish Balay continue; 89889371c9d4SSatish Balay } 89899566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 89909566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8991ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 89929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 89939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8994ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 89959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 89969371c9d4SSatish Balay if (cone[c] != pp) { 89979371c9d4SSatish Balay c = 0; 89989371c9d4SSatish Balay break; 89999371c9d4SSatish Balay } 9000ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 9001ca8062c8SMatthew G. Knepley } 9002ca8062c8SMatthew G. Knepley if (c >= coneSize) { 900363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 900448a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 90059566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 900663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 900748a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 90089566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 900963a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 9010ca8062c8SMatthew G. Knepley } 9011ca8062c8SMatthew G. Knepley } 9012ca8062c8SMatthew G. Knepley } 901357beb4faSStefano Zampini if (storagecheck) { 90149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 90159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 901663a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 901757beb4faSStefano Zampini } 90183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9019ca8062c8SMatthew G. Knepley } 9020ca8062c8SMatthew G. Knepley 9021412e9a14SMatthew G. Knepley /* 9022412e9a14SMatthew 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. 9023412e9a14SMatthew G. Knepley */ 9024d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9025d71ae5a4SJacob Faibussowitsch { 9026412e9a14SMatthew G. Knepley DMPolytopeType cct; 9027412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9028412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9029412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9030412e9a14SMatthew G. Knepley 9031412e9a14SMatthew G. Knepley PetscFunctionBegin; 9032412e9a14SMatthew G. Knepley *unsplit = 0; 9033412e9a14SMatthew G. Knepley switch (ct) { 9034d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9035d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9036d71ae5a4SJacob Faibussowitsch break; 9037412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 90389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 90399566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9040412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 90419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9042412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9043412e9a14SMatthew G. Knepley } 9044412e9a14SMatthew G. Knepley break; 9045412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9046412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 90479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 90489566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9049412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 90509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 90519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9052412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 90539566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9054412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9055412e9a14SMatthew G. Knepley PetscInt p; 90569371c9d4SSatish Balay for (p = 0; p < npt; ++p) 90579371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9058412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9059412e9a14SMatthew G. Knepley } 9060412e9a14SMatthew G. Knepley } 9061412e9a14SMatthew G. Knepley } 9062412e9a14SMatthew G. Knepley break; 9063d71ae5a4SJacob Faibussowitsch default: 9064d71ae5a4SJacob Faibussowitsch break; 9065412e9a14SMatthew G. Knepley } 9066412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 90679566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9068412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9069412e9a14SMatthew G. Knepley } 90703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9071412e9a14SMatthew G. Knepley } 9072412e9a14SMatthew G. Knepley 9073ca8062c8SMatthew G. Knepley /*@ 9074ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9075ca8062c8SMatthew G. Knepley 9076ca8062c8SMatthew G. Knepley Input Parameters: 9077a1cb98faSBarry Smith + dm - The `DMPLEX` object 907858723a97SMatthew G. Knepley - cellHeight - Normally 0 9079ca8062c8SMatthew G. Knepley 9080a1cb98faSBarry Smith Level: developer 9081a1cb98faSBarry Smith 908295eb5ee5SVaclav Hapla Notes: 908395eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 908425c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9085ca8062c8SMatthew G. Knepley 908620f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 908795eb5ee5SVaclav Hapla 90881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9089ca8062c8SMatthew G. Knepley @*/ 9090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9091d71ae5a4SJacob Faibussowitsch { 9092412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9093412e9a14SMatthew G. Knepley DMPolytopeType ct; 9094412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9095ca8062c8SMatthew G. Knepley 9096ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9097ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90989566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 90999566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 91009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9101412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9102412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9103412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 910458723a97SMatthew G. Knepley 91059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 910663a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 9107412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9108412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 91099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 911063a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == DMPolytopeTypeGetConeSize(ct), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has cone size %" PetscInt_FMT " != %" PetscInt_FMT, c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct)); 9111412e9a14SMatthew G. Knepley } 91129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 911358723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 911458723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9115412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 911658723a97SMatthew G. Knepley } 91179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9118412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9119412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9120412e9a14SMatthew G. Knepley PetscInt unsplit; 912142363296SMatthew G. Knepley 91229566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9123412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 912442363296SMatthew G. Knepley } 912563a3b9bcSJacob Faibussowitsch PetscCheck(Nv == DMPolytopeTypeGetNumVertices(ct), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " vertices != %" PetscInt_FMT, c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct)); 912642363296SMatthew G. Knepley } 91273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9128ca8062c8SMatthew G. Knepley } 91299bf0dad6SMatthew G. Knepley 91309bf0dad6SMatthew G. Knepley /*@ 91319bf0dad6SMatthew 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 91329bf0dad6SMatthew G. Knepley 913320f4b53cSBarry Smith Collective 9134899ea2b8SJacob Faibussowitsch 91359bf0dad6SMatthew G. Knepley Input Parameters: 9136a1cb98faSBarry Smith + dm - The `DMPLEX` object 91379bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 91389bf0dad6SMatthew G. Knepley 9139a1cb98faSBarry Smith Level: developer 9140a1cb98faSBarry Smith 914145da879fSVaclav Hapla Notes: 914245da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 914345da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 914445da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 914545da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 91469bf0dad6SMatthew G. Knepley 9147a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 914895eb5ee5SVaclav Hapla 91491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 91509bf0dad6SMatthew G. Knepley @*/ 9151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9152d71ae5a4SJacob Faibussowitsch { 9153ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9154899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 91559bf0dad6SMatthew G. Knepley 91569bf0dad6SMatthew G. Knepley PetscFunctionBegin; 91579bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91588f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 91593ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 91608f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 91613ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 91623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9163899ea2b8SJacob Faibussowitsch } 9164899ea2b8SJacob Faibussowitsch 91659566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 91669566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 91679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9168ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 91699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 91703554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9171412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9172412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9173ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9174412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9175412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 91769bf0dad6SMatthew G. Knepley 91779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 91789566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9179412e9a14SMatthew G. Knepley if (unsplit) continue; 91809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 91819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 91839566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 91849bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 91859bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 91869bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 91879bf0dad6SMatthew G. Knepley } 91889566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 918963a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == numFaces, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " faces but should have %" PetscInt_FMT, c, DMPolytopeTypes[ct], coneSize, numFaces); 91909bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9191d4961f80SStefano Zampini DMPolytopeType fct; 91929bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 91939bf0dad6SMatthew G. Knepley 91949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 91959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 91969bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 91979bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 91989bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 91999bf0dad6SMatthew G. Knepley } 920063a3b9bcSJacob Faibussowitsch PetscCheck(fnumCorners == faceSizes[f], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " of type %s (cone idx %" PetscInt_FMT ") of cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " vertices but should have %" PetscInt_FMT, cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], fnumCorners, faceSizes[f]); 92019bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9202b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9203b5a892a1SMatthew G. Knepley PetscInt v1; 9204b5a892a1SMatthew G. Knepley 92059566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 920663a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 92079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 920863a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 92099566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 921063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " of type %s (cone idx %" PetscInt_FMT ", ornt %" PetscInt_FMT ") of cell %" PetscInt_FMT " of type %s vertex %" PetscInt_FMT ", %" PetscInt_FMT " != %" PetscInt_FMT, cone[f], DMPolytopeTypes[fct], f, ornt[f], c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff + v]); 9211b5a892a1SMatthew G. Knepley } 92129bf0dad6SMatthew G. Knepley } 92139566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9214412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 92159bf0dad6SMatthew G. Knepley } 92169566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 92179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92189bf0dad6SMatthew G. Knepley } 92193554e41dSMatthew G. Knepley } 92203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9221552f7358SJed Brown } 92223913d7c8SMatthew G. Knepley 9223bb6a34a8SMatthew G. Knepley /*@ 9224bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9225bb6a34a8SMatthew G. Knepley 9226bb6a34a8SMatthew G. Knepley Input Parameter: 9227a1cb98faSBarry Smith . dm - The `DMPLEX` object 9228a1cb98faSBarry Smith 9229a1cb98faSBarry Smith Level: developer 9230bb6a34a8SMatthew G. Knepley 923195eb5ee5SVaclav Hapla Notes: 923295eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 923395eb5ee5SVaclav Hapla 923420f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9235bb6a34a8SMatthew G. Knepley 92361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9237bb6a34a8SMatthew G. Knepley @*/ 9238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9239d71ae5a4SJacob Faibussowitsch { 9240a2a9e04cSMatthew G. Knepley Vec coordinates; 9241bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9242bb6a34a8SMatthew G. Knepley PetscReal vol; 924351a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9244bb6a34a8SMatthew G. Knepley 9245bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 92469566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 92479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 92483ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 92499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9250bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 92519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9252a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 92539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 92543ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9255412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9256412e9a14SMatthew G. Knepley DMPolytopeType ct; 9257412e9a14SMatthew G. Knepley PetscInt unsplit; 9258412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9259412e9a14SMatthew G. Knepley 92609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9261412e9a14SMatthew G. Knepley switch (ct) { 9262412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9263412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9264d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9265d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9266d71ae5a4SJacob Faibussowitsch break; 9267d71ae5a4SJacob Faibussowitsch default: 9268d71ae5a4SJacob Faibussowitsch break; 9269412e9a14SMatthew G. Knepley } 9270412e9a14SMatthew G. Knepley switch (ct) { 9271412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9272412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9273412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9274d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9275d71ae5a4SJacob Faibussowitsch continue; 9276d71ae5a4SJacob Faibussowitsch default: 9277d71ae5a4SJacob Faibussowitsch break; 9278412e9a14SMatthew G. Knepley } 92799566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9280412e9a14SMatthew G. Knepley if (unsplit) continue; 92819566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 92821dca8a05SBarry Smith PetscCheck(detJ >= -PETSC_SMALL && (detJ > 0.0 || ignoreZeroVol), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double)detJ); 928363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 92846858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 92856858538eSMatthew G. Knepley if (depth > 1) { 92869566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 92871dca8a05SBarry Smith PetscCheck(vol >= -PETSC_SMALL && (vol > 0.0 || ignoreZeroVol), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double)vol); 928863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9289bb6a34a8SMatthew G. Knepley } 9290bb6a34a8SMatthew G. Knepley } 92913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9292bb6a34a8SMatthew G. Knepley } 9293bb6a34a8SMatthew G. Knepley 929403da9461SVaclav Hapla /*@ 929520f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 92967726db96SVaclav Hapla 929720f4b53cSBarry Smith Collective 929803da9461SVaclav Hapla 929903da9461SVaclav Hapla Input Parameters: 9300a1cb98faSBarry Smith + dm - The `DMPLEX` object 930120f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9302a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9303a1cb98faSBarry Smith 9304a1cb98faSBarry Smith Level: developer 930503da9461SVaclav Hapla 9306e83a0d2dSVaclav Hapla Notes: 9307e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 930803da9461SVaclav Hapla 9309a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 931095eb5ee5SVaclav Hapla 9311baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9312d7d32a9aSMatthew G. Knepley 93131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 931403da9461SVaclav Hapla @*/ 9315d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9316d71ae5a4SJacob Faibussowitsch { 93177726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 93187726db96SVaclav Hapla const PetscInt *locals; 93197726db96SVaclav Hapla const PetscSFNode *remotes; 9320f0cfc026SVaclav Hapla PetscBool distributed; 93217726db96SVaclav Hapla MPI_Comm comm; 93227726db96SVaclav Hapla PetscMPIInt rank; 932303da9461SVaclav Hapla 932403da9461SVaclav Hapla PetscFunctionBegin; 932503da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93267726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 93277726db96SVaclav Hapla else pointSF = dm->sf; 93287726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 93297726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 93307726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 93317726db96SVaclav Hapla { 93327726db96SVaclav Hapla PetscMPIInt mpiFlag; 93337726db96SVaclav Hapla 93347726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 93357726db96SVaclav Hapla PetscCheck(mpiFlag == MPI_CONGRUENT || mpiFlag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "DM and Point SF have different communicators (flag %d)", mpiFlag); 93367726db96SVaclav Hapla } 93377726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 93389566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 93397726db96SVaclav Hapla if (!distributed) { 93407726db96SVaclav Hapla PetscCheck(nroots < 0 || nleaves == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Undistributed DMPlex cannot have non-empty PointSF (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves); 93413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 93428918e3e2SVaclav Hapla } 93437726db96SVaclav Hapla PetscCheck(nroots >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves); 93447726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 934503da9461SVaclav Hapla 93467726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 93477726db96SVaclav Hapla { 93487726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 93497726db96SVaclav Hapla 93507726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 93517726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9352d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 93537726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 93547726db96SVaclav Hapla } 93557726db96SVaclav Hapla 93567726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 93577726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 93587726db96SVaclav Hapla PetscAssert(remotes[l].rank != (PetscInt)rank, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains local point %" PetscInt_FMT " <- (%" PetscInt_FMT ",%" PetscInt_FMT ")", locals ? locals[l] : l, remotes[l].rank, remotes[l].index); 93597726db96SVaclav Hapla } 93607726db96SVaclav Hapla 93617726db96SVaclav Hapla /* Check there are no cells in interface */ 93627726db96SVaclav Hapla if (!overlap) { 93637726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 93647726db96SVaclav Hapla 93659566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 93669566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9367f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 93687726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9369f5869d18SMatthew G. Knepley 93707726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 93717726db96SVaclav Hapla } 937203da9461SVaclav Hapla } 9373ece87651SVaclav Hapla 93747726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 93757726db96SVaclav Hapla { 93767726db96SVaclav Hapla const PetscInt *rootdegree; 93777726db96SVaclav Hapla 93787726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 93797726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9380f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 93817726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9382f5869d18SMatthew G. Knepley const PetscInt *cone; 9383f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9384f5869d18SMatthew G. Knepley 93859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 93869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9387f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9388f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 93897726db96SVaclav Hapla if (locals) { 93909566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 93917726db96SVaclav Hapla } else { 93927726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 93937726db96SVaclav Hapla } 939463a3b9bcSJacob Faibussowitsch PetscCheck(idx >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " but not %" PetscInt_FMT " from its cone", point, cone[c]); 9395f5869d18SMatthew G. Knepley } 9396f5869d18SMatthew G. Knepley } 9397ece87651SVaclav Hapla } 93987726db96SVaclav Hapla } 93993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 940003da9461SVaclav Hapla } 940103da9461SVaclav Hapla 94027f9d8d6cSVaclav Hapla /*@ 940320f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 94047f9d8d6cSVaclav Hapla 94057f9d8d6cSVaclav Hapla Input Parameter: 9406a1cb98faSBarry Smith . dm - The `DMPLEX` object 9407a1cb98faSBarry Smith 9408a1cb98faSBarry Smith Level: developer 94097f9d8d6cSVaclav Hapla 94107f9d8d6cSVaclav Hapla Notes: 94117f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 94127f9d8d6cSVaclav Hapla 941320f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 94147f9d8d6cSVaclav Hapla 941520f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 94167f9d8d6cSVaclav Hapla 94171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 94187f9d8d6cSVaclav Hapla @*/ 9419d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9420d71ae5a4SJacob Faibussowitsch { 94217f9d8d6cSVaclav Hapla PetscInt cellHeight; 94227f9d8d6cSVaclav Hapla 9423b5a892a1SMatthew G. Knepley PetscFunctionBegin; 94247f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94259566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 94269566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 94279566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 94289566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9429d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 94309566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 94313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9432b5a892a1SMatthew G. Knepley } 9433b5a892a1SMatthew G. Knepley 94349371c9d4SSatish Balay typedef struct cell_stats { 9435068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9436068a5610SStefano Zampini PetscInt count; 9437068a5610SStefano Zampini } cell_stats_t; 9438068a5610SStefano Zampini 9439d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9440d71ae5a4SJacob Faibussowitsch { 9441068a5610SStefano Zampini PetscInt i, N = *len; 9442068a5610SStefano Zampini 9443068a5610SStefano Zampini for (i = 0; i < N; i++) { 9444068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9445068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9446068a5610SStefano Zampini 9447068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9448068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9449068a5610SStefano Zampini B->sum += A->sum; 9450068a5610SStefano Zampini B->squaresum += A->squaresum; 9451068a5610SStefano Zampini B->count += A->count; 9452068a5610SStefano Zampini } 9453068a5610SStefano Zampini } 9454068a5610SStefano Zampini 9455068a5610SStefano Zampini /*@ 945643fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9457068a5610SStefano Zampini 945820f4b53cSBarry Smith Collective 94598261a58bSMatthew G. Knepley 9460068a5610SStefano Zampini Input Parameters: 9461a1cb98faSBarry Smith + dm - The `DMPLEX` object 946220f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9463a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9464a1cb98faSBarry Smith 9465a1cb98faSBarry Smith Level: developer 9466068a5610SStefano Zampini 946795eb5ee5SVaclav Hapla Notes: 946895eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 946995eb5ee5SVaclav Hapla 9470a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9471068a5610SStefano Zampini 94721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9473068a5610SStefano Zampini @*/ 9474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9475d71ae5a4SJacob Faibussowitsch { 9476068a5610SStefano Zampini DM dmCoarse; 947743fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 947843fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 947943fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 948043fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9481412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 948243fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9483068a5610SStefano Zampini 9484068a5610SStefano Zampini PetscFunctionBegin; 9485068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9486068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9487068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9488068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9489068a5610SStefano Zampini stats.count = 0; 9490068a5610SStefano Zampini 94919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 94929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 94939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 94949566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 94959566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 94969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9497412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9498068a5610SStefano Zampini PetscInt i; 9499068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9500068a5610SStefano Zampini 95019566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 950263a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 950343fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9504068a5610SStefano Zampini frobJ += J[i] * J[i]; 9505068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9506068a5610SStefano Zampini } 9507068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9508068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9509068a5610SStefano Zampini 9510068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9511068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9512068a5610SStefano Zampini stats.sum += cond; 9513068a5610SStefano Zampini stats.squaresum += cond2; 9514068a5610SStefano Zampini stats.count++; 95158261a58bSMatthew G. Knepley if (output && cond > limit) { 951643fa8764SMatthew G. Knepley PetscSection coordSection; 951743fa8764SMatthew G. Knepley Vec coordsLocal; 951843fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 951943fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 952043fa8764SMatthew G. Knepley 95219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 95229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 95239566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 952463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 952543fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 952663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 952743fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 95289566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 95299566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 953043fa8764SMatthew G. Knepley } 95319566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 953243fa8764SMatthew G. Knepley } 95339566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 953443fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 953543fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 953643fa8764SMatthew G. Knepley 953743fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 953843fa8764SMatthew G. Knepley PetscReal len; 953943fa8764SMatthew G. Knepley 95409566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 954163a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 954243fa8764SMatthew G. Knepley } 954343fa8764SMatthew G. Knepley } 95449566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 95459566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 954643fa8764SMatthew G. Knepley } 9547068a5610SStefano Zampini } 95489566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9549068a5610SStefano Zampini 9550068a5610SStefano Zampini if (size > 1) { 9551068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9552068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9553068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9554068a5610SStefano Zampini MPI_Op statReduce; 9555068a5610SStefano Zampini 95569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 95579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 95589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 95599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 95609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 95619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9562068a5610SStefano Zampini } else { 95639566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9564068a5610SStefano Zampini } 9565dd400576SPatrick Sanan if (rank == 0) { 9566068a5610SStefano Zampini count = globalStats.count; 9567068a5610SStefano Zampini min = globalStats.min; 9568068a5610SStefano Zampini max = globalStats.max; 9569068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9570068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9571068a5610SStefano Zampini } 9572068a5610SStefano Zampini 957348a46eb9SPierre Jolivet if (output) PetscCall(PetscPrintf(comm, "Mesh with %" PetscInt_FMT " cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double)min, (double)max, (double)mean, (double)stdev)); 95749566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9575068a5610SStefano Zampini 95769566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9577068a5610SStefano Zampini if (dmCoarse) { 9578068a5610SStefano Zampini PetscBool isplex; 9579068a5610SStefano Zampini 95809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 95811baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9582068a5610SStefano Zampini } 95833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9584068a5610SStefano Zampini } 9585068a5610SStefano Zampini 9586f108dbd7SJacob Faibussowitsch /*@ 9587f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9588f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9589f108dbd7SJacob Faibussowitsch 959020f4b53cSBarry Smith Collective 9591f108dbd7SJacob Faibussowitsch 9592f108dbd7SJacob Faibussowitsch Input Parameters: 9593a1cb98faSBarry Smith + dm - The `DMPLEX` object 9594a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9595f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9596f108dbd7SJacob Faibussowitsch 9597f108dbd7SJacob Faibussowitsch Output Parameters: 959820f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9599a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9600f108dbd7SJacob Faibussowitsch 9601f108dbd7SJacob Faibussowitsch Options Database Keys: 9602a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9603f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9604f108dbd7SJacob Faibussowitsch 9605a1cb98faSBarry Smith Level: intermediate 9606a1cb98faSBarry Smith 9607f108dbd7SJacob Faibussowitsch Notes: 9608a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9609f108dbd7SJacob Faibussowitsch 9610a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9611f108dbd7SJacob Faibussowitsch 9612f108dbd7SJacob 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 9613f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9614f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9615f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9616f108dbd7SJacob Faibussowitsch 9617f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9618f108dbd7SJacob Faibussowitsch 9619a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9620f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9621f108dbd7SJacob Faibussowitsch 9622f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9623f108dbd7SJacob Faibussowitsch 96241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9625f108dbd7SJacob Faibussowitsch @*/ 9626d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9627d71ae5a4SJacob Faibussowitsch { 96286ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 96296ed19f2fSJacob Faibussowitsch PetscInt *idx; 96306ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9631f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 96326ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9633f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9634f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9635f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9636f108dbd7SJacob Faibussowitsch IS glob; 9637f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9638f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9639f108dbd7SJacob Faibussowitsch 9640f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9641f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9642ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 96434f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 96446bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 96459566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 96469566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 964763a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 96486ed19f2fSJacob Faibussowitsch { 96496ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 96506ed19f2fSJacob Faibussowitsch 96519566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9652f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9653f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9654f108dbd7SJacob Faibussowitsch 96559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 965698921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9657f108dbd7SJacob Faibussowitsch } 96586ed19f2fSJacob Faibussowitsch } 9659f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 96604f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 96619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 96629566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 96639371c9d4SSatish Balay } else { 96649371c9d4SSatish Balay *OrthQualLabel = NULL; 96659371c9d4SSatish Balay } 96669566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 96679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 96689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 96699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 96709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 96719566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 96729566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 96739566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 96749566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 96759566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 96769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 96779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 96789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 96799566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 96809566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 96819566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 96829566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 96839566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 96846ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 96856ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9686f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9687f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9688898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9689f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9690f108dbd7SJacob Faibussowitsch 96916ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9692f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9693f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 96949566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 96959566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9696f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 96979566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 96986ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 96996ed19f2fSJacob Faibussowitsch PetscInt i; 97006ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9701f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9702f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9703f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9704f108dbd7SJacob Faibussowitsch 9705f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9706f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 97079566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9708f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 97096ed19f2fSJacob Faibussowitsch { 97106ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 97116ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 97126ed19f2fSJacob Faibussowitsch 97139566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97149566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 97159566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97166ed19f2fSJacob Faibussowitsch } 9717f108dbd7SJacob Faibussowitsch 9718f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9719f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9720f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9721f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9722f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9723addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9724addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9725addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9726f108dbd7SJacob Faibussowitsch } 9727addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9728addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9729addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9730f108dbd7SJacob Faibussowitsch 9731f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9732f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9733f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9734f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9735f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9736f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9737f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9738f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9739f108dbd7SJacob Faibussowitsch } 9740ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9741ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9742f108dbd7SJacob Faibussowitsch } 97439566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 97449566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9745f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 97466ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9747f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97489566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9749f108dbd7SJacob Faibussowitsch } 9750f108dbd7SJacob Faibussowitsch } 97519566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 97529566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 97539566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 97549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 97559566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 97569566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9757f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97589566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9759f108dbd7SJacob Faibussowitsch } 97609566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 9761cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&vwr)); 97629566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 97633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9764f108dbd7SJacob Faibussowitsch } 9765f108dbd7SJacob Faibussowitsch 9766d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 97671eb70e55SToby Isaac * interpolator construction */ 9768d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9769d71ae5a4SJacob Faibussowitsch { 97701eb70e55SToby Isaac PetscSection section, newSection, gsection; 97711eb70e55SToby Isaac PetscSF sf; 97721eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 97731eb70e55SToby Isaac 97741eb70e55SToby Isaac PetscFunctionBegin; 97751eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97764f572ea9SToby Isaac PetscAssertPointer(odm, 2); 97779566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 97789566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9779712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 97801eb70e55SToby Isaac if (!ghasConstraints) { 97819566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 97821eb70e55SToby Isaac *odm = dm; 97833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97841eb70e55SToby Isaac } 97859566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 97869566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 97879566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 97889566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 9789eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection)); 97909566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 97919566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 97923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97931eb70e55SToby Isaac } 97941eb70e55SToby Isaac 9795d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9796d71ae5a4SJacob Faibussowitsch { 97971eb70e55SToby Isaac DM dmco, dmfo; 97981eb70e55SToby Isaac Mat interpo; 97991eb70e55SToby Isaac Vec rscale; 98001eb70e55SToby Isaac Vec cglobalo, clocal; 98011eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 98021eb70e55SToby Isaac PetscBool regular; 98031eb70e55SToby Isaac 98041eb70e55SToby Isaac PetscFunctionBegin; 98059566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 98069566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 98079566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 98089566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 98099566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 98109566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 98119566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 98129566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 98139566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 98149566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 98159566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 98169566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 98179566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 98189566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 98199566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 98209566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 98219566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 98229566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 98239566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 98249566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 98259566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 98269566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 98279566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 98289566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 98291eb70e55SToby Isaac *shift = fglobal; 98309566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 98319566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 98329566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 98339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 98349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 98359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 98369566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 98379566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 98383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98391eb70e55SToby Isaac } 98401eb70e55SToby Isaac 9841d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9842d71ae5a4SJacob Faibussowitsch { 98431eb70e55SToby Isaac PetscObject shifto; 98441eb70e55SToby Isaac Vec shift; 98451eb70e55SToby Isaac 98461eb70e55SToby Isaac PetscFunctionBegin; 98471eb70e55SToby Isaac if (!interp) { 98481eb70e55SToby Isaac Vec rscale; 98491eb70e55SToby Isaac 98509566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 98519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 98521eb70e55SToby Isaac } else { 98539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 98541eb70e55SToby Isaac } 98559566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 98561eb70e55SToby Isaac if (!shifto) { 98579566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 98589566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 98591eb70e55SToby Isaac shifto = (PetscObject)shift; 98609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 98611eb70e55SToby Isaac } 98621eb70e55SToby Isaac shift = (Vec)shifto; 98639566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 98649566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 98659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 98663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98671eb70e55SToby Isaac } 98681eb70e55SToby Isaac 9869bceba477SMatthew G. Knepley /* Pointwise interpolation 9870bceba477SMatthew G. Knepley Just code FEM for now 9871bceba477SMatthew G. Knepley u^f = I u^c 98724ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 98734ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 98744ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9875bceba477SMatthew G. Knepley */ 9876d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9877d71ae5a4SJacob Faibussowitsch { 9878bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9879bceba477SMatthew G. Knepley PetscInt m, n; 9880a063dac3SMatthew G. Knepley void *ctx; 988168132eb9SMatthew G. Knepley DM cdm; 9882cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9883bceba477SMatthew G. Knepley 9884bceba477SMatthew G. Knepley PetscFunctionBegin; 98859566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 98869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 98879566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 98889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 988968132eb9SMatthew G. Knepley 98909566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 98919566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 98929566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 98939566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 98949566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 989568132eb9SMatthew G. Knepley 98969566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 98979566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 98989566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 98999566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 99009566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 99014db47ee9SStefano Zampini if (scaling) { 99025d1c2e58SMatthew G. Knepley /* Use naive scaling */ 99039566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 99044db47ee9SStefano Zampini } 99053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9906a063dac3SMatthew G. Knepley } 9907bceba477SMatthew G. Knepley 9908d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9909d71ae5a4SJacob Faibussowitsch { 99106dbf9973SLawrence Mitchell VecScatter ctx; 991190748bafSMatthew G. Knepley 9912a063dac3SMatthew G. Knepley PetscFunctionBegin; 99139566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 99149566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 99159566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 99163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9917bceba477SMatthew G. Knepley } 9918bceba477SMatthew G. Knepley 9919d71ae5a4SJacob Faibussowitsch static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9920d71ae5a4SJacob Faibussowitsch { 992100635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 992200635df3SMatthew G. Knepley PetscInt c; 992300635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 99243e9753d6SMatthew G. Knepley } 99253e9753d6SMatthew G. Knepley 9926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9927d71ae5a4SJacob Faibussowitsch { 9928b4937a87SMatthew G. Knepley DM dmc; 9929b4937a87SMatthew G. Knepley PetscDS ds; 9930b4937a87SMatthew G. Knepley Vec ones, locmass; 9931b4937a87SMatthew G. Knepley IS cellIS; 9932b4937a87SMatthew G. Knepley PetscFormKey key; 9933b4937a87SMatthew G. Knepley PetscInt depth; 9934b4937a87SMatthew G. Knepley 9935b4937a87SMatthew G. Knepley PetscFunctionBegin; 99369566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 99379566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 99389566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 99399566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 99409566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 99419566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 99429566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 99439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 99449566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 99459566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 99469566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9947b4937a87SMatthew G. Knepley key.label = NULL; 9948b4937a87SMatthew G. Knepley key.value = 0; 9949b4937a87SMatthew G. Knepley key.field = 0; 9950b4937a87SMatthew G. Knepley key.part = 0; 99519566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 99529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 99539566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 99549566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 99559566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 99569566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 99579566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 99589566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 99593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9960b4937a87SMatthew G. Knepley } 9961b4937a87SMatthew G. Knepley 9962d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9963d71ae5a4SJacob Faibussowitsch { 9964bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9965bd041c0cSMatthew G. Knepley PetscInt m, n; 9966bd041c0cSMatthew G. Knepley void *ctx; 9967bd041c0cSMatthew G. Knepley DM cdm; 9968bd041c0cSMatthew G. Knepley PetscBool regular; 9969bd041c0cSMatthew G. Knepley 9970bd041c0cSMatthew G. Knepley PetscFunctionBegin; 99713e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 99723e9753d6SMatthew G. Knepley DM dmc; 99733e9753d6SMatthew G. Knepley PetscDS ds; 9974b4937a87SMatthew G. Knepley PetscWeakForm wf; 99753e9753d6SMatthew G. Knepley Vec u; 99763e9753d6SMatthew G. Knepley IS cellIS; 997706ad1575SMatthew G. Knepley PetscFormKey key; 99783e9753d6SMatthew G. Knepley PetscInt depth; 99793e9753d6SMatthew G. Knepley 99809566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 99819566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 99829566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 99839566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 99849566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 99859566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 99869566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 99878d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 99889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 99899566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 99909566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 99916528b96dSMatthew G. Knepley key.label = NULL; 99926528b96dSMatthew G. Knepley key.value = 0; 99936528b96dSMatthew G. Knepley key.field = 0; 999406ad1575SMatthew G. Knepley key.part = 0; 99959566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 99969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 99978d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 99989566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 99993e9753d6SMatthew G. Knepley } else { 100009566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 100019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 100029566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 100039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 10004bd041c0cSMatthew G. Knepley 100059566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 100069566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 100079566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 100089566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 10009bd041c0cSMatthew G. Knepley 100109566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 100119566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 100129566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 100139566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 100143e9753d6SMatthew G. Knepley } 100159566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 100163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10017bd041c0cSMatthew G. Knepley } 10018bd041c0cSMatthew G. Knepley 100190aef6b92SMatthew G. Knepley /*@ 100200aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100210aef6b92SMatthew G. Knepley 100220aef6b92SMatthew G. Knepley Input Parameter: 10023a1cb98faSBarry Smith . dm - The `DMPLEX` object 100240aef6b92SMatthew G. Knepley 100250aef6b92SMatthew G. Knepley Output Parameter: 100260aef6b92SMatthew G. Knepley . regular - The flag 100270aef6b92SMatthew G. Knepley 100280aef6b92SMatthew G. Knepley Level: intermediate 100290aef6b92SMatthew G. Knepley 100301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 100310aef6b92SMatthew G. Knepley @*/ 10032d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10033d71ae5a4SJacob Faibussowitsch { 100340aef6b92SMatthew G. Knepley PetscFunctionBegin; 100350aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100364f572ea9SToby Isaac PetscAssertPointer(regular, 2); 100370aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 100383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100390aef6b92SMatthew G. Knepley } 100400aef6b92SMatthew G. Knepley 100410aef6b92SMatthew G. Knepley /*@ 100420aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100430aef6b92SMatthew G. Knepley 100440aef6b92SMatthew G. Knepley Input Parameters: 10045a1cb98faSBarry Smith + dm - The `DMPLEX` object 100460aef6b92SMatthew G. Knepley - regular - The flag 100470aef6b92SMatthew G. Knepley 100480aef6b92SMatthew G. Knepley Level: intermediate 100490aef6b92SMatthew G. Knepley 100501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 100510aef6b92SMatthew G. Knepley @*/ 10052d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10053d71ae5a4SJacob Faibussowitsch { 100540aef6b92SMatthew G. Knepley PetscFunctionBegin; 100550aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100560aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 100573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100580aef6b92SMatthew G. Knepley } 100590aef6b92SMatthew G. Knepley 10060a68b90caSToby Isaac /*@ 10061f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10062a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10063a68b90caSToby Isaac 10064a1cb98faSBarry Smith Not Collective 10065a68b90caSToby Isaac 10066f899ff85SJose E. Roman Input Parameter: 10067a1cb98faSBarry Smith . dm - The `DMPLEX` object 10068a68b90caSToby Isaac 10069a68b90caSToby Isaac Output Parameters: 1007020f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1007120f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10072a68b90caSToby Isaac 10073a68b90caSToby Isaac Level: intermediate 10074a68b90caSToby Isaac 100751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10076a68b90caSToby Isaac @*/ 10077d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 10078d71ae5a4SJacob Faibussowitsch { 10079a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10080a68b90caSToby Isaac 10081a68b90caSToby Isaac PetscFunctionBegin; 10082a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100839566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10084a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10085a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 100863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10087a68b90caSToby Isaac } 10088a68b90caSToby Isaac 10089a68b90caSToby Isaac /*@ 10090a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10091a68b90caSToby Isaac 1009220f4b53cSBarry Smith Collective 10093a68b90caSToby Isaac 10094a68b90caSToby Isaac Input Parameters: 10095a1cb98faSBarry Smith + dm - The `DMPLEX` object 10096a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10097a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10098a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10099a68b90caSToby Isaac 10100a68b90caSToby Isaac Level: intermediate 10101a68b90caSToby Isaac 10102a1cb98faSBarry Smith Notes: 10103a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10104a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10105a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10106a4e35b19SJacob Faibussowitsch 10107a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10108a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10109a1cb98faSBarry Smith 1011020f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10111a1cb98faSBarry Smith 101121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10113a68b90caSToby Isaac @*/ 10114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10115d71ae5a4SJacob Faibussowitsch { 10116a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10117e228b242SToby Isaac PetscMPIInt result; 10118a68b90caSToby Isaac 10119a68b90caSToby Isaac PetscFunctionBegin; 10120a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10121e228b242SToby Isaac if (anchorSection) { 10122e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 101239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 101241dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10125e228b242SToby Isaac } 10126e228b242SToby Isaac if (anchorIS) { 10127e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 101289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 101291dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10130e228b242SToby Isaac } 10131a68b90caSToby Isaac 101329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 101339566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10134a68b90caSToby Isaac plex->anchorSection = anchorSection; 10135a68b90caSToby Isaac 101369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 101379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10138a68b90caSToby Isaac plex->anchorIS = anchorIS; 10139a68b90caSToby Isaac 10140cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10141a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10142a68b90caSToby Isaac const PetscInt *anchors; 10143a68b90caSToby Isaac 101449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 101459566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 101469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10147a68b90caSToby Isaac for (a = 0; a < size; a++) { 10148a68b90caSToby Isaac PetscInt p; 10149a68b90caSToby Isaac 10150a68b90caSToby Isaac p = anchors[a]; 10151a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10152a68b90caSToby Isaac PetscInt dof; 10153a68b90caSToby Isaac 101549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10155a68b90caSToby Isaac if (dof) { 101569566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1015763a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10158a68b90caSToby Isaac } 10159a68b90caSToby Isaac } 10160a68b90caSToby Isaac } 101619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10162a68b90caSToby Isaac } 10163f7c74593SToby Isaac /* reset the generic constraints */ 101649566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 101653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10166a68b90caSToby Isaac } 10167a68b90caSToby Isaac 10168d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10169d71ae5a4SJacob Faibussowitsch { 10170f7c74593SToby Isaac PetscSection anchorSection; 101716995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10172a68b90caSToby Isaac 10173a68b90caSToby Isaac PetscFunctionBegin; 10174a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101759566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 101769566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 101779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 101786995de1eSToby Isaac if (numFields) { 10179719ab38cSToby Isaac PetscInt f; 101809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10181719ab38cSToby Isaac 10182719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10183719ab38cSToby Isaac PetscInt numComp; 10184719ab38cSToby Isaac 101859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 101869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10187719ab38cSToby Isaac } 101886995de1eSToby Isaac } 101899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 101909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 101916995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 101926995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 101936995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 101949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10195a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 101969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10197a68b90caSToby Isaac if (dof) { 101989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 101999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10200a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 102019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 102029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10203a68b90caSToby Isaac } 10204a68b90caSToby Isaac } 10205a68b90caSToby Isaac } 102069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 102079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 102083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10209a68b90caSToby Isaac } 10210a68b90caSToby Isaac 10211d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10212d71ae5a4SJacob Faibussowitsch { 10213f7c74593SToby Isaac PetscSection aSec; 10214ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 102150ac89760SToby Isaac const PetscInt *anchors; 102160ac89760SToby Isaac PetscInt numFields, f; 1021766ad2231SToby Isaac IS aIS; 10218e19f7ee6SMark Adams MatType mtype; 10219e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 102200ac89760SToby Isaac 102210ac89760SToby Isaac PetscFunctionBegin; 102220ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 102249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 102259566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 102269566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 102279566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 102289566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 102299566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 102309566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10231e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10232e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10233e19f7ee6SMark Adams else mtype = MATSEQAIJ; 102349566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 102359566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 102369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 102376995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 102389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 102399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 102409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 102410ac89760SToby Isaac i[0] = 0; 102429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 102430ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10244f19733c5SToby Isaac PetscInt rDof, rOff, r; 10245f19733c5SToby Isaac 102469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10247f19733c5SToby Isaac if (!rDof) continue; 102489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102490ac89760SToby Isaac if (numFields) { 102500ac89760SToby Isaac for (f = 0; f < numFields; f++) { 102510ac89760SToby Isaac annz = 0; 10252f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10253f19733c5SToby Isaac a = anchors[rOff + r]; 10254ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 102560ac89760SToby Isaac annz += aDof; 102570ac89760SToby Isaac } 102589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 102599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10260ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 102610ac89760SToby Isaac } 102622f7452b8SBarry Smith } else { 102630ac89760SToby Isaac annz = 0; 102649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102650ac89760SToby Isaac for (q = 0; q < dof; q++) { 10266ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10267ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 102690ac89760SToby Isaac annz += aDof; 102700ac89760SToby Isaac } 102719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10273ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 102740ac89760SToby Isaac } 102750ac89760SToby Isaac } 102760ac89760SToby Isaac nnz = i[m]; 102779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 102780ac89760SToby Isaac offset = 0; 102790ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 102800ac89760SToby Isaac if (numFields) { 102810ac89760SToby Isaac for (f = 0; f < numFields; f++) { 102829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 102830ac89760SToby Isaac for (q = 0; q < dof; q++) { 102840ac89760SToby Isaac PetscInt rDof, rOff, r; 102859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 102869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102870ac89760SToby Isaac for (r = 0; r < rDof; r++) { 102880ac89760SToby Isaac PetscInt s; 102890ac89760SToby Isaac 102900ac89760SToby Isaac a = anchors[rOff + r]; 10291ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 102939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10294ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 102950ac89760SToby Isaac } 102960ac89760SToby Isaac } 102970ac89760SToby Isaac } 102982f7452b8SBarry Smith } else { 102999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103000ac89760SToby Isaac for (q = 0; q < dof; q++) { 103010ac89760SToby Isaac PetscInt rDof, rOff, r; 103029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 103039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103040ac89760SToby Isaac for (r = 0; r < rDof; r++) { 103050ac89760SToby Isaac PetscInt s; 103060ac89760SToby Isaac 103070ac89760SToby Isaac a = anchors[rOff + r]; 10308ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 103109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10311ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 103120ac89760SToby Isaac } 103130ac89760SToby Isaac } 103140ac89760SToby Isaac } 103150ac89760SToby Isaac } 103169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 103179566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 103189566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 103199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 103203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103210ac89760SToby Isaac } 103220ac89760SToby Isaac 10323d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10324d71ae5a4SJacob Faibussowitsch { 10325f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10326f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1032766ad2231SToby Isaac Mat cMat; 1032866ad2231SToby Isaac 1032966ad2231SToby Isaac PetscFunctionBegin; 1033066ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 103319566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1033266ad2231SToby Isaac if (anchorSection) { 1033344a7f3ddSMatthew G. Knepley PetscInt Nf; 10334e228b242SToby Isaac 103359566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 103369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 103379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 103389566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 103399566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 103409566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 103419566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 103429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1034366ad2231SToby Isaac } 103443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1034566ad2231SToby Isaac } 10346a93c429eSMatthew G. Knepley 10347d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10348d71ae5a4SJacob Faibussowitsch { 10349a93c429eSMatthew G. Knepley IS subis; 10350a93c429eSMatthew G. Knepley PetscSection section, subsection; 10351a93c429eSMatthew G. Knepley 10352a93c429eSMatthew G. Knepley PetscFunctionBegin; 103539566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1035428b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1035528b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10356a93c429eSMatthew G. Knepley /* Create subdomain */ 103579566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 10358a93c429eSMatthew G. Knepley /* Create submodel */ 103599566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 103609566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 103619566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 103629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 103639566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10364a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10365a93c429eSMatthew G. Knepley if (is) { 10366a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10367a93c429eSMatthew G. Knepley IS spIS; 10368a93c429eSMatthew G. Knepley const PetscInt *spmap; 10369a93c429eSMatthew G. Knepley PetscInt *subIndices; 10370a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10371a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10372a93c429eSMatthew G. Knepley 103739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 103749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 103759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 103769566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 103779566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 103789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10379a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10380a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10381a93c429eSMatthew G. Knepley 103829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10383a93c429eSMatthew G. Knepley if (gdof > 0) { 10384a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10385a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10386a93c429eSMatthew G. Knepley 103879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 103889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10389a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10390a93c429eSMatthew G. Knepley } 10391a93c429eSMatthew G. Knepley subSize += pSubSize; 10392a93c429eSMatthew G. Knepley if (pSubSize) { 10393a93c429eSMatthew G. Knepley if (bs < 0) { 10394a93c429eSMatthew G. Knepley bs = pSubSize; 10395a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10396a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10397a93c429eSMatthew G. Knepley bs = 1; 10398a93c429eSMatthew G. Knepley } 10399a93c429eSMatthew G. Knepley } 10400a93c429eSMatthew G. Knepley } 10401a93c429eSMatthew G. Knepley } 10402a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 104039371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 104049371c9d4SSatish Balay bsLocal[1] = bs; 104059566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 104069371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 104079371c9d4SSatish Balay bs = 1; 104089371c9d4SSatish Balay } else { 104099371c9d4SSatish Balay bs = bsMinMax[0]; 104109371c9d4SSatish Balay } 104119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10412a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10413a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10414a93c429eSMatthew G. Knepley 104159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10416a93c429eSMatthew G. Knepley if (gdof > 0) { 10417a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10418a93c429eSMatthew G. Knepley 104199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10420a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10421a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10422a93c429eSMatthew G. Knepley 10423a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10424a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 104259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 104269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10427a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10428a93c429eSMatthew G. Knepley } 104299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 104309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10431ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10432a93c429eSMatthew G. Knepley } 10433a93c429eSMatthew G. Knepley } 10434a93c429eSMatthew G. Knepley } 104359566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 104369566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10437a93c429eSMatthew G. Knepley if (bs > 1) { 10438a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10439a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10440a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10441a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 104429371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 104439371c9d4SSatish Balay set = 0; 104449371c9d4SSatish Balay break; 104459371c9d4SSatish Balay } 10446a93c429eSMatthew G. Knepley } 10447a93c429eSMatthew G. Knepley } 104489566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10449a93c429eSMatthew G. Knepley } 10450a93c429eSMatthew G. Knepley /* Attach nullspace */ 10451a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10452a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10453a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10454a93c429eSMatthew G. Knepley } 10455a93c429eSMatthew G. Knepley if (f < Nf) { 10456a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 104579566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 104586823f3c5SBlaise Bourdin 104599566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 104609566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10461a93c429eSMatthew G. Knepley } 10462a93c429eSMatthew G. Knepley } 104633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10464a93c429eSMatthew G. Knepley } 10465c0f0dcc3SMatthew G. Knepley 10466c0f0dcc3SMatthew G. Knepley /*@ 10467c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10468c0f0dcc3SMatthew G. Knepley 10469a1cb98faSBarry Smith Input Parameters: 10470a1cb98faSBarry Smith + dm - The `DM` 10471a1cb98faSBarry Smith - dummy - unused argument 10472a1cb98faSBarry Smith 10473a1cb98faSBarry Smith Options Database Key: 10474a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10475c0f0dcc3SMatthew G. Knepley 10476c0f0dcc3SMatthew G. Knepley Level: developer 10477c0f0dcc3SMatthew G. Knepley 104781cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10479c0f0dcc3SMatthew G. Knepley @*/ 10480d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10481d71ae5a4SJacob Faibussowitsch { 10482b665b14eSToby Isaac PetscLogHandler default_handler; 10483b665b14eSToby Isaac 104842611ad71SToby Isaac PetscFunctionBegin; 104852611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10486b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10487b665b14eSToby Isaac if (default_handler) { 10488c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10489c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10490c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10491c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10492c0f0dcc3SMatthew G. Knepley const char *name; 10493c0f0dcc3SMatthew G. Knepley 104949566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 104959566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 104969566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 104979566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10498b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10499c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10500c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10501c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1050263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DM (%s) FE Residual Integration: %" PetscInt_FMT " integrals %d reps\n Cell rate: %.2g/s flop rate: %.2g MF/s\n", name ? name : "unknown", N, eventInfo.count, (double)cellRate, (double)(flopRate / 1.e6))); 105032611ad71SToby Isaac } else { 10504b665b14eSToby Isaac SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off or the default log handler is not running. Reconfigure using --with-log and run with -log_view."); 105052611ad71SToby Isaac } 105063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10507c0f0dcc3SMatthew G. Knepley } 10508