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> 11c789d87fSToby 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: 2433dc9a610eSPierre Jolivet 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)); 2801*32b27637SMatthew G. Knepley if (dof > 0) { 2802d02c7345SMatthew G. Knepley for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof; 2803d02c7345SMatthew G. Knepley // Signal block concatenation 2804d02c7345SMatthew G. Knepley if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof); 2805*32b27637SMatthew G. Knepley } 28061d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 28071d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 28081d17a0a3SMatthew G. Knepley if (dof) { 28099371c9d4SSatish Balay if (bs < 0) { 28109371c9d4SSatish Balay bs = bdof; 28119371c9d4SSatish Balay } else if (bs != bdof) { 28129371c9d4SSatish Balay bs = 1; 28139371c9d4SSatish Balay } 2814552f7358SJed Brown } 2815863027abSJed Brown } break; 2816863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2817863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2818863027abSJed Brown PetscInt num_comp, bdof, offset; 2819863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2820863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2821863027abSJed Brown if (dof < 0) continue; 2822863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2823863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2824863027abSJed 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); 2825863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2826863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2827863027abSJed Brown // Handle possibly constant block size (unlikely) 2828863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2829863027abSJed Brown if (dof) { 2830863027abSJed Brown if (bs < 0) { 2831863027abSJed Brown bs = bdof; 2832863027abSJed Brown } else if (bs != bdof) { 2833863027abSJed Brown bs = 1; 2834863027abSJed Brown } 2835863027abSJed Brown } 2836863027abSJed Brown } 2837863027abSJed Brown } break; 2838863027abSJed Brown } 28392a28c762SMatthew G Knepley } 28402a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2841e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2842e432b41dSStefano Zampini bsLocal[1] = bs; 28439566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2844e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2845e432b41dSStefano Zampini else bs = bsMinMax[0]; 28466fd5c86aSStefano Zampini bs = PetscMax(1, bs); 28479566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 28480682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 28499566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 28509566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 28510682b8bbSJed Brown } else { 28529566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 28539566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 28549566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2855552f7358SJed Brown } 2856*32b27637SMatthew G. Knepley if (pblocks) { // Consolidate blocks 28579fca9976SJed Brown PetscInt nblocks = 0; 2858*32b27637SMatthew G. Knepley pblocks[0] = PetscAbs(pblocks[0]); 28599fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 28609fca9976SJed Brown if (pblocks[i] == 0) continue; 2861d02c7345SMatthew G. Knepley // Negative block size indicates the blocks should be concatenated 2862d02c7345SMatthew G. Knepley if (pblocks[i] < 0) { 2863d02c7345SMatthew G. Knepley pblocks[i] = -pblocks[i]; 2864d02c7345SMatthew G. Knepley pblocks[nblocks - 1] += pblocks[i]; 2865d02c7345SMatthew G. Knepley } else { 28669fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2867d02c7345SMatthew G. Knepley } 2868ad540459SPierre 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]); 28699fca9976SJed Brown } 28709fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 28719fca9976SJed Brown } 28729fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2873aa0f6e3cSJed Brown } 28749566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 28753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2876552f7358SJed Brown } 2877552f7358SJed Brown 28787cd05799SMatthew G. Knepley /*@ 2879a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2880be36d101SStefano Zampini 2881a1cb98faSBarry Smith Not Collective 2882be36d101SStefano Zampini 2883be36d101SStefano Zampini Input Parameter: 288460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2885be36d101SStefano Zampini 28862fe279fdSBarry Smith Output Parameter: 2887be36d101SStefano Zampini . subsection - The subdomain section 2888be36d101SStefano Zampini 2889be36d101SStefano Zampini Level: developer 2890be36d101SStefano Zampini 28911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 28927cd05799SMatthew G. Knepley @*/ 2893d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2894d71ae5a4SJacob Faibussowitsch { 2895be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2896be36d101SStefano Zampini 2897be36d101SStefano Zampini PetscFunctionBegin; 2898be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2899be36d101SStefano Zampini if (!mesh->subdomainSection) { 2900be36d101SStefano Zampini PetscSection section; 2901be36d101SStefano Zampini PetscSF sf; 2902be36d101SStefano Zampini 29039566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 29049566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 2905eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 29069566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2907be36d101SStefano Zampini } 2908be36d101SStefano Zampini *subsection = mesh->subdomainSection; 29093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2910be36d101SStefano Zampini } 2911be36d101SStefano Zampini 2912552f7358SJed Brown /*@ 291320f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2914552f7358SJed Brown 2915a1cb98faSBarry Smith Not Collective 2916552f7358SJed Brown 2917552f7358SJed Brown Input Parameter: 291860225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2919552f7358SJed Brown 2920552f7358SJed Brown Output Parameters: 2921552f7358SJed Brown + pStart - The first mesh point 2922552f7358SJed Brown - pEnd - The upper bound for mesh points 2923552f7358SJed Brown 2924552f7358SJed Brown Level: beginner 2925552f7358SJed Brown 29261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2927552f7358SJed Brown @*/ 2928d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2929d71ae5a4SJacob Faibussowitsch { 2930552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2931552f7358SJed Brown 2932552f7358SJed Brown PetscFunctionBegin; 2933552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29349f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 29359f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 29363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2937552f7358SJed Brown } 2938552f7358SJed Brown 2939552f7358SJed Brown /*@ 294020f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 2941552f7358SJed Brown 2942a1cb98faSBarry Smith Not Collective 2943552f7358SJed Brown 2944552f7358SJed Brown Input Parameters: 294560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2946552f7358SJed Brown . pStart - The first mesh point 2947552f7358SJed Brown - pEnd - The upper bound for mesh points 2948552f7358SJed Brown 2949552f7358SJed Brown Level: beginner 2950552f7358SJed Brown 29511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2952552f7358SJed Brown @*/ 2953d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2954d71ae5a4SJacob Faibussowitsch { 2955552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2956552f7358SJed Brown 2957552f7358SJed Brown PetscFunctionBegin; 2958552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 29609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 296121027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 29623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2963552f7358SJed Brown } 2964552f7358SJed Brown 2965552f7358SJed Brown /*@ 2966eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2967552f7358SJed Brown 2968a1cb98faSBarry Smith Not Collective 2969552f7358SJed Brown 2970552f7358SJed Brown Input Parameters: 297160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2972a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2973552f7358SJed Brown 2974552f7358SJed Brown Output Parameter: 297520f4b53cSBarry Smith . size - The cone size for point `p` 2976552f7358SJed Brown 2977552f7358SJed Brown Level: beginner 2978552f7358SJed Brown 29791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2980552f7358SJed Brown @*/ 2981d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2982d71ae5a4SJacob Faibussowitsch { 2983552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2984552f7358SJed Brown 2985552f7358SJed Brown PetscFunctionBegin; 2986552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29874f572ea9SToby Isaac PetscAssertPointer(size, 3); 29889f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 29899f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 29903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2991552f7358SJed Brown } 2992552f7358SJed Brown 2993552f7358SJed Brown /*@ 2994eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2995552f7358SJed Brown 2996a1cb98faSBarry Smith Not Collective 2997552f7358SJed Brown 2998552f7358SJed Brown Input Parameters: 299960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3000a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 300120f4b53cSBarry Smith - size - The cone size for point `p` 3002552f7358SJed Brown 3003552f7358SJed Brown Level: beginner 3004552f7358SJed Brown 3005a1cb98faSBarry Smith Note: 3006a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 3007a1cb98faSBarry Smith 30081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 3009552f7358SJed Brown @*/ 3010d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 3011d71ae5a4SJacob Faibussowitsch { 3012552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3013552f7358SJed Brown 3014552f7358SJed Brown PetscFunctionBegin; 3015552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30169f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 30179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 30183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3019552f7358SJed Brown } 3020552f7358SJed Brown 3021552f7358SJed Brown /*@C 3022eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 3023552f7358SJed Brown 3024a1cb98faSBarry Smith Not Collective 3025552f7358SJed Brown 3026552f7358SJed Brown Input Parameters: 3027a1cb98faSBarry Smith + dm - The `DMPLEX` 3028a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3029552f7358SJed Brown 3030552f7358SJed Brown Output Parameter: 303120f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p` 3032552f7358SJed Brown 3033552f7358SJed Brown Level: beginner 3034552f7358SJed Brown 303560225df5SJacob Faibussowitsch Fortran Notes: 3036a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 3037a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 30383813dfbdSMatthew G Knepley 30391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3040552f7358SJed Brown @*/ 3041d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3042d71ae5a4SJacob Faibussowitsch { 3043552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3044552f7358SJed Brown PetscInt off; 3045552f7358SJed Brown 3046552f7358SJed Brown PetscFunctionBegin; 3047552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30484f572ea9SToby Isaac PetscAssertPointer(cone, 3); 30499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30508e3a54c0SPierre Jolivet *cone = PetscSafePointerPlusOffset(mesh->cones, off); 30513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3052552f7358SJed Brown } 3053552f7358SJed Brown 30540ce7577fSVaclav Hapla /*@C 30550ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 30560ce7577fSVaclav Hapla 3057a1cb98faSBarry Smith Not Collective 30580ce7577fSVaclav Hapla 30590ce7577fSVaclav Hapla Input Parameters: 3060a1cb98faSBarry Smith + dm - The `DMPLEX` 3061a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 30620ce7577fSVaclav Hapla 3063d8d19677SJose E. Roman Output Parameters: 306420f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 306520f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p` 30660ce7577fSVaclav Hapla 30670ce7577fSVaclav Hapla Level: intermediate 30680ce7577fSVaclav Hapla 30691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 30700ce7577fSVaclav Hapla @*/ 3071d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 3072d71ae5a4SJacob Faibussowitsch { 30730ce7577fSVaclav Hapla PetscSection cs, newcs; 30740ce7577fSVaclav Hapla PetscInt *cones; 30750ce7577fSVaclav Hapla PetscInt *newarr = NULL; 30760ce7577fSVaclav Hapla PetscInt n; 30770ce7577fSVaclav Hapla 30780ce7577fSVaclav Hapla PetscFunctionBegin; 30799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 30809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 30819566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 30820ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 30830ce7577fSVaclav Hapla if (pCones) { 30849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 30859566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 30860ce7577fSVaclav Hapla } 30873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30880ce7577fSVaclav Hapla } 30890ce7577fSVaclav Hapla 3090af9eab45SVaclav Hapla /*@ 3091af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3092d4636a37SVaclav Hapla 3093a1cb98faSBarry Smith Not Collective 3094d4636a37SVaclav Hapla 3095d4636a37SVaclav Hapla Input Parameters: 3096a1cb98faSBarry Smith + dm - The `DMPLEX` 3097a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3098d4636a37SVaclav Hapla 3099d4636a37SVaclav Hapla Output Parameter: 3100af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 3101d4636a37SVaclav Hapla 3102d4636a37SVaclav Hapla Level: advanced 3103d4636a37SVaclav Hapla 3104af9eab45SVaclav Hapla Notes: 310520f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3106af9eab45SVaclav Hapla 3107a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3108a1cb98faSBarry Smith 31091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3110a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3111d4636a37SVaclav Hapla @*/ 3112d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3113d71ae5a4SJacob Faibussowitsch { 3114af9eab45SVaclav Hapla IS *expandedPointsAll; 3115af9eab45SVaclav Hapla PetscInt depth; 3116d4636a37SVaclav Hapla 3117d4636a37SVaclav Hapla PetscFunctionBegin; 3118af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3119af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31204f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 31219566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3122af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 31239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 31249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 31253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3126af9eab45SVaclav Hapla } 3127af9eab45SVaclav Hapla 3128af9eab45SVaclav Hapla /*@ 3129af9eab45SVaclav 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). 3130af9eab45SVaclav Hapla 3131a1cb98faSBarry Smith Not Collective 3132af9eab45SVaclav Hapla 3133af9eab45SVaclav Hapla Input Parameters: 3134a1cb98faSBarry Smith + dm - The `DMPLEX` 3135a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3136af9eab45SVaclav Hapla 3137d8d19677SJose E. Roman Output Parameters: 3138a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3139af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3140af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3141af9eab45SVaclav Hapla 3142af9eab45SVaclav Hapla Level: advanced 3143af9eab45SVaclav Hapla 3144af9eab45SVaclav Hapla Notes: 3145a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3146af9eab45SVaclav Hapla 3147a4e35b19SJacob 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. 3148af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3149af9eab45SVaclav Hapla 3150a4e35b19SJacob 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\: 3151a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3152a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3153af9eab45SVaclav Hapla 31541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3155a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3156af9eab45SVaclav Hapla @*/ 3157d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3158d71ae5a4SJacob Faibussowitsch { 3159af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3160af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3161af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3162af9eab45SVaclav Hapla IS *expandedPoints_; 3163af9eab45SVaclav Hapla PetscSection *sections_; 3164af9eab45SVaclav Hapla 3165af9eab45SVaclav Hapla PetscFunctionBegin; 3166af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3167af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31684f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 31694f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 31704f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 31719566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 31729566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 31739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 31749566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 31759566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3176af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3177af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 31789566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 31799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3180af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31819566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3182af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 31839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 31849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3185af9eab45SVaclav Hapla } else { 31869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3187af9eab45SVaclav Hapla } 3188af9eab45SVaclav Hapla } 31899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 31909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 31919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3192af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 31949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3195af9eab45SVaclav Hapla if (cn > 1) { 31969566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 31979566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3198af9eab45SVaclav Hapla } else { 3199af9eab45SVaclav Hapla newarr[co] = arr[i]; 3200af9eab45SVaclav Hapla } 3201af9eab45SVaclav Hapla } 32029566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3203af9eab45SVaclav Hapla arr = newarr; 3204af9eab45SVaclav Hapla n = newn; 3205af9eab45SVaclav Hapla } 32069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3207af9eab45SVaclav Hapla *depth = depth_; 3208af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3209af9eab45SVaclav Hapla else { 32109566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 32119566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3212af9eab45SVaclav Hapla } 3213af9eab45SVaclav Hapla if (sections) *sections = sections_; 3214af9eab45SVaclav Hapla else { 32159566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 32169566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3217af9eab45SVaclav Hapla } 32183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3219af9eab45SVaclav Hapla } 3220af9eab45SVaclav Hapla 3221af9eab45SVaclav Hapla /*@ 3222a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3223af9eab45SVaclav Hapla 3224a1cb98faSBarry Smith Not Collective 3225af9eab45SVaclav Hapla 3226af9eab45SVaclav Hapla Input Parameters: 3227a1cb98faSBarry Smith + dm - The `DMPLEX` 3228a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3229af9eab45SVaclav Hapla 3230d8d19677SJose E. Roman Output Parameters: 3231a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3232af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3233af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3234af9eab45SVaclav Hapla 3235af9eab45SVaclav Hapla Level: advanced 3236af9eab45SVaclav Hapla 3237a1cb98faSBarry Smith Note: 3238a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3239af9eab45SVaclav Hapla 32401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3241a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3242af9eab45SVaclav Hapla @*/ 3243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3244d71ae5a4SJacob Faibussowitsch { 3245af9eab45SVaclav Hapla PetscInt d, depth_; 3246af9eab45SVaclav Hapla 3247af9eab45SVaclav Hapla PetscFunctionBegin; 32489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 32491dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3250af9eab45SVaclav Hapla if (depth) *depth = 0; 3251af9eab45SVaclav Hapla if (expandedPoints) { 32529566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 32539566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3254af9eab45SVaclav Hapla } 3255af9eab45SVaclav Hapla if (sections) { 32569566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 32579566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3258af9eab45SVaclav Hapla } 32593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3260d4636a37SVaclav Hapla } 3261d4636a37SVaclav Hapla 3262552f7358SJed Brown /*@ 326392371b87SBarry 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 3264552f7358SJed Brown 3265a1cb98faSBarry Smith Not Collective 3266552f7358SJed Brown 3267552f7358SJed Brown Input Parameters: 326860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3269a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 327020f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p` 3271552f7358SJed Brown 3272552f7358SJed Brown Level: beginner 3273552f7358SJed Brown 3274a1cb98faSBarry Smith Note: 3275a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3276a1cb98faSBarry Smith 32771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3278552f7358SJed Brown @*/ 3279d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3280d71ae5a4SJacob Faibussowitsch { 3281552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3282552f7358SJed Brown PetscInt dof, off, c; 3283552f7358SJed Brown 3284552f7358SJed Brown PetscFunctionBegin; 3285552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32874f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 32889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3289db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3290db485b19SStefano Zampini PetscInt pStart, pEnd; 3291db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 329263a3b9bcSJacob 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); 3293552f7358SJed Brown for (c = 0; c < dof; ++c) { 329463a3b9bcSJacob 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); 3295552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3296552f7358SJed Brown } 3297db485b19SStefano Zampini } else { 3298db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3299db485b19SStefano Zampini } 33003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3301552f7358SJed Brown } 3302552f7358SJed Brown 3303552f7358SJed Brown /*@C 3304eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3305552f7358SJed Brown 3306a1cb98faSBarry Smith Not Collective 3307552f7358SJed Brown 3308552f7358SJed Brown Input Parameters: 330960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3310a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3311552f7358SJed Brown 3312552f7358SJed Brown Output Parameter: 331320f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 3314b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3315552f7358SJed Brown 3316552f7358SJed Brown Level: beginner 3317552f7358SJed Brown 3318a1cb98faSBarry Smith Note: 3319b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3320b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3321a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3322b5a892a1SMatthew G. Knepley with the identity. 3323b5a892a1SMatthew G. Knepley 332460225df5SJacob Faibussowitsch Fortran Notes: 3325a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3326a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 33273813dfbdSMatthew G Knepley 33281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3329552f7358SJed Brown @*/ 3330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3331d71ae5a4SJacob Faibussowitsch { 3332552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3333552f7358SJed Brown PetscInt off; 3334552f7358SJed Brown 3335552f7358SJed Brown PetscFunctionBegin; 3336552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 333776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3338552f7358SJed Brown PetscInt dof; 33399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33404f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3341552f7358SJed Brown } 33429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 33430d644c17SKarl Rupp 3344552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 33453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3346552f7358SJed Brown } 3347552f7358SJed Brown 3348552f7358SJed Brown /*@ 3349eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3350552f7358SJed Brown 3351a1cb98faSBarry Smith Not Collective 3352552f7358SJed Brown 3353552f7358SJed Brown Input Parameters: 335460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3355a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3356b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3357b5a892a1SMatthew G. Knepley 3358552f7358SJed Brown Level: beginner 3359552f7358SJed Brown 3360a1cb98faSBarry Smith Notes: 3361a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3362a1cb98faSBarry Smith 3363a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3364a1cb98faSBarry Smith 33651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3366552f7358SJed Brown @*/ 3367d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3368d71ae5a4SJacob Faibussowitsch { 3369552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3370552f7358SJed Brown PetscInt pStart, pEnd; 3371552f7358SJed Brown PetscInt dof, off, c; 3372552f7358SJed Brown 3373552f7358SJed Brown PetscFunctionBegin; 3374552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33764f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 33779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3378db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3379db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 338063a3b9bcSJacob 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); 3381552f7358SJed Brown for (c = 0; c < dof; ++c) { 3382552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3383552f7358SJed Brown 33849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 33851dca8a05SBarry 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); 3386552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3387552f7358SJed Brown } 3388db485b19SStefano Zampini } else { 3389db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3390db485b19SStefano Zampini } 33913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3392552f7358SJed Brown } 3393552f7358SJed Brown 33947cd05799SMatthew G. Knepley /*@ 3395eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 33967cd05799SMatthew G. Knepley 3397a1cb98faSBarry Smith Not Collective 33987cd05799SMatthew G. Knepley 33997cd05799SMatthew G. Knepley Input Parameters: 340060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3401a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34027cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34037cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 34047cd05799SMatthew G. Knepley 34057cd05799SMatthew G. Knepley Level: beginner 34067cd05799SMatthew G. Knepley 34071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34087cd05799SMatthew G. Knepley @*/ 3409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3410d71ae5a4SJacob Faibussowitsch { 3411552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3412552f7358SJed Brown PetscInt pStart, pEnd; 3413552f7358SJed Brown PetscInt dof, off; 3414552f7358SJed Brown 3415552f7358SJed Brown PetscFunctionBegin; 3416552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3417a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 341963a3b9bcSJacob 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); 342063a3b9bcSJacob 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); 34219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 342263a3b9bcSJacob 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); 3423a03d55ffSStefano Zampini } 3424a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3425552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 34263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3427552f7358SJed Brown } 3428552f7358SJed Brown 34297cd05799SMatthew G. Knepley /*@ 3430eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 34317cd05799SMatthew G. Knepley 3432a1cb98faSBarry Smith Not Collective 34337cd05799SMatthew G. Knepley 34347cd05799SMatthew G. Knepley Input Parameters: 343560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3436a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34377cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34387cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 34397cd05799SMatthew G. Knepley 34407cd05799SMatthew G. Knepley Level: beginner 34417cd05799SMatthew G. Knepley 3442a1cb98faSBarry Smith Note: 3443a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3444b5a892a1SMatthew G. Knepley 34451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34467cd05799SMatthew G. Knepley @*/ 3447d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3448d71ae5a4SJacob Faibussowitsch { 344977c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 345077c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 345177c88f5bSMatthew G Knepley PetscInt dof, off; 345277c88f5bSMatthew G Knepley 345377c88f5bSMatthew G Knepley PetscFunctionBegin; 345477c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3455a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 345763a3b9bcSJacob 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); 34589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 345963a3b9bcSJacob 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); 3460a03d55ffSStefano Zampini } 3461a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 346277c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 34633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 346477c88f5bSMatthew G Knepley } 346577c88f5bSMatthew G Knepley 34669f4ada15SMatthew G. Knepley /*@C 34679f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 34689f4ada15SMatthew G. Knepley 34699f4ada15SMatthew G. Knepley Not collective 34709f4ada15SMatthew G. Knepley 34719f4ada15SMatthew G. Knepley Input Parameters: 34729f4ada15SMatthew G. Knepley + dm - The DMPlex 34739f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 34749f4ada15SMatthew G. Knepley 34759f4ada15SMatthew G. Knepley Output Parameters: 347620f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 347720f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34789f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34799f4ada15SMatthew G. Knepley 34809f4ada15SMatthew G. Knepley Level: beginner 34819f4ada15SMatthew G. Knepley 34829f4ada15SMatthew G. Knepley Notes: 34839f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34849f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 348520f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 34869f4ada15SMatthew G. Knepley with the identity. 34879f4ada15SMatthew G. Knepley 34889f4ada15SMatthew G. Knepley Fortran Notes: 348920f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 349020f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 34919f4ada15SMatthew G. Knepley 34921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 34939f4ada15SMatthew G. Knepley @*/ 34949f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 34959f4ada15SMatthew G. Knepley { 34969f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 34979f4ada15SMatthew G. Knepley 34989f4ada15SMatthew G. Knepley PetscFunctionBegin; 34999f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35009f4ada15SMatthew G. Knepley if (mesh->tr) { 35019f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 35029f4ada15SMatthew G. Knepley } else { 35039f4ada15SMatthew G. Knepley PetscInt off; 35049f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 35059f4ada15SMatthew G. Knepley PetscInt dof; 35069f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35079f4ada15SMatthew G. Knepley if (dof) { 35084f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 35094f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 35109f4ada15SMatthew G. Knepley } 35119f4ada15SMatthew G. Knepley } 35129f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 35138e3a54c0SPierre Jolivet if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off); 35148e3a54c0SPierre Jolivet if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off); 35159f4ada15SMatthew G. Knepley } 35163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35179f4ada15SMatthew G. Knepley } 35189f4ada15SMatthew G. Knepley 35199f4ada15SMatthew G. Knepley /*@C 35209f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 35219f4ada15SMatthew G. Knepley 352220f4b53cSBarry Smith Not Collective 35239f4ada15SMatthew G. Knepley 35249f4ada15SMatthew G. Knepley Input Parameters: 35259f4ada15SMatthew G. Knepley + dm - The DMPlex 352620f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35279f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 352820f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 35299f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 35309f4ada15SMatthew G. Knepley 35319f4ada15SMatthew G. Knepley Level: beginner 35329f4ada15SMatthew G. Knepley 35339f4ada15SMatthew G. Knepley Notes: 35349f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 35359f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 353620f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 35379f4ada15SMatthew G. Knepley with the identity. 35389f4ada15SMatthew G. Knepley 353960225df5SJacob Faibussowitsch Fortran Notes: 354020f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 354120f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 35429f4ada15SMatthew G. Knepley 35431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 35449f4ada15SMatthew G. Knepley @*/ 35459f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 35469f4ada15SMatthew G. Knepley { 35479f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 35489f4ada15SMatthew G. Knepley 35499f4ada15SMatthew G. Knepley PetscFunctionBegin; 35509f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35519f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 35523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35539f4ada15SMatthew G. Knepley } 35549f4ada15SMatthew G. Knepley 3555552f7358SJed Brown /*@ 3556eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3557552f7358SJed Brown 3558a1cb98faSBarry Smith Not Collective 3559552f7358SJed Brown 3560552f7358SJed Brown Input Parameters: 356160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3562a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3563552f7358SJed Brown 3564552f7358SJed Brown Output Parameter: 356520f4b53cSBarry Smith . size - The support size for point `p` 3566552f7358SJed Brown 3567552f7358SJed Brown Level: beginner 3568552f7358SJed Brown 35691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3570552f7358SJed Brown @*/ 3571d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3572d71ae5a4SJacob Faibussowitsch { 3573552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3574552f7358SJed Brown 3575552f7358SJed Brown PetscFunctionBegin; 3576552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35774f572ea9SToby Isaac PetscAssertPointer(size, 3); 35789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 35793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3580552f7358SJed Brown } 3581552f7358SJed Brown 3582552f7358SJed Brown /*@ 3583eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3584552f7358SJed Brown 3585a1cb98faSBarry Smith Not Collective 3586552f7358SJed Brown 3587552f7358SJed Brown Input Parameters: 358860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3589a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 359020f4b53cSBarry Smith - size - The support size for point `p` 3591552f7358SJed Brown 3592a1cb98faSBarry Smith Level: beginner 3593552f7358SJed Brown 3594552f7358SJed Brown Note: 359520f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3596552f7358SJed Brown 35971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3598552f7358SJed Brown @*/ 3599d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3600d71ae5a4SJacob Faibussowitsch { 3601552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3602552f7358SJed Brown 3603552f7358SJed Brown PetscFunctionBegin; 3604552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 36063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3607552f7358SJed Brown } 3608552f7358SJed Brown 3609552f7358SJed Brown /*@C 3610eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3611552f7358SJed Brown 3612a1cb98faSBarry Smith Not Collective 3613552f7358SJed Brown 3614552f7358SJed Brown Input Parameters: 361560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3616a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3617552f7358SJed Brown 3618552f7358SJed Brown Output Parameter: 361920f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p` 3620552f7358SJed Brown 3621552f7358SJed Brown Level: beginner 3622552f7358SJed Brown 362360225df5SJacob Faibussowitsch Fortran Notes: 3624a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3625a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 36263813dfbdSMatthew G Knepley 36271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3628552f7358SJed Brown @*/ 3629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3630d71ae5a4SJacob Faibussowitsch { 3631552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3632552f7358SJed Brown PetscInt off; 3633552f7358SJed Brown 3634552f7358SJed Brown PetscFunctionBegin; 3635552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36364f572ea9SToby Isaac PetscAssertPointer(support, 3); 36379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 36388e3a54c0SPierre Jolivet *support = PetscSafePointerPlusOffset(mesh->supports, off); 36393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3640552f7358SJed Brown } 3641552f7358SJed Brown 3642552f7358SJed Brown /*@ 364392371b87SBarry 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 3644552f7358SJed Brown 3645a1cb98faSBarry Smith Not Collective 3646552f7358SJed Brown 3647552f7358SJed Brown Input Parameters: 364860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3649a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 365020f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p` 3651552f7358SJed Brown 3652552f7358SJed Brown Level: beginner 3653552f7358SJed Brown 3654a1cb98faSBarry Smith Note: 3655a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3656a1cb98faSBarry Smith 36571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3658552f7358SJed Brown @*/ 3659d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3660d71ae5a4SJacob Faibussowitsch { 3661552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3662552f7358SJed Brown PetscInt pStart, pEnd; 3663552f7358SJed Brown PetscInt dof, off, c; 3664552f7358SJed Brown 3665552f7358SJed Brown PetscFunctionBegin; 3666552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36694f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 36709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 367163a3b9bcSJacob 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); 3672552f7358SJed Brown for (c = 0; c < dof; ++c) { 367363a3b9bcSJacob 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); 3674552f7358SJed Brown mesh->supports[off + c] = support[c]; 3675552f7358SJed Brown } 36763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3677552f7358SJed Brown } 3678552f7358SJed Brown 36797cd05799SMatthew G. Knepley /*@ 3680eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 36817cd05799SMatthew G. Knepley 3682a1cb98faSBarry Smith Not Collective 36837cd05799SMatthew G. Knepley 36847cd05799SMatthew G. Knepley Input Parameters: 368560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3686a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36877cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 36887cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 36897cd05799SMatthew G. Knepley 36907cd05799SMatthew G. Knepley Level: beginner 36917cd05799SMatthew G. Knepley 36921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36937cd05799SMatthew G. Knepley @*/ 3694d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3695d71ae5a4SJacob Faibussowitsch { 3696552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3697552f7358SJed Brown PetscInt pStart, pEnd; 3698552f7358SJed Brown PetscInt dof, off; 3699552f7358SJed Brown 3700552f7358SJed Brown PetscFunctionBegin; 3701552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 37039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 37049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 370563a3b9bcSJacob 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); 370663a3b9bcSJacob 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); 370763a3b9bcSJacob 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); 3708552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 37093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3710552f7358SJed Brown } 3711552f7358SJed Brown 3712b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3713d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3714d71ae5a4SJacob Faibussowitsch { 3715b5a892a1SMatthew G. Knepley switch (ct) { 3716b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3717b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3718b5a892a1SMatthew G. Knepley break; 3719b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3720b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3721b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3722b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3723b5a892a1SMatthew G. Knepley break; 3724b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3725b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3726b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3727b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3728b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3729b5a892a1SMatthew G. Knepley break; 3730d71ae5a4SJacob Faibussowitsch default: 3731d71ae5a4SJacob Faibussowitsch return o; 3732b5a892a1SMatthew G. Knepley } 3733b5a892a1SMatthew G. Knepley return o; 3734b5a892a1SMatthew G. Knepley } 3735b5a892a1SMatthew G. Knepley 3736b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3737d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3738d71ae5a4SJacob Faibussowitsch { 3739b5a892a1SMatthew G. Knepley switch (ct) { 3740b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3741b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3742b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3743b5a892a1SMatthew G. Knepley break; 3744b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3745b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3746b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3747b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3748b5a892a1SMatthew G. Knepley break; 3749b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3750b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3751b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3752b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3753b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3754b5a892a1SMatthew G. Knepley break; 3755d71ae5a4SJacob Faibussowitsch default: 3756d71ae5a4SJacob Faibussowitsch return o; 3757b5a892a1SMatthew G. Knepley } 3758b5a892a1SMatthew G. Knepley return o; 3759b5a892a1SMatthew G. Knepley } 3760b5a892a1SMatthew G. Knepley 3761b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3763d71ae5a4SJacob Faibussowitsch { 3764b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3765b5a892a1SMatthew G. Knepley 3766b5a892a1SMatthew G. Knepley PetscFunctionBegin; 37679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3768b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3769b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3770b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3771b5a892a1SMatthew G. Knepley 37729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 37739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 37749566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3775b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3776b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3777b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3778b5a892a1SMatthew G. Knepley 37799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3780b5a892a1SMatthew G. Knepley switch (ct) { 3781b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 37829566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37839566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3784b5a892a1SMatthew G. Knepley break; 3785b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 37869566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37879566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37889566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3789b5a892a1SMatthew G. Knepley break; 3790b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 37919566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37929566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37939566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 37949566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3795b5a892a1SMatthew G. Knepley break; 3796d71ae5a4SJacob Faibussowitsch default: 3797d71ae5a4SJacob Faibussowitsch break; 3798b5a892a1SMatthew G. Knepley } 3799b5a892a1SMatthew G. Knepley } 3800b5a892a1SMatthew G. Knepley } 38013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3802b5a892a1SMatthew G. Knepley } 3803b5a892a1SMatthew G. Knepley 380409015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 380509015e70SStefano Zampini { 380609015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 380709015e70SStefano Zampini 380809015e70SStefano Zampini PetscFunctionBeginHot; 380909015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 381009015e70SStefano Zampini if (useCone) { 381109015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 381209015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 381309015e70SStefano Zampini } else { 381409015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 381509015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 381609015e70SStefano Zampini } 381709015e70SStefano Zampini } else { 381809015e70SStefano Zampini if (useCone) { 381909015e70SStefano Zampini const PetscSection s = mesh->coneSection; 382009015e70SStefano Zampini const PetscInt ps = p - s->pStart; 382109015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 382209015e70SStefano Zampini 382309015e70SStefano Zampini *size = s->atlasDof[ps]; 382409015e70SStefano Zampini *arr = mesh->cones + off; 382509015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 382609015e70SStefano Zampini } else { 382709015e70SStefano Zampini const PetscSection s = mesh->supportSection; 382809015e70SStefano Zampini const PetscInt ps = p - s->pStart; 382909015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 383009015e70SStefano Zampini 383109015e70SStefano Zampini *size = s->atlasDof[ps]; 383209015e70SStefano Zampini *arr = mesh->supports + off; 383309015e70SStefano Zampini } 383409015e70SStefano Zampini } 383509015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 383609015e70SStefano Zampini } 383709015e70SStefano Zampini 383809015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 383909015e70SStefano Zampini { 384009015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 384109015e70SStefano Zampini 384209015e70SStefano Zampini PetscFunctionBeginHot; 384309015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 384409015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 384509015e70SStefano Zampini } 384609015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 384709015e70SStefano Zampini } 384809015e70SStefano Zampini 3849d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3850d71ae5a4SJacob Faibussowitsch { 3851b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3852b5a892a1SMatthew G. Knepley PetscInt *closure; 3853b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3854b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3855b5a892a1SMatthew G. Knepley 3856b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3857b5a892a1SMatthew G. Knepley if (ornt) { 38589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3859476787b7SMatthew 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; 3860b5a892a1SMatthew G. Knepley } 3861b5a892a1SMatthew G. Knepley if (*points) { 3862b5a892a1SMatthew G. Knepley closure = *points; 3863b5a892a1SMatthew G. Knepley } else { 3864b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 38659566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 38669566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3867b5a892a1SMatthew G. Knepley } 386809015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3869b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3870b5a892a1SMatthew G. Knepley closure[off++] = p; 3871b5a892a1SMatthew G. Knepley closure[off++] = 0; 3872b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3873b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3874b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3875b5a892a1SMatthew G. Knepley } 3876b5a892a1SMatthew G. Knepley } else { 387785036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt); 3878b5a892a1SMatthew G. Knepley 3879b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3880b5a892a1SMatthew G. Knepley closure[off++] = p; 3881b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3882b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3883b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3884b5a892a1SMatthew G. Knepley 38859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3886b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3887b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3888b5a892a1SMatthew G. Knepley } 3889b5a892a1SMatthew G. Knepley } 389009015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3891b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3892b5a892a1SMatthew G. Knepley if (points) *points = closure; 38933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3894b5a892a1SMatthew G. Knepley } 3895b5a892a1SMatthew G. Knepley 3896d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3897d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3898d71ae5a4SJacob Faibussowitsch { 389985036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o); 3900b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3901b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3902b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3903b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3904b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3905b5a892a1SMatthew G. Knepley 3906b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 390809015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 39099566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3910b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3911b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3912b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39139371c9d4SSatish Balay if (*points) { 39149371c9d4SSatish Balay pts = *points; 39159371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3916b5a892a1SMatthew G. Knepley c = 0; 3917b5a892a1SMatthew G. Knepley pts[c++] = point; 3918b5a892a1SMatthew G. Knepley pts[c++] = o; 39199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 39209566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 39219371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39229371c9d4SSatish Balay pts[c++] = closure[cl]; 39239371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39249371c9d4SSatish Balay } 39259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 39269371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39279371c9d4SSatish Balay pts[c++] = closure[cl]; 39289371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39299371c9d4SSatish Balay } 39309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3931b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 39329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3933b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3934b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3935b5a892a1SMatthew G. Knepley } 393609015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 3937b5a892a1SMatthew G. Knepley if (dim >= 3) { 3938b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3939b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3940b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3941b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3942b5a892a1SMatthew G. Knepley 39439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 394485036b15SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 394509015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3946b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3947b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3948b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3949b5a892a1SMatthew G. Knepley 39509371c9d4SSatish Balay for (i = 0; i < c; i += 2) 39519371c9d4SSatish Balay if (pts[i] == cp) break; 3952b5a892a1SMatthew G. Knepley if (i == c) { 39539566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3954b5a892a1SMatthew G. Knepley pts[c++] = cp; 3955b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3956b5a892a1SMatthew G. Knepley } 3957b5a892a1SMatthew G. Knepley } 395809015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3959b5a892a1SMatthew G. Knepley } 3960b5a892a1SMatthew G. Knepley } 3961b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3962b5a892a1SMatthew G. Knepley *points = pts; 39633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3964b5a892a1SMatthew G. Knepley } 3965b5a892a1SMatthew G. Knepley 3966d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3967d71ae5a4SJacob Faibussowitsch { 3968b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3969b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3970b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3971b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3972b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3973b5a892a1SMatthew G. Knepley 3974b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3976b5a892a1SMatthew G. Knepley if (depth == 1) { 39779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 39783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3979b5a892a1SMatthew G. Knepley } 39809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3981476787b7SMatthew 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; 3982c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 39839566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 39843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3985b5a892a1SMatthew G. Knepley } 39869566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3987b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3988b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3989b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39909566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 39919371c9d4SSatish Balay if (*points) { 39929371c9d4SSatish Balay closure = *points; 39939371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3994b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3995b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3996b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3997b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3998b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3999b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 4000b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 4001b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 4002b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 4003b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 400485036b15SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangement(qt, o); 400509015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 4006b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 4007b5a892a1SMatthew G. Knepley 4008b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 400985036b15SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2; 401063a3b9bcSJacob 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); 4011b5a892a1SMatthew G. Knepley } 401209015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4013b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4014b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 4015b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 4016b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 40179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 4018b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 4019b5a892a1SMatthew G. Knepley PetscInt c; 4020b5a892a1SMatthew G. Knepley 4021b5a892a1SMatthew G. Knepley /* Check for duplicate */ 4022b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 4023b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 4024b5a892a1SMatthew G. Knepley } 4025b5a892a1SMatthew G. Knepley if (c == closureSize) { 4026b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 4027b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 4028b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 4029b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 4030b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4031b5a892a1SMatthew G. Knepley } 4032b5a892a1SMatthew G. Knepley } 403309015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4034b5a892a1SMatthew G. Knepley } 40359566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 4036b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4037b5a892a1SMatthew G. Knepley if (points) *points = closure; 40383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4039b5a892a1SMatthew G. Knepley } 4040b5a892a1SMatthew G. Knepley 4041552f7358SJed Brown /*@C 4042eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4043552f7358SJed Brown 4044a1cb98faSBarry Smith Not Collective 4045552f7358SJed Brown 4046552f7358SJed Brown Input Parameters: 4047a1cb98faSBarry Smith + dm - The `DMPLEX` 4048b5a892a1SMatthew G. Knepley . p - The mesh point 4049a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 4050552f7358SJed Brown 40516b867d5aSJose E. Roman Input/Output Parameter: 40526b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 405320f4b53cSBarry Smith if `NULL` on input, internal storage will be returned, otherwise the provided array is used 40546b867d5aSJose E. Roman 40556b867d5aSJose E. Roman Output Parameter: 405620f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4057552f7358SJed Brown 4058a1cb98faSBarry Smith Level: beginner 4059a1cb98faSBarry Smith 4060552f7358SJed Brown Note: 406120f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4062552f7358SJed Brown 406360225df5SJacob Faibussowitsch Fortran Notes: 406420f4b53cSBarry Smith The `numPoints` argument is not present in the Fortran binding since it is internal to the array. 40653813dfbdSMatthew G Knepley 40661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4067552f7358SJed Brown @*/ 4068d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4069d71ae5a4SJacob Faibussowitsch { 4070b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4071552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40724f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 40734f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 40749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 40753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40769bf0dad6SMatthew G. Knepley } 40779bf0dad6SMatthew G. Knepley 4078552f7358SJed Brown /*@C 4079eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4080552f7358SJed Brown 4081a1cb98faSBarry Smith Not Collective 4082552f7358SJed Brown 4083552f7358SJed Brown Input Parameters: 4084a1cb98faSBarry Smith + dm - The `DMPLEX` 4085b5a892a1SMatthew G. Knepley . p - The mesh point 4086a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 408720f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4088b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4089552f7358SJed Brown 4090a1cb98faSBarry Smith Level: beginner 4091a1cb98faSBarry Smith 4092552f7358SJed Brown Note: 409320f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4094552f7358SJed Brown 40951cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4096552f7358SJed Brown @*/ 4097d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4098d71ae5a4SJacob Faibussowitsch { 4099b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4100552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41014ff43b2cSJed Brown if (numPoints) *numPoints = 0; 41029566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 41033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4104552f7358SJed Brown } 4105552f7358SJed Brown 4106552f7358SJed Brown /*@ 4107eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4108552f7358SJed Brown 4109a1cb98faSBarry Smith Not Collective 4110552f7358SJed Brown 4111552f7358SJed Brown Input Parameter: 411260225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4113552f7358SJed Brown 4114552f7358SJed Brown Output Parameters: 4115552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4116552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4117552f7358SJed Brown 4118552f7358SJed Brown Level: beginner 4119552f7358SJed Brown 41201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4121552f7358SJed Brown @*/ 4122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 4123d71ae5a4SJacob Faibussowitsch { 4124552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4125552f7358SJed Brown 4126552f7358SJed Brown PetscFunctionBegin; 4127552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41281baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 41291baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 41303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4131552f7358SJed Brown } 4132552f7358SJed Brown 4133d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4134d71ae5a4SJacob Faibussowitsch { 4135552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 41366302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4137552f7358SJed Brown 4138552f7358SJed Brown PetscFunctionBegin; 4139552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 41419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 41429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 41439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 41446302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41456302a7fbSVaclav Hapla if (maxSupportSize) { 41469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 41479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 41489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4149552f7358SJed Brown } 41503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4151552f7358SJed Brown } 4152552f7358SJed Brown 4153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4154d71ae5a4SJacob Faibussowitsch { 4155552f7358SJed Brown PetscFunctionBegin; 41569566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 4157dd072f5fSMatthew G. Knepley PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm)); 4158ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4159736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 416095602cf2SAlexis Marboeuf PetscSF sfNatural; 4161f94b4a02SBlaise Bourdin 41623dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 41639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 416495602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4165c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4166f94b4a02SBlaise Bourdin } 41673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4168552f7358SJed Brown } 4169552f7358SJed Brown 4170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4171d71ae5a4SJacob Faibussowitsch { 41723dcd263cSBlaise Bourdin PetscInt i = 0; 41732adcc780SMatthew G. Knepley 41742adcc780SMatthew G. Knepley PetscFunctionBegin; 41759566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 41769566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4177c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 41783dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 41793dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 418095602cf2SAlexis Marboeuf PetscSF sfNatural; 41813dcd263cSBlaise Bourdin 41823dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 41839566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4184c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 418595602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4186c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 41873dcd263cSBlaise Bourdin break; 41883dcd263cSBlaise Bourdin } 41893dcd263cSBlaise Bourdin } 41903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41912adcc780SMatthew G. Knepley } 41922adcc780SMatthew G. Knepley 4193552f7358SJed Brown /*@ 4194eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4195552f7358SJed Brown 4196a1cb98faSBarry Smith Not Collective 4197552f7358SJed Brown 4198552f7358SJed Brown Input Parameter: 419960225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4200552f7358SJed Brown 4201552f7358SJed Brown Level: beginner 4202552f7358SJed Brown 4203a1cb98faSBarry Smith Note: 4204a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4205a1cb98faSBarry Smith 42061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4207552f7358SJed Brown @*/ 4208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4209d71ae5a4SJacob Faibussowitsch { 4210552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4211552f7358SJed Brown PetscInt *offsets; 4212552f7358SJed Brown PetscInt supportSize; 4213552f7358SJed Brown PetscInt pStart, pEnd, p; 4214552f7358SJed Brown 4215552f7358SJed Brown PetscFunctionBegin; 4216552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 421728b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 42189566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4219552f7358SJed Brown /* Calculate support sizes */ 42209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4221552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4222552f7358SJed Brown PetscInt dof, off, c; 4223552f7358SJed Brown 42249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 422648a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4227552f7358SJed Brown } 42289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4229552f7358SJed Brown /* Calculate supports */ 42309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 42319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 42329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4233552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4234552f7358SJed Brown PetscInt dof, off, c; 4235552f7358SJed Brown 42369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4238552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4239552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4240552f7358SJed Brown PetscInt offS; 4241552f7358SJed Brown 42429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 42430d644c17SKarl Rupp 4244552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4245552f7358SJed Brown ++offsets[q]; 4246552f7358SJed Brown } 4247552f7358SJed Brown } 42489566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 42499566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 42503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4251552f7358SJed Brown } 4252552f7358SJed Brown 4253d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4254d71ae5a4SJacob Faibussowitsch { 4255277ea44aSLisandro Dalcin IS stratumIS; 4256277ea44aSLisandro Dalcin 4257277ea44aSLisandro Dalcin PetscFunctionBegin; 42583ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 425976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4260277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4261277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 42629566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4263277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 42649566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 42659371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 42669371c9d4SSatish Balay overlap = PETSC_TRUE; 42679371c9d4SSatish Balay break; 42689371c9d4SSatish Balay } 4269277ea44aSLisandro Dalcin } 427063a3b9bcSJacob 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); 4271277ea44aSLisandro Dalcin } 42729566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 42739566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 42749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 42753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4276277ea44aSLisandro Dalcin } 4277277ea44aSLisandro Dalcin 4278e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4279e91fa0a1SMatthew G. Knepley { 4280e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4281e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4282e91fa0a1SMatthew G. Knepley PetscInt dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT; 4283e91fa0a1SMatthew G. Knepley 4284e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4285e91fa0a1SMatthew G. Knepley { 4286e91fa0a1SMatthew G. Knepley DMLabel label2; 4287e91fa0a1SMatthew G. Knepley 4288e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4289e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4290e91fa0a1SMatthew G. Knepley } 4291e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4292e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4293e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4294e91fa0a1SMatthew G. Knepley 4295e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4296e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4297e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4298e91fa0a1SMatthew G. Knepley } 4299e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4300e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4301e91fa0a1SMatthew G. Knepley pMin[d] = PETSC_MAX_INT; 4302e91fa0a1SMatthew G. Knepley pMax[d] = PETSC_MIN_INT; 4303e91fa0a1SMatthew G. Knepley } 4304e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4305e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4306e91fa0a1SMatthew G. Knepley PetscInt d; 4307e91fa0a1SMatthew G. Knepley 4308e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4309e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4310e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4311e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4312e91fa0a1SMatthew G. Knepley } 4313e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4314e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4315e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4316e91fa0a1SMatthew G. Knepley } 4317e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4318e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4319e91fa0a1SMatthew G. Knepley } 4320e91fa0a1SMatthew G. Knepley 4321e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4322e91fa0a1SMatthew G. Knepley { 4323e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4324e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4325e91fa0a1SMatthew G. Knepley 4326e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4327e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4328e91fa0a1SMatthew G. Knepley { 4329e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 4330e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4331e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4332e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4333e91fa0a1SMatthew G. Knepley 4334e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4335e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4336e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4337e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4338e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4339e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4340e91fa0a1SMatthew G. Knepley ++numRoots; 4341e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4342e91fa0a1SMatthew G. Knepley ++numLeaves; 4343e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4344e91fa0a1SMatthew G. Knepley /* Isolated points */ 4345e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4346e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4347e91fa0a1SMatthew G. Knepley } 4348e91fa0a1SMatthew G. Knepley } 4349e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4350e91fa0a1SMatthew G. Knepley } 4351e91fa0a1SMatthew G. Knepley 4352e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 4353e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4354e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4355e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4356e91fa0a1SMatthew G. Knepley 4357e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4358e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4359e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4360e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4361e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4362e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4363e91fa0a1SMatthew G. Knepley } 4364e91fa0a1SMatthew G. Knepley } 4365e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4366e91fa0a1SMatthew G. Knepley } else { 4367e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4368e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4369e91fa0a1SMatthew G. Knepley 4370e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4371e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 4372e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4373e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4374e91fa0a1SMatthew G. Knepley 4375e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4376e91fa0a1SMatthew G. Knepley const PetscInt *support; 4377e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4378e91fa0a1SMatthew G. Knepley 4379e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4380e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4381e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4382e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4383e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4384e91fa0a1SMatthew G. Knepley } 4385e91fa0a1SMatthew G. Knepley } 4386e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4387e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4388e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4389e91fa0a1SMatthew G. Knepley } 4390e91fa0a1SMatthew G. Knepley } 4391e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4392e91fa0a1SMatthew G. Knepley } 4393e91fa0a1SMatthew G. Knepley 4394552f7358SJed Brown /*@ 4395a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4396552f7358SJed Brown 439720f4b53cSBarry Smith Collective 4398552f7358SJed Brown 4399552f7358SJed Brown Input Parameter: 440060225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4401552f7358SJed Brown 4402a1cb98faSBarry Smith Level: beginner 4403552f7358SJed Brown 4404552f7358SJed Brown Notes: 4405a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4406a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4407a4e35b19SJacob Faibussowitsch 4408a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4409a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4410a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4411b1bb481bSMatthew 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 4412a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4413a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4414a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4415552f7358SJed Brown 4416b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4417b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4418b1bb481bSMatthew 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 4419b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4420a1cb98faSBarry Smith .vb 4421a1cb98faSBarry Smith cone(c0) = {e0, v2} 4422a1cb98faSBarry Smith cone(e0) = {v0, v1} 4423a1cb98faSBarry Smith .ve 4424a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4425a1cb98faSBarry Smith .vb 4426a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4427a1cb98faSBarry Smith depth 1 = {e0, c0} 4428a1cb98faSBarry Smith .ve 4429b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4430b1bb481bSMatthew Knepley 4431a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4432552f7358SJed Brown 44331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4434552f7358SJed Brown @*/ 4435d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4436d71ae5a4SJacob Faibussowitsch { 4437df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4438aa50250dSMatthew G. Knepley DMLabel label; 4439e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4440552f7358SJed Brown 4441552f7358SJed Brown PetscFunctionBegin; 4442552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 44439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4444277ea44aSLisandro Dalcin 4445e91fa0a1SMatthew G. Knepley // Create depth label 4446d28dd301SMatthew G. Knepley PetscCall(DMRemoveLabel(dm, "depth", NULL)); 44479566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 44489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4449277ea44aSLisandro Dalcin 4450e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4451e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4452e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4453552f7358SJed Brown 4454bf4602e4SToby Isaac { /* just in case there is an empty process */ 4455bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4456bf4602e4SToby Isaac 44579566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4458712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 445948a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4460bf4602e4SToby Isaac } 44619566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 44629566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 44633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4464552f7358SJed Brown } 4465552f7358SJed Brown 4466d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4467d71ae5a4SJacob Faibussowitsch { 4468412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4469412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4470ba2698f1SMatthew G. Knepley 4471412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 44729566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 44739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 44749566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4475ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4476ba2698f1SMatthew G. Knepley if (depth <= 1) { 4477ba2698f1SMatthew G. Knepley switch (pdepth) { 4478d71ae5a4SJacob Faibussowitsch case 0: 4479d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4480d71ae5a4SJacob Faibussowitsch break; 4481ba2698f1SMatthew G. Knepley case 1: 4482ba2698f1SMatthew G. Knepley switch (coneSize) { 4483d71ae5a4SJacob Faibussowitsch case 2: 4484d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4485d71ae5a4SJacob Faibussowitsch break; 4486d71ae5a4SJacob Faibussowitsch case 3: 4487d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4488d71ae5a4SJacob Faibussowitsch break; 4489ba2698f1SMatthew G. Knepley case 4: 4490ba2698f1SMatthew G. Knepley switch (dim) { 4491d71ae5a4SJacob Faibussowitsch case 2: 4492d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4493d71ae5a4SJacob Faibussowitsch break; 4494d71ae5a4SJacob Faibussowitsch case 3: 4495d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4496d71ae5a4SJacob Faibussowitsch break; 4497d71ae5a4SJacob Faibussowitsch default: 4498d71ae5a4SJacob Faibussowitsch break; 4499ba2698f1SMatthew G. Knepley } 4500ba2698f1SMatthew G. Knepley break; 4501d71ae5a4SJacob Faibussowitsch case 5: 4502d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4503d71ae5a4SJacob Faibussowitsch break; 4504d71ae5a4SJacob Faibussowitsch case 6: 4505d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4506d71ae5a4SJacob Faibussowitsch break; 4507d71ae5a4SJacob Faibussowitsch case 8: 4508d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4509d71ae5a4SJacob Faibussowitsch break; 4510d71ae5a4SJacob Faibussowitsch default: 4511d71ae5a4SJacob Faibussowitsch break; 4512ba2698f1SMatthew G. Knepley } 4513ba2698f1SMatthew G. Knepley } 4514ba2698f1SMatthew G. Knepley } else { 4515ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4516ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4517ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4518ba2698f1SMatthew G. Knepley switch (dim) { 4519ba2698f1SMatthew G. Knepley case 1: 4520ba2698f1SMatthew G. Knepley switch (coneSize) { 4521d71ae5a4SJacob Faibussowitsch case 2: 4522d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4523d71ae5a4SJacob Faibussowitsch break; 4524d71ae5a4SJacob Faibussowitsch default: 4525d71ae5a4SJacob Faibussowitsch break; 4526ba2698f1SMatthew G. Knepley } 4527ba2698f1SMatthew G. Knepley break; 4528ba2698f1SMatthew G. Knepley case 2: 4529ba2698f1SMatthew G. Knepley switch (coneSize) { 4530d71ae5a4SJacob Faibussowitsch case 3: 4531d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4532d71ae5a4SJacob Faibussowitsch break; 4533d71ae5a4SJacob Faibussowitsch case 4: 4534d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4535d71ae5a4SJacob Faibussowitsch break; 4536d71ae5a4SJacob Faibussowitsch default: 4537d71ae5a4SJacob Faibussowitsch break; 4538ba2698f1SMatthew G. Knepley } 4539ba2698f1SMatthew G. Knepley break; 4540ba2698f1SMatthew G. Knepley case 3: 4541ba2698f1SMatthew G. Knepley switch (coneSize) { 4542d71ae5a4SJacob Faibussowitsch case 4: 4543d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4544d71ae5a4SJacob Faibussowitsch break; 45459371c9d4SSatish Balay case 5: { 4546da9060c4SMatthew G. Knepley const PetscInt *cone; 4547da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4548da9060c4SMatthew G. Knepley 45499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 45509566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4551da9060c4SMatthew G. Knepley switch (faceConeSize) { 4552d71ae5a4SJacob Faibussowitsch case 3: 4553d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4554d71ae5a4SJacob Faibussowitsch break; 4555d71ae5a4SJacob Faibussowitsch case 4: 4556d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4557d71ae5a4SJacob Faibussowitsch break; 4558da9060c4SMatthew G. Knepley } 45599371c9d4SSatish Balay } break; 4560d71ae5a4SJacob Faibussowitsch case 6: 4561d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4562d71ae5a4SJacob Faibussowitsch break; 4563d71ae5a4SJacob Faibussowitsch default: 4564d71ae5a4SJacob Faibussowitsch break; 4565ba2698f1SMatthew G. Knepley } 4566ba2698f1SMatthew G. Knepley break; 4567d71ae5a4SJacob Faibussowitsch default: 4568d71ae5a4SJacob Faibussowitsch break; 4569ba2698f1SMatthew G. Knepley } 4570ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4571ba2698f1SMatthew G. Knepley switch (coneSize) { 4572d71ae5a4SJacob Faibussowitsch case 2: 4573d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4574d71ae5a4SJacob Faibussowitsch break; 4575d71ae5a4SJacob Faibussowitsch case 3: 4576d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4577d71ae5a4SJacob Faibussowitsch break; 4578d71ae5a4SJacob Faibussowitsch case 4: 4579d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4580d71ae5a4SJacob Faibussowitsch break; 4581d71ae5a4SJacob Faibussowitsch default: 4582d71ae5a4SJacob Faibussowitsch break; 4583ba2698f1SMatthew G. Knepley } 4584ba2698f1SMatthew G. Knepley } 4585ba2698f1SMatthew G. Knepley } 4586412e9a14SMatthew G. Knepley *pt = ct; 45873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4588ba2698f1SMatthew G. Knepley } 4589412e9a14SMatthew G. Knepley 4590412e9a14SMatthew G. Knepley /*@ 4591412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4592412e9a14SMatthew G. Knepley 459320f4b53cSBarry Smith Collective 4594412e9a14SMatthew G. Knepley 4595412e9a14SMatthew G. Knepley Input Parameter: 459660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4597412e9a14SMatthew G. Knepley 4598412e9a14SMatthew G. Knepley Level: developer 4599412e9a14SMatthew G. Knepley 4600a1cb98faSBarry Smith Note: 4601a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4602a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4603a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4604412e9a14SMatthew G. Knepley 4605a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4606a1cb98faSBarry Smith 46071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4608412e9a14SMatthew G. Knepley @*/ 4609d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4610d71ae5a4SJacob Faibussowitsch { 4611412e9a14SMatthew G. Knepley DM_Plex *mesh; 4612412e9a14SMatthew G. Knepley DMLabel ctLabel; 4613412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4614412e9a14SMatthew G. Knepley 4615412e9a14SMatthew G. Knepley PetscFunctionBegin; 4616412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4617412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 46189566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 46199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 46209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 462121027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 462221027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4623412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4624327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4625412e9a14SMatthew G. Knepley PetscInt pdepth; 4626412e9a14SMatthew G. Knepley 46279566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 46289566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4629476787b7SMatthew 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); 46309566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 463121027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = ct; 4632412e9a14SMatthew G. Knepley } 46339566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 46349566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 46353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4636ba2698f1SMatthew G. Knepley } 4637ba2698f1SMatthew G. Knepley 4638552f7358SJed Brown /*@C 4639552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4640552f7358SJed Brown 4641552f7358SJed Brown Not Collective 4642552f7358SJed Brown 4643552f7358SJed Brown Input Parameters: 4644a1cb98faSBarry Smith + dm - The `DMPLEX` object 4645552f7358SJed Brown . numPoints - The number of input points for the join 4646552f7358SJed Brown - points - The input points 4647552f7358SJed Brown 4648552f7358SJed Brown Output Parameters: 4649552f7358SJed Brown + numCoveredPoints - The number of points in the join 4650552f7358SJed Brown - coveredPoints - The points in the join 4651552f7358SJed Brown 4652552f7358SJed Brown Level: intermediate 4653552f7358SJed Brown 4654a1cb98faSBarry Smith Note: 4655a1cb98faSBarry Smith Currently, this is restricted to a single level join 4656552f7358SJed Brown 465760225df5SJacob Faibussowitsch Fortran Notes: 465820f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 46593813dfbdSMatthew G Knepley 46601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4661552f7358SJed Brown @*/ 4662d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4663d71ae5a4SJacob Faibussowitsch { 4664552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4665552f7358SJed Brown PetscInt *join[2]; 4666552f7358SJed Brown PetscInt joinSize, i = 0; 4667552f7358SJed Brown PetscInt dof, off, p, c, m; 46686302a7fbSVaclav Hapla PetscInt maxSupportSize; 4669552f7358SJed Brown 4670552f7358SJed Brown PetscFunctionBegin; 4671552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46724f572ea9SToby Isaac PetscAssertPointer(points, 3); 46734f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 46744f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46756302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 46766302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 46776302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4678552f7358SJed Brown /* Copy in support of first point */ 46799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 46809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4681ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4682552f7358SJed Brown /* Check each successive support */ 4683552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4684552f7358SJed Brown PetscInt newJoinSize = 0; 4685552f7358SJed Brown 46869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 46879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4688552f7358SJed Brown for (c = 0; c < dof; ++c) { 4689552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4690552f7358SJed Brown 4691552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4692552f7358SJed Brown if (point == join[i][m]) { 4693552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4694552f7358SJed Brown break; 4695552f7358SJed Brown } 4696552f7358SJed Brown } 4697552f7358SJed Brown } 4698552f7358SJed Brown joinSize = newJoinSize; 4699552f7358SJed Brown i = 1 - i; 4700552f7358SJed Brown } 4701552f7358SJed Brown *numCoveredPoints = joinSize; 4702552f7358SJed Brown *coveredPoints = join[i]; 47036302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 47043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4705552f7358SJed Brown } 4706552f7358SJed Brown 4707552f7358SJed Brown /*@C 4708552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4709552f7358SJed Brown 4710552f7358SJed Brown Not Collective 4711552f7358SJed Brown 4712552f7358SJed Brown Input Parameters: 4713a1cb98faSBarry Smith + dm - The `DMPLEX` object 4714552f7358SJed Brown . numPoints - The number of input points for the join 4715552f7358SJed Brown - points - The input points 4716552f7358SJed Brown 4717552f7358SJed Brown Output Parameters: 4718552f7358SJed Brown + numCoveredPoints - The number of points in the join 4719552f7358SJed Brown - coveredPoints - The points in the join 4720552f7358SJed Brown 4721552f7358SJed Brown Level: intermediate 4722552f7358SJed Brown 472360225df5SJacob Faibussowitsch Fortran Notes: 472420f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4725a1cb98faSBarry Smith 47261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4727552f7358SJed Brown @*/ 4728d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4729d71ae5a4SJacob Faibussowitsch { 4730552f7358SJed Brown PetscFunctionBegin; 4731552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47324f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 47334f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 47344f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 47359566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4736d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 47373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4738552f7358SJed Brown } 4739552f7358SJed Brown 4740552f7358SJed Brown /*@C 4741552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4742552f7358SJed Brown 4743552f7358SJed Brown Not Collective 4744552f7358SJed Brown 4745552f7358SJed Brown Input Parameters: 4746a1cb98faSBarry Smith + dm - The `DMPLEX` object 4747552f7358SJed Brown . numPoints - The number of input points for the join 4748552f7358SJed Brown - points - The input points 4749552f7358SJed Brown 4750552f7358SJed Brown Output Parameters: 4751552f7358SJed Brown + numCoveredPoints - The number of points in the join 4752552f7358SJed Brown - coveredPoints - The points in the join 4753552f7358SJed Brown 4754552f7358SJed Brown Level: intermediate 4755552f7358SJed Brown 475660225df5SJacob Faibussowitsch Fortran Notes: 475720f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4758a1cb98faSBarry Smith 47591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4760552f7358SJed Brown @*/ 4761d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4762d71ae5a4SJacob Faibussowitsch { 4763552f7358SJed Brown PetscInt *offsets, **closures; 4764552f7358SJed Brown PetscInt *join[2]; 4765552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 476624c766afSToby Isaac PetscInt p, d, c, m, ms; 4767552f7358SJed Brown 4768552f7358SJed Brown PetscFunctionBegin; 4769552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47704f572ea9SToby Isaac PetscAssertPointer(points, 3); 47714f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 47724f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4773552f7358SJed Brown 47749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 47759566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 47769566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 47776302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 477824c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 47799566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 47809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4781552f7358SJed Brown 4782552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4783552f7358SJed Brown PetscInt closureSize; 4784552f7358SJed Brown 47859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 47860d644c17SKarl Rupp 4787552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4788552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4789552f7358SJed Brown PetscInt pStart, pEnd, i; 4790552f7358SJed Brown 47919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4792552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4793552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4794552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4795552f7358SJed Brown break; 4796552f7358SJed Brown } 4797552f7358SJed Brown } 4798552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4799552f7358SJed Brown } 480063a3b9bcSJacob 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); 4801552f7358SJed Brown } 4802552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4803552f7358SJed Brown PetscInt dof; 4804552f7358SJed Brown 4805552f7358SJed Brown /* Copy in support of first point */ 4806552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4807ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4808552f7358SJed Brown /* Check each successive cone */ 4809552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4810552f7358SJed Brown PetscInt newJoinSize = 0; 4811552f7358SJed Brown 4812552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4813552f7358SJed Brown for (c = 0; c < dof; ++c) { 4814552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4815552f7358SJed Brown 4816552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4817552f7358SJed Brown if (point == join[i][m]) { 4818552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4819552f7358SJed Brown break; 4820552f7358SJed Brown } 4821552f7358SJed Brown } 4822552f7358SJed Brown } 4823552f7358SJed Brown joinSize = newJoinSize; 4824552f7358SJed Brown i = 1 - i; 4825552f7358SJed Brown } 4826552f7358SJed Brown if (joinSize) break; 4827552f7358SJed Brown } 4828552f7358SJed Brown *numCoveredPoints = joinSize; 4829552f7358SJed Brown *coveredPoints = join[i]; 483048a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 48319566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 48329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 48336302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 48343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4835552f7358SJed Brown } 4836552f7358SJed Brown 4837552f7358SJed Brown /*@C 4838552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4839552f7358SJed Brown 4840552f7358SJed Brown Not Collective 4841552f7358SJed Brown 4842552f7358SJed Brown Input Parameters: 4843a1cb98faSBarry Smith + dm - The `DMPLEX` object 4844552f7358SJed Brown . numPoints - The number of input points for the meet 4845552f7358SJed Brown - points - The input points 4846552f7358SJed Brown 4847552f7358SJed Brown Output Parameters: 484860225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 484960225df5SJacob Faibussowitsch - coveringPoints - The points in the meet 4850552f7358SJed Brown 4851552f7358SJed Brown Level: intermediate 4852552f7358SJed Brown 4853a1cb98faSBarry Smith Note: 4854a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4855552f7358SJed Brown 48563813dfbdSMatthew G Knepley Fortran Notes: 485720f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48583813dfbdSMatthew G Knepley 48591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4860552f7358SJed Brown @*/ 4861d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4862d71ae5a4SJacob Faibussowitsch { 4863552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4864552f7358SJed Brown PetscInt *meet[2]; 4865552f7358SJed Brown PetscInt meetSize, i = 0; 4866552f7358SJed Brown PetscInt dof, off, p, c, m; 48676302a7fbSVaclav Hapla PetscInt maxConeSize; 4868552f7358SJed Brown 4869552f7358SJed Brown PetscFunctionBegin; 4870552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48714f572ea9SToby Isaac PetscAssertPointer(points, 3); 48724f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 48734f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 48746302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 48756302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 48766302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4877552f7358SJed Brown /* Copy in cone of first point */ 48789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 48799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4880ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4881552f7358SJed Brown /* Check each successive cone */ 4882552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4883552f7358SJed Brown PetscInt newMeetSize = 0; 4884552f7358SJed Brown 48859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 48869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4887552f7358SJed Brown for (c = 0; c < dof; ++c) { 4888552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4889552f7358SJed Brown 4890552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4891552f7358SJed Brown if (point == meet[i][m]) { 4892552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4893552f7358SJed Brown break; 4894552f7358SJed Brown } 4895552f7358SJed Brown } 4896552f7358SJed Brown } 4897552f7358SJed Brown meetSize = newMeetSize; 4898552f7358SJed Brown i = 1 - i; 4899552f7358SJed Brown } 4900552f7358SJed Brown *numCoveringPoints = meetSize; 4901552f7358SJed Brown *coveringPoints = meet[i]; 49026302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 49033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4904552f7358SJed Brown } 4905552f7358SJed Brown 4906552f7358SJed Brown /*@C 4907552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4908552f7358SJed Brown 4909552f7358SJed Brown Not Collective 4910552f7358SJed Brown 4911552f7358SJed Brown Input Parameters: 4912a1cb98faSBarry Smith + dm - The `DMPLEX` object 4913552f7358SJed Brown . numPoints - The number of input points for the meet 4914552f7358SJed Brown - points - The input points 4915552f7358SJed Brown 4916552f7358SJed Brown Output Parameters: 4917552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4918552f7358SJed Brown - coveredPoints - The points in the meet 4919552f7358SJed Brown 4920552f7358SJed Brown Level: intermediate 4921552f7358SJed Brown 492260225df5SJacob Faibussowitsch Fortran Notes: 492320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49243813dfbdSMatthew G Knepley 49251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4926552f7358SJed Brown @*/ 4927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4928d71ae5a4SJacob Faibussowitsch { 4929552f7358SJed Brown PetscFunctionBegin; 4930552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49314f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 49324f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 49334f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 49349566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4935d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 49363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4937552f7358SJed Brown } 4938552f7358SJed Brown 4939552f7358SJed Brown /*@C 4940552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4941552f7358SJed Brown 4942552f7358SJed Brown Not Collective 4943552f7358SJed Brown 4944552f7358SJed Brown Input Parameters: 4945a1cb98faSBarry Smith + dm - The `DMPLEX` object 4946552f7358SJed Brown . numPoints - The number of input points for the meet 4947552f7358SJed Brown - points - The input points 4948552f7358SJed Brown 4949552f7358SJed Brown Output Parameters: 4950552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4951552f7358SJed Brown - coveredPoints - The points in the meet 4952552f7358SJed Brown 4953552f7358SJed Brown Level: intermediate 4954552f7358SJed Brown 495560225df5SJacob Faibussowitsch Fortran Notes: 495620f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49573813dfbdSMatthew G Knepley 49581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4959552f7358SJed Brown @*/ 4960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4961d71ae5a4SJacob Faibussowitsch { 4962552f7358SJed Brown PetscInt *offsets, **closures; 4963552f7358SJed Brown PetscInt *meet[2]; 4964552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 496524c766afSToby Isaac PetscInt p, h, c, m, mc; 4966552f7358SJed Brown 4967552f7358SJed Brown PetscFunctionBegin; 4968552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49694f572ea9SToby Isaac PetscAssertPointer(points, 3); 49704f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 49714f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4972552f7358SJed Brown 49739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 49749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 49759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 49766302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 497724c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 49789566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 49799566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4980552f7358SJed Brown 4981552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4982552f7358SJed Brown PetscInt closureSize; 4983552f7358SJed Brown 49849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 49850d644c17SKarl Rupp 4986552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4987552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4988552f7358SJed Brown PetscInt pStart, pEnd, i; 4989552f7358SJed Brown 49909566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4991552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4992552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4993552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4994552f7358SJed Brown break; 4995552f7358SJed Brown } 4996552f7358SJed Brown } 4997552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4998552f7358SJed Brown } 499963a3b9bcSJacob 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); 5000552f7358SJed Brown } 5001552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 5002552f7358SJed Brown PetscInt dof; 5003552f7358SJed Brown 5004552f7358SJed Brown /* Copy in cone of first point */ 5005552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 5006ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 5007552f7358SJed Brown /* Check each successive cone */ 5008552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 5009552f7358SJed Brown PetscInt newMeetSize = 0; 5010552f7358SJed Brown 5011552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 5012552f7358SJed Brown for (c = 0; c < dof; ++c) { 5013552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 5014552f7358SJed Brown 5015552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5016552f7358SJed Brown if (point == meet[i][m]) { 5017552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5018552f7358SJed Brown break; 5019552f7358SJed Brown } 5020552f7358SJed Brown } 5021552f7358SJed Brown } 5022552f7358SJed Brown meetSize = newMeetSize; 5023552f7358SJed Brown i = 1 - i; 5024552f7358SJed Brown } 5025552f7358SJed Brown if (meetSize) break; 5026552f7358SJed Brown } 5027552f7358SJed Brown *numCoveredPoints = meetSize; 5028552f7358SJed Brown *coveredPoints = meet[i]; 502948a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 50309566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 50319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 50326302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 50333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5034552f7358SJed Brown } 5035552f7358SJed Brown 50364e3744c5SMatthew G. Knepley /*@C 5037a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 50384e3744c5SMatthew G. Knepley 50394e3744c5SMatthew G. Knepley Not Collective 50404e3744c5SMatthew G. Knepley 50414e3744c5SMatthew G. Knepley Input Parameters: 5042a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5043a1cb98faSBarry Smith - dmB - A `DMPLEX` object 50444e3744c5SMatthew G. Knepley 50452fe279fdSBarry Smith Output Parameter: 5046a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 50474e3744c5SMatthew G. Knepley 50484e3744c5SMatthew G. Knepley Level: intermediate 50494e3744c5SMatthew G. Knepley 5050a1cb98faSBarry Smith Note: 50513c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 50524e3744c5SMatthew G. Knepley 50531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 50544e3744c5SMatthew G. Knepley @*/ 5055d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5056d71ae5a4SJacob Faibussowitsch { 50574e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 50584e3744c5SMatthew G. Knepley 50594e3744c5SMatthew G. Knepley PetscFunctionBegin; 50604e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 50614e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 50624f572ea9SToby Isaac PetscAssertPointer(equal, 3); 50634e3744c5SMatthew G. Knepley 50644e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 50659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 50669566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 50673ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 50689566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 50699566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 50703ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 50714e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 50724e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 50734e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 50744e3744c5SMatthew G. Knepley 50759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 50769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 50779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 50789566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 50799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 50809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 50813ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50824e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 50833ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50843ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50854e3744c5SMatthew G. Knepley } 50869566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 50879566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 50889566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 50899566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 50903ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50914e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 50923ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 50934e3744c5SMatthew G. Knepley } 50944e3744c5SMatthew G. Knepley } 50954e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 50963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50974e3744c5SMatthew G. Knepley } 50984e3744c5SMatthew G. Knepley 50997cd05799SMatthew G. Knepley /*@C 51007cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 51017cd05799SMatthew G. Knepley 51027cd05799SMatthew G. Knepley Not Collective 51037cd05799SMatthew G. Knepley 51047cd05799SMatthew G. Knepley Input Parameters: 5105a1cb98faSBarry Smith + dm - The `DMPLEX` 51067cd05799SMatthew G. Knepley . cellDim - The cell dimension 51077cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 51087cd05799SMatthew G. Knepley 51092fe279fdSBarry Smith Output Parameter: 51107cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 51117cd05799SMatthew G. Knepley 51127cd05799SMatthew G. Knepley Level: developer 51137cd05799SMatthew G. Knepley 5114a1cb98faSBarry Smith Note: 51157cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 51167cd05799SMatthew G. Knepley 51171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 51187cd05799SMatthew G. Knepley @*/ 5119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5120d71ae5a4SJacob Faibussowitsch { 512182f516ccSBarry Smith MPI_Comm comm; 5122552f7358SJed Brown 5123552f7358SJed Brown PetscFunctionBegin; 51249566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 51254f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5126552f7358SJed Brown switch (cellDim) { 5127d71ae5a4SJacob Faibussowitsch case 0: 5128d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5129d71ae5a4SJacob Faibussowitsch break; 5130d71ae5a4SJacob Faibussowitsch case 1: 5131d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5132d71ae5a4SJacob Faibussowitsch break; 5133552f7358SJed Brown case 2: 5134552f7358SJed Brown switch (numCorners) { 513519436ca2SJed Brown case 3: /* triangle */ 513619436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5137552f7358SJed Brown break; 513819436ca2SJed Brown case 4: /* quadrilateral */ 513919436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5140552f7358SJed Brown break; 514119436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 514219436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5143552f7358SJed Brown break; 514419436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 514519436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5146552f7358SJed Brown break; 5147d71ae5a4SJacob Faibussowitsch default: 5148d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5149552f7358SJed Brown } 5150552f7358SJed Brown break; 5151552f7358SJed Brown case 3: 5152552f7358SJed Brown switch (numCorners) { 515319436ca2SJed Brown case 4: /* tetradehdron */ 515419436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5155552f7358SJed Brown break; 515619436ca2SJed Brown case 6: /* tet cohesive cells */ 515719436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5158552f7358SJed Brown break; 515919436ca2SJed Brown case 8: /* hexahedron */ 516019436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5161552f7358SJed Brown break; 516219436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 516319436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5164552f7358SJed Brown break; 516519436ca2SJed Brown case 10: /* quadratic tetrahedron */ 516619436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5167552f7358SJed Brown break; 516819436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 516919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5170552f7358SJed Brown break; 517119436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 517219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5173552f7358SJed Brown break; 517419436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 517519436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5176552f7358SJed Brown break; 5177d71ae5a4SJacob Faibussowitsch default: 5178d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5179552f7358SJed Brown } 5180552f7358SJed Brown break; 5181d71ae5a4SJacob Faibussowitsch default: 5182d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5183552f7358SJed Brown } 51843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5185552f7358SJed Brown } 5186552f7358SJed Brown 5187552f7358SJed Brown /*@ 5188a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5189552f7358SJed Brown 5190552f7358SJed Brown Not Collective 5191552f7358SJed Brown 5192aa50250dSMatthew G. Knepley Input Parameter: 5193a1cb98faSBarry Smith . dm - The `DMPLEX` object 5194552f7358SJed Brown 5195aa50250dSMatthew G. Knepley Output Parameter: 5196a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5197552f7358SJed Brown 5198552f7358SJed Brown Level: developer 5199552f7358SJed Brown 52001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5201aa50250dSMatthew G. Knepley @*/ 5202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5203d71ae5a4SJacob Faibussowitsch { 5204aa50250dSMatthew G. Knepley PetscFunctionBegin; 5205aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52064f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5207c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 52083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5209aa50250dSMatthew G. Knepley } 5210aa50250dSMatthew G. Knepley 5211aa50250dSMatthew G. Knepley /*@ 5212aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5213aa50250dSMatthew G. Knepley 5214aa50250dSMatthew G. Knepley Not Collective 5215aa50250dSMatthew G. Knepley 5216aa50250dSMatthew G. Knepley Input Parameter: 5217a1cb98faSBarry Smith . dm - The `DMPLEX` object 5218aa50250dSMatthew G. Knepley 5219aa50250dSMatthew G. Knepley Output Parameter: 5220aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5221aa50250dSMatthew G. Knepley 5222aa50250dSMatthew G. Knepley Level: developer 5223552f7358SJed Brown 5224b1bb481bSMatthew Knepley Notes: 5225a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5226a1cb98faSBarry Smith 5227a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5228a1cb98faSBarry Smith 5229dc287ab2SVaclav Hapla An empty mesh gives -1. 5230b1bb481bSMatthew Knepley 52311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5232552f7358SJed Brown @*/ 5233d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5234d71ae5a4SJacob Faibussowitsch { 52359f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5236aa50250dSMatthew G. Knepley DMLabel label; 5237aa50250dSMatthew G. Knepley PetscInt d = 0; 5238552f7358SJed Brown 5239552f7358SJed Brown PetscFunctionBegin; 5240552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52414f572ea9SToby Isaac PetscAssertPointer(depth, 2); 52429f4ada15SMatthew G. Knepley if (mesh->tr) { 52439f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 52449f4ada15SMatthew G. Knepley } else { 52459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52469566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 5247552f7358SJed Brown *depth = d - 1; 52489f4ada15SMatthew G. Knepley } 52493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5250552f7358SJed Brown } 5251552f7358SJed Brown 5252552f7358SJed Brown /*@ 525320f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5254552f7358SJed Brown 5255552f7358SJed Brown Not Collective 5256552f7358SJed Brown 5257552f7358SJed Brown Input Parameters: 5258a1cb98faSBarry Smith + dm - The `DMPLEX` object 5259570fa34dSVaclav Hapla - depth - The requested depth 5260552f7358SJed Brown 5261552f7358SJed Brown Output Parameters: 526220f4b53cSBarry Smith + start - The first point at this `depth` 526320f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5264552f7358SJed Brown 5265552f7358SJed Brown Level: developer 5266552f7358SJed Brown 5267a1cb98faSBarry Smith Notes: 5268a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5269a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5270a1cb98faSBarry Smith higher dimension, e.g., "edges". 5271a1cb98faSBarry Smith 52722827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5273552f7358SJed Brown @*/ 5274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5275d71ae5a4SJacob Faibussowitsch { 52769f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5277aa50250dSMatthew G. Knepley DMLabel label; 527863d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5279552f7358SJed Brown 5280552f7358SJed Brown PetscFunctionBegin; 5281552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52829371c9d4SSatish Balay if (start) { 52834f572ea9SToby Isaac PetscAssertPointer(start, 3); 52849371c9d4SSatish Balay *start = 0; 52859371c9d4SSatish Balay } 52869371c9d4SSatish Balay if (end) { 52874f572ea9SToby Isaac PetscAssertPointer(end, 4); 52889371c9d4SSatish Balay *end = 0; 52899371c9d4SSatish Balay } 52909566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 52913ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5292570fa34dSVaclav Hapla if (depth < 0) { 529363d1a920SMatthew G. Knepley if (start) *start = pStart; 529463d1a920SMatthew G. Knepley if (end) *end = pEnd; 52953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5296552f7358SJed Brown } 52979f4ada15SMatthew G. Knepley if (mesh->tr) { 52989f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 52999f4ada15SMatthew G. Knepley } else { 53009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 530128b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5302570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 53039f4ada15SMatthew G. Knepley } 53043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5305552f7358SJed Brown } 5306552f7358SJed Brown 5307552f7358SJed Brown /*@ 530820f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5309552f7358SJed Brown 5310552f7358SJed Brown Not Collective 5311552f7358SJed Brown 5312552f7358SJed Brown Input Parameters: 5313a1cb98faSBarry Smith + dm - The `DMPLEX` object 5314570fa34dSVaclav Hapla - height - The requested height 5315552f7358SJed Brown 5316552f7358SJed Brown Output Parameters: 531720f4b53cSBarry Smith + start - The first point at this `height` 531820f4b53cSBarry Smith - end - One beyond the last point at this `height` 5319552f7358SJed Brown 5320552f7358SJed Brown Level: developer 5321552f7358SJed Brown 5322a1cb98faSBarry Smith Notes: 5323a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5324a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5325a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5326a1cb98faSBarry Smith 53272827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5328552f7358SJed Brown @*/ 5329d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5330d71ae5a4SJacob Faibussowitsch { 5331aa50250dSMatthew G. Knepley DMLabel label; 533263d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5333552f7358SJed Brown 5334552f7358SJed Brown PetscFunctionBegin; 5335552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53369371c9d4SSatish Balay if (start) { 53374f572ea9SToby Isaac PetscAssertPointer(start, 3); 53389371c9d4SSatish Balay *start = 0; 53399371c9d4SSatish Balay } 53409371c9d4SSatish Balay if (end) { 53414f572ea9SToby Isaac PetscAssertPointer(end, 4); 53429371c9d4SSatish Balay *end = 0; 53439371c9d4SSatish Balay } 53449566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 53453ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5346570fa34dSVaclav Hapla if (height < 0) { 534763d1a920SMatthew G. Knepley if (start) *start = pStart; 534863d1a920SMatthew G. Knepley if (end) *end = pEnd; 53493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5350552f7358SJed Brown } 53519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 535259e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 535359e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 535459e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 535559e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 53563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5357552f7358SJed Brown } 5358552f7358SJed Brown 5359ba2698f1SMatthew G. Knepley /*@ 536020f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5361ba2698f1SMatthew G. Knepley 5362ba2698f1SMatthew G. Knepley Not Collective 5363ba2698f1SMatthew G. Knepley 5364d8d19677SJose E. Roman Input Parameters: 5365a1cb98faSBarry Smith + dm - The `DMPLEX` object 5366ba2698f1SMatthew G. Knepley - point - The point 5367ba2698f1SMatthew G. Knepley 5368ba2698f1SMatthew G. Knepley Output Parameter: 536920f4b53cSBarry Smith . depth - The depth of the `point` 5370ba2698f1SMatthew G. Knepley 5371ba2698f1SMatthew G. Knepley Level: intermediate 5372ba2698f1SMatthew G. Knepley 53731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5374ba2698f1SMatthew G. Knepley @*/ 5375d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5376d71ae5a4SJacob Faibussowitsch { 5377ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5378ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53794f572ea9SToby Isaac PetscAssertPointer(depth, 3); 53809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 53813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5382ba2698f1SMatthew G. Knepley } 5383ba2698f1SMatthew G. Knepley 5384ba2698f1SMatthew G. Knepley /*@ 538520f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 53860c0a32dcSVaclav Hapla 53870c0a32dcSVaclav Hapla Not Collective 53880c0a32dcSVaclav Hapla 5389d8d19677SJose E. Roman Input Parameters: 5390a1cb98faSBarry Smith + dm - The `DMPLEX` object 53910c0a32dcSVaclav Hapla - point - The point 53920c0a32dcSVaclav Hapla 53930c0a32dcSVaclav Hapla Output Parameter: 539420f4b53cSBarry Smith . height - The height of the `point` 53950c0a32dcSVaclav Hapla 53960c0a32dcSVaclav Hapla Level: intermediate 53970c0a32dcSVaclav Hapla 53981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 53990c0a32dcSVaclav Hapla @*/ 5400d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5401d71ae5a4SJacob Faibussowitsch { 54020c0a32dcSVaclav Hapla PetscInt n, pDepth; 54030c0a32dcSVaclav Hapla 54040c0a32dcSVaclav Hapla PetscFunctionBegin; 54050c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54064f572ea9SToby Isaac PetscAssertPointer(height, 3); 54079566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 54089566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 54090c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 54103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54110c0a32dcSVaclav Hapla } 54120c0a32dcSVaclav Hapla 54130c0a32dcSVaclav Hapla /*@ 5414a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5415ba2698f1SMatthew G. Knepley 5416ba2698f1SMatthew G. Knepley Not Collective 5417ba2698f1SMatthew G. Knepley 5418ba2698f1SMatthew G. Knepley Input Parameter: 5419a1cb98faSBarry Smith . dm - The `DMPLEX` object 5420ba2698f1SMatthew G. Knepley 5421ba2698f1SMatthew G. Knepley Output Parameter: 5422a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5423412e9a14SMatthew G. Knepley 5424ba2698f1SMatthew G. Knepley Level: developer 5425ba2698f1SMatthew G. Knepley 5426a1cb98faSBarry Smith Note: 5427a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5428a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5429a1cb98faSBarry Smith 54301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5431ba2698f1SMatthew G. Knepley @*/ 5432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5433d71ae5a4SJacob Faibussowitsch { 5434ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5435ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54364f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 54379566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5438ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 54393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5440ba2698f1SMatthew G. Knepley } 5441ba2698f1SMatthew G. Knepley 5442ba2698f1SMatthew G. Knepley /*@ 5443ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5444ba2698f1SMatthew G. Knepley 5445ba2698f1SMatthew G. Knepley Not Collective 5446ba2698f1SMatthew G. Knepley 5447d8d19677SJose E. Roman Input Parameters: 5448a1cb98faSBarry Smith + dm - The `DMPLEX` object 5449ba2698f1SMatthew G. Knepley - cell - The cell 5450ba2698f1SMatthew G. Knepley 5451ba2698f1SMatthew G. Knepley Output Parameter: 5452ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5453ba2698f1SMatthew G. Knepley 5454ba2698f1SMatthew G. Knepley Level: intermediate 5455ba2698f1SMatthew G. Knepley 54561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5457ba2698f1SMatthew G. Knepley @*/ 5458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5459d71ae5a4SJacob Faibussowitsch { 54609f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5461ba2698f1SMatthew G. Knepley DMLabel label; 5462ba2698f1SMatthew G. Knepley PetscInt ct; 5463ba2698f1SMatthew G. Knepley 5464ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5465ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54664f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 54679f4ada15SMatthew G. Knepley if (mesh->tr) { 54689f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 54699f4ada15SMatthew G. Knepley } else { 547021027e53SStefano Zampini PetscInt pStart, pEnd; 547121027e53SStefano Zampini 547221027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 547321027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 547421027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 547521027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 547621027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 547721027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 547821027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 547921027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct; 548021027e53SStefano Zampini } 548121027e53SStefano Zampini } 548221027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 548321027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 54849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 54859566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 548663a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5487936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 548821027e53SStefano Zampini } 54899f4ada15SMatthew G. Knepley } 54903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5491ba2698f1SMatthew G. Knepley } 5492ba2698f1SMatthew G. Knepley 5493412e9a14SMatthew G. Knepley /*@ 5494412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5495412e9a14SMatthew G. Knepley 5496412e9a14SMatthew G. Knepley Not Collective 5497412e9a14SMatthew G. Knepley 5498412e9a14SMatthew G. Knepley Input Parameters: 5499a1cb98faSBarry Smith + dm - The `DMPLEX` object 5500412e9a14SMatthew G. Knepley . cell - The cell 5501412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5502412e9a14SMatthew G. Knepley 5503a1cb98faSBarry Smith Level: advanced 5504a1cb98faSBarry Smith 5505a1cb98faSBarry Smith Note: 5506a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5507412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5508412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5509db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5510412e9a14SMatthew G. Knepley 55111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5512412e9a14SMatthew G. Knepley @*/ 5513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5514d71ae5a4SJacob Faibussowitsch { 551521027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5516412e9a14SMatthew G. Knepley DMLabel label; 551721027e53SStefano Zampini PetscInt pStart, pEnd; 5518412e9a14SMatthew G. Knepley 5519412e9a14SMatthew G. Knepley PetscFunctionBegin; 5520412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 552121027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 55229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 55239566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 552421027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 552521027e53SStefano Zampini mesh->cellTypes[cell - pStart].value_as_uint8 = celltype; 55263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5527412e9a14SMatthew G. Knepley } 5528412e9a14SMatthew G. Knepley 5529d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5530d71ae5a4SJacob Faibussowitsch { 5531c789d87fSToby Isaac PetscSection section; 55323e922f36SToby Isaac PetscInt maxHeight; 5533dd4c3f67SMatthew G. Knepley const char *prefix; 5534552f7358SJed Brown 5535552f7358SJed Brown PetscFunctionBegin; 55369566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5537dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5538dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5539dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 55409566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 55419566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 55429566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 55439566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 55449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 55458f4c458bSMatthew G. Knepley 55469566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 55479566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5548dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5549dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 55503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5551552f7358SJed Brown } 5552552f7358SJed Brown 5553d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5554d71ae5a4SJacob Faibussowitsch { 55556858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 55566858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5557f19dbd58SToby Isaac 5558f19dbd58SToby Isaac PetscFunctionBegin; 5559f19dbd58SToby Isaac *field = NULL; 55609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 55619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 55626858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 55636858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5564f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 55656858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 55666858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5567f19dbd58SToby Isaac } 55683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5569f19dbd58SToby Isaac } 5570f19dbd58SToby Isaac 55717cd05799SMatthew G. Knepley /*@C 55727cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 55737cd05799SMatthew G. Knepley 55747cd05799SMatthew G. Knepley Not Collective 55757cd05799SMatthew G. Knepley 55762fe279fdSBarry Smith Input Parameter: 5577a1cb98faSBarry Smith . dm - The `DMPLEX` object 55787cd05799SMatthew G. Knepley 55797cd05799SMatthew G. Knepley Output Parameter: 5580a1cb98faSBarry Smith . section - The `PetscSection` object 55817cd05799SMatthew G. Knepley 55827cd05799SMatthew G. Knepley Level: developer 55837cd05799SMatthew G. Knepley 55841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 55857cd05799SMatthew G. Knepley @*/ 5586d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5587d71ae5a4SJacob Faibussowitsch { 5588552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5589552f7358SJed Brown 5590552f7358SJed Brown PetscFunctionBegin; 5591552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5592552f7358SJed Brown if (section) *section = mesh->coneSection; 55933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5594552f7358SJed Brown } 5595552f7358SJed Brown 55967cd05799SMatthew G. Knepley /*@C 55977cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 55987cd05799SMatthew G. Knepley 55997cd05799SMatthew G. Knepley Not Collective 56007cd05799SMatthew G. Knepley 56012fe279fdSBarry Smith Input Parameter: 5602a1cb98faSBarry Smith . dm - The `DMPLEX` object 56037cd05799SMatthew G. Knepley 56047cd05799SMatthew G. Knepley Output Parameter: 5605a1cb98faSBarry Smith . section - The `PetscSection` object 56067cd05799SMatthew G. Knepley 56077cd05799SMatthew G. Knepley Level: developer 56087cd05799SMatthew G. Knepley 56091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 56107cd05799SMatthew G. Knepley @*/ 5611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5612d71ae5a4SJacob Faibussowitsch { 56138cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 56148cb4d582SMatthew G. Knepley 56158cb4d582SMatthew G. Knepley PetscFunctionBegin; 56168cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56178cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 56183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56198cb4d582SMatthew G. Knepley } 56208cb4d582SMatthew G. Knepley 56217cd05799SMatthew G. Knepley /*@C 56227cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 56237cd05799SMatthew G. Knepley 56247cd05799SMatthew G. Knepley Not Collective 56257cd05799SMatthew G. Knepley 56262fe279fdSBarry Smith Input Parameter: 5627a1cb98faSBarry Smith . dm - The `DMPLEX` object 56287cd05799SMatthew G. Knepley 56297cd05799SMatthew G. Knepley Output Parameter: 56307cd05799SMatthew G. Knepley . cones - The cone for each point 56317cd05799SMatthew G. Knepley 56327cd05799SMatthew G. Knepley Level: developer 56337cd05799SMatthew G. Knepley 56341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 56357cd05799SMatthew G. Knepley @*/ 5636d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5637d71ae5a4SJacob Faibussowitsch { 5638552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5639552f7358SJed Brown 5640552f7358SJed Brown PetscFunctionBegin; 5641552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5642552f7358SJed Brown if (cones) *cones = mesh->cones; 56433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5644552f7358SJed Brown } 5645552f7358SJed Brown 56467cd05799SMatthew G. Knepley /*@C 56477cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 56487cd05799SMatthew G. Knepley 56497cd05799SMatthew G. Knepley Not Collective 56507cd05799SMatthew G. Knepley 56512fe279fdSBarry Smith Input Parameter: 5652a1cb98faSBarry Smith . dm - The `DMPLEX` object 56537cd05799SMatthew G. Knepley 56547cd05799SMatthew G. Knepley Output Parameter: 5655b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 56567cd05799SMatthew G. Knepley 56577cd05799SMatthew G. Knepley Level: developer 56587cd05799SMatthew G. Knepley 5659b5a892a1SMatthew G. Knepley Notes: 5660a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5661b5a892a1SMatthew G. Knepley 5662a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5663b5a892a1SMatthew G. Knepley 56641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 56657cd05799SMatthew G. Knepley @*/ 5666d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5667d71ae5a4SJacob Faibussowitsch { 5668552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5669552f7358SJed Brown 5670552f7358SJed Brown PetscFunctionBegin; 5671552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5672552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 56733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5674552f7358SJed Brown } 5675552f7358SJed Brown 5676552f7358SJed Brown /******************************** FEM Support **********************************/ 5677552f7358SJed Brown 5678d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5679d2b2dc1eSMatthew G. Knepley { 5680d2b2dc1eSMatthew G. Knepley PetscInt depth; 5681d2b2dc1eSMatthew G. Knepley 5682d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5683d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5684d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5685d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5686d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5687d2b2dc1eSMatthew G. Knepley } 5688d2b2dc1eSMatthew G. Knepley 56895962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 56905962854dSMatthew G. Knepley { 56915962854dSMatthew G. Knepley PetscInt depth; 56925962854dSMatthew G. Knepley 56935962854dSMatthew G. Knepley PetscFunctionBegin; 56945962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 56955962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 56965962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 56975962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 56985962854dSMatthew G. Knepley } 56995962854dSMatthew G. Knepley 57009e8305c2SJed Brown /* 57019e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 57029e8305c2SJed Brown representing a line in the section. 57039e8305c2SJed Brown */ 57045f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor) 5705d71ae5a4SJacob Faibussowitsch { 5706e327e467SRezgar Shakeri PetscObject obj; 5707e327e467SRezgar Shakeri PetscClassId id; 5708e327e467SRezgar Shakeri PetscFE fe = NULL; 5709e327e467SRezgar Shakeri 57109e8305c2SJed Brown PetscFunctionBeginHot; 57119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5712e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5713e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5714e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5715e327e467SRezgar Shakeri 5716e327e467SRezgar Shakeri if (!fe) { 5717e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 57189e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 57199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 57209e8305c2SJed Brown *k = *k / *Nc + 1; 5721e327e467SRezgar Shakeri } else { 5722e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 57235f82726aSMatthew G. Knepley PetscDualSpace dsp; 57245f82726aSMatthew G. Knepley 5725e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 57265f82726aSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &dsp)); 57275f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size)); 5728e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 57295f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous)); 57305f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor)); 57315f82726aSMatthew G. Knepley } 57325f82726aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 57335f82726aSMatthew G. Knepley } 57345f82726aSMatthew G. Knepley 57355f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof) 57365f82726aSMatthew G. Knepley { 57375f82726aSMatthew G. Knepley PetscFunctionBeginHot; 57385f82726aSMatthew G. Knepley if (tensor) { 57395f82726aSMatthew G. Knepley *dof = PetscPowInt(k + 1, dim); 57405f82726aSMatthew G. Knepley } else { 57415f82726aSMatthew G. Knepley switch (dim) { 57425f82726aSMatthew G. Knepley case 1: 57435f82726aSMatthew G. Knepley *dof = k + 1; 57445f82726aSMatthew G. Knepley break; 57455f82726aSMatthew G. Knepley case 2: 57465f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2)) / 2; 57475f82726aSMatthew G. Knepley break; 57485f82726aSMatthew G. Knepley case 3: 57495f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2) * (k + 3)) / 6; 57505f82726aSMatthew G. Knepley break; 57515f82726aSMatthew G. Knepley default: 57525f82726aSMatthew G. Knepley *dof = 0; 57535f82726aSMatthew G. Knepley } 57549e8305c2SJed Brown } 57553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57569e8305c2SJed Brown } 57579e8305c2SJed Brown 5758a4355906SMatthew Knepley /*@ 5759bc1eb3faSJed Brown 5760bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5761bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 576220f4b53cSBarry Smith section provided (or the section of the `DM`). 5763a4355906SMatthew Knepley 5764a4355906SMatthew Knepley Input Parameters: 576520f4b53cSBarry Smith + dm - The `DM` 576620f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 576720f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5768a4355906SMatthew Knepley 5769bc1eb3faSJed Brown Example: 5770bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5771bc1eb3faSJed Brown .vb 5772bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5773bc1eb3faSJed Brown 5774bc1eb3faSJed Brown v4 -- e6 -- v3 5775bc1eb3faSJed Brown | | 5776bc1eb3faSJed Brown e7 c0 e8 5777bc1eb3faSJed Brown | | 5778bc1eb3faSJed Brown v1 -- e5 -- v2 5779bc1eb3faSJed Brown .ve 5780bc1eb3faSJed Brown 5781bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5782bc1eb3faSJed Brown dofs in the order of points, e.g., 5783bc1eb3faSJed Brown .vb 5784bc1eb3faSJed Brown c0 -> [0,1,2,3] 5785bc1eb3faSJed Brown v1 -> [4] 5786bc1eb3faSJed Brown ... 5787bc1eb3faSJed Brown e5 -> [8, 9] 5788bc1eb3faSJed Brown .ve 5789bc1eb3faSJed Brown 5790bc1eb3faSJed Brown which corresponds to the dofs 5791bc1eb3faSJed Brown .vb 5792bc1eb3faSJed Brown 6 10 11 7 5793bc1eb3faSJed Brown 13 2 3 15 5794bc1eb3faSJed Brown 12 0 1 14 5795bc1eb3faSJed Brown 4 8 9 5 5796bc1eb3faSJed Brown .ve 5797bc1eb3faSJed Brown 5798bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5799bc1eb3faSJed Brown .vb 5800bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5801bc1eb3faSJed Brown .ve 5802bc1eb3faSJed Brown 5803bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5804bc1eb3faSJed Brown .vb 5805bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5806bc1eb3faSJed Brown .ve 5807bc1eb3faSJed Brown 5808a4355906SMatthew Knepley Level: developer 5809a4355906SMatthew Knepley 5810da9ac489SAlbert Cowie Notes: 5811a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5812a1cb98faSBarry Smith degree of the basis. 5813a1cb98faSBarry Smith 5814da9ac489SAlbert Cowie This is required to run with libCEED. 5815da9ac489SAlbert Cowie 58161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5817a4355906SMatthew Knepley @*/ 5818d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5819d71ae5a4SJacob Faibussowitsch { 58207391a63aSMatthew G. Knepley DMLabel label; 5821bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 58225f82726aSMatthew G. Knepley PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE; 58233194fc30SMatthew G. Knepley 58243194fc30SMatthew G. Knepley PetscFunctionBegin; 58259566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 58263ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5827a433471fSStefano Zampini if (point < 0) { 5828a433471fSStefano Zampini PetscInt sStart, sEnd; 5829a433471fSStefano Zampini 58309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5831a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5832a433471fSStefano Zampini } 58339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 58349566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 58359566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 58369371c9d4SSatish Balay if (depth == 1) { 58379371c9d4SSatish Balay eStart = point; 58389371c9d4SSatish Balay } else if (depth == dim) { 58397391a63aSMatthew G. Knepley const PetscInt *cone; 58407391a63aSMatthew G. Knepley 58419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5842d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5843d4e6627bSStefano Zampini else if (dim == 3) { 5844d4e6627bSStefano Zampini const PetscInt *cone2; 58459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5846d4e6627bSStefano Zampini eStart = cone2[0]; 584763a3b9bcSJacob 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); 584863a3b9bcSJacob 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); 5849e327e467SRezgar Shakeri 58509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5851bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5852bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5853bb197d40SJed Brown PetscInt *perm; 5854bb197d40SJed Brown 58553194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 58565f82726aSMatthew G. Knepley PetscInt dof; 58575f82726aSMatthew G. Knepley 58585f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58595f82726aSMatthew 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); 58605f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58615f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58625f82726aSMatthew G. Knepley size += dof * Nc; 58633194fc30SMatthew G. Knepley } 58649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 58653194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5866bb197d40SJed Brown switch (d) { 5867babf31e0SJed Brown case 1: 58685f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58695f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 5870babf31e0SJed Brown /* 5871babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5872babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5873babf31e0SJed Brown */ 5874e327e467SRezgar Shakeri if (continuous) { 5875babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 58769371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 58779371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5878babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5879babf31e0SJed Brown foffset = offset; 5880e327e467SRezgar Shakeri } else { 58815f82726aSMatthew G. Knepley PetscInt dof; 58825f82726aSMatthew G. Knepley 58835f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58845f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 58855f82726aSMatthew G. Knepley foffset = offset; 5886e327e467SRezgar Shakeri } 5887babf31e0SJed Brown break; 588889eabcffSMatthew G. Knepley case 2: 58893194fc30SMatthew 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} */ 58905f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58915f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58923194fc30SMatthew G. Knepley /* The SEM order is 58933194fc30SMatthew G. Knepley 58943194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 589589eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 58963194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 58973194fc30SMatthew G. Knepley */ 5898e327e467SRezgar Shakeri if (continuous) { 58993194fc30SMatthew G. Knepley const PetscInt of = 0; 59003194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 59013194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 59023194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 59033194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 59043194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 59053194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 59063194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 59073194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 59083194fc30SMatthew G. Knepley PetscInt o; 59093194fc30SMatthew G. Knepley 59103194fc30SMatthew G. Knepley /* bottom */ 59113194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 59129371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 59139371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59143194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 59153194fc30SMatthew G. Knepley /* middle */ 59163194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 59173194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 59189371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 59199371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59203194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 59213194fc30SMatthew G. Knepley } 59223194fc30SMatthew G. Knepley /* top */ 59233194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 59249371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 59259371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59263194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 59273194fc30SMatthew G. Knepley foffset = offset; 5928e327e467SRezgar Shakeri } else { 59295f82726aSMatthew G. Knepley PetscInt dof; 59305f82726aSMatthew G. Knepley 59315f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 59325f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 59335f82726aSMatthew G. Knepley foffset = offset; 59343194fc30SMatthew G. Knepley } 593589eabcffSMatthew G. Knepley break; 593689eabcffSMatthew G. Knepley case 3: 593789eabcffSMatthew G. Knepley /* The original hex closure is 593889eabcffSMatthew G. Knepley 593989eabcffSMatthew G. Knepley {c, 594089eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 594189eabcffSMatthew 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, 594289eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 594389eabcffSMatthew G. Knepley */ 59445f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 59455f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 594689eabcffSMatthew G. Knepley /* The SEM order is 594789eabcffSMatthew G. Knepley Bottom Slice 594889eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 594989eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 595089eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 595189eabcffSMatthew G. Knepley 595289eabcffSMatthew G. Knepley Middle Slice (j) 595389eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 595489eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 595589eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 595689eabcffSMatthew G. Knepley 595789eabcffSMatthew G. Knepley Top Slice 595889eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 595989eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 596089eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 596189eabcffSMatthew G. Knepley */ 5962e327e467SRezgar Shakeri if (continuous) { 596389eabcffSMatthew G. Knepley const PetscInt oc = 0; 596489eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 596589eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 596689eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 596789eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 596889eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 596989eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 597089eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 597189eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 597289eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 597389eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 597489eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 597589eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 597689eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 597789eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 597889eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 597989eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 598089eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 598189eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 598289eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 598389eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 598489eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 598589eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 598689eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 598789eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 598889eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 598989eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 599089eabcffSMatthew G. Knepley PetscInt o, n; 599189eabcffSMatthew G. Knepley 599289eabcffSMatthew G. Knepley /* Bottom Slice */ 599389eabcffSMatthew G. Knepley /* bottom */ 599489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 59959371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 59969371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 599789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 599889eabcffSMatthew G. Knepley /* middle */ 599989eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 600089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 60019371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 60029371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 60039371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 60049371c9d4SSatish Balay } 600589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 60063194fc30SMatthew G. Knepley } 600789eabcffSMatthew G. Knepley /* top */ 600889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 60099371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 60109371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 601189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 601289eabcffSMatthew G. Knepley 601389eabcffSMatthew G. Knepley /* Middle Slice */ 601489eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 601589eabcffSMatthew G. Knepley /* bottom */ 601689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 60179371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 60189371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 601989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 602089eabcffSMatthew G. Knepley /* middle */ 602189eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 602289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 60239371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60249371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 602589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 602689eabcffSMatthew G. Knepley } 602789eabcffSMatthew G. Knepley /* top */ 602889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 60299371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 60309371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 603189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 603289eabcffSMatthew G. Knepley } 603389eabcffSMatthew G. Knepley 603489eabcffSMatthew G. Knepley /* Top Slice */ 603589eabcffSMatthew G. Knepley /* bottom */ 603689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 60379371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 60389371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 603989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 604089eabcffSMatthew G. Knepley /* middle */ 604189eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 604289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 60439371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60449371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 604589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 604689eabcffSMatthew G. Knepley } 604789eabcffSMatthew G. Knepley /* top */ 604889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 60499371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 60509371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 605189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 605289eabcffSMatthew G. Knepley 605389eabcffSMatthew G. Knepley foffset = offset; 6054e327e467SRezgar Shakeri } else { 60555f82726aSMatthew G. Knepley PetscInt dof; 60565f82726aSMatthew G. Knepley 60575f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60585f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 60595f82726aSMatthew G. Knepley foffset = offset; 606089eabcffSMatthew G. Knepley } 606189eabcffSMatthew G. Knepley break; 6062d71ae5a4SJacob Faibussowitsch default: 6063d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 606489eabcffSMatthew G. Knepley } 606589eabcffSMatthew G. Knepley } 606663a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 60673194fc30SMatthew G. Knepley /* Check permutation */ 60683194fc30SMatthew G. Knepley { 60693194fc30SMatthew G. Knepley PetscInt *check; 60703194fc30SMatthew G. Knepley 60719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 60721dca8a05SBarry Smith for (i = 0; i < size; ++i) { 60731dca8a05SBarry Smith check[i] = -1; 60741dca8a05SBarry 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]); 60751dca8a05SBarry Smith } 60763194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 60771dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 60789566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 60793194fc30SMatthew G. Knepley } 60809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6081a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6082a05c9aa3SJed Brown PetscInt *loc_perm; 60839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6084a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6085a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6086a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6087a05c9aa3SJed Brown } 60889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6089a05c9aa3SJed Brown } 6090bb197d40SJed Brown } 60913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60923194fc30SMatthew G. Knepley } 60933194fc30SMatthew G. Knepley 6094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6095d71ae5a4SJacob Faibussowitsch { 6096e071409bSToby Isaac PetscDS prob; 6097e071409bSToby Isaac PetscInt depth, Nf, h; 6098e071409bSToby Isaac DMLabel label; 6099e071409bSToby Isaac 6100e071409bSToby Isaac PetscFunctionBeginHot; 61019566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6102e071409bSToby Isaac Nf = prob->Nf; 6103e071409bSToby Isaac label = dm->depthLabel; 6104e071409bSToby Isaac *dspace = NULL; 6105e071409bSToby Isaac if (field < Nf) { 6106e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6107e071409bSToby Isaac 6108e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6109e071409bSToby Isaac PetscDualSpace dsp; 6110e071409bSToby Isaac 61119566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 61129566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 61139566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6114e071409bSToby Isaac h = depth - 1 - h; 6115e071409bSToby Isaac if (h) { 61169566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6117e071409bSToby Isaac } else { 6118e071409bSToby Isaac *dspace = dsp; 6119e071409bSToby Isaac } 6120e071409bSToby Isaac } 6121e071409bSToby Isaac } 61223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6123e071409bSToby Isaac } 6124e071409bSToby Isaac 6125d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6126d71ae5a4SJacob Faibussowitsch { 612728351e22SJed Brown PetscScalar *array; 612828351e22SJed Brown const PetscScalar *vArray; 6129d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 61301a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6131552f7358SJed Brown 61321b406b76SMatthew G. Knepley PetscFunctionBeginHot; 61339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 61349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 61359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 61369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 61373f7cbbe7SMatthew G. Knepley if (!values || !*values) { 61389df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61399df71ca4SMatthew G. Knepley PetscInt dof; 6140d9917b9dSMatthew G. Knepley 61419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61429df71ca4SMatthew G. Knepley size += dof; 61439df71ca4SMatthew G. Knepley } 61449df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61459df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61462a3aaacfSMatthew G. Knepley PetscInt dof; 61475a1bb5cfSMatthew G. Knepley 61485a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61505a1bb5cfSMatthew G. Knepley size += dof; 61515a1bb5cfSMatthew G. Knepley } 61523f7cbbe7SMatthew G. Knepley if (!values) { 61533f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 61543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61553f7cbbe7SMatthew G. Knepley } 61569566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6157982e9ed1SMatthew G. Knepley } else { 6158982e9ed1SMatthew G. Knepley array = *values; 6159982e9ed1SMatthew G. Knepley } 61609df71ca4SMatthew G. Knepley size = 0; 616128351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 61629df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61639df71ca4SMatthew G. Knepley PetscInt dof, off, d; 616428351e22SJed Brown const PetscScalar *varr; 6165d9917b9dSMatthew G. Knepley 61669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 61688e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 6169ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61709df71ca4SMatthew G. Knepley size += dof; 61719df71ca4SMatthew G. Knepley } 61729df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61739df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61749df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 61755a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 617628351e22SJed Brown const PetscScalar *varr; 61775a1bb5cfSMatthew G. Knepley 617852ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 61818e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 61825a1bb5cfSMatthew G. Knepley if (o >= 0) { 6183ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61845a1bb5cfSMatthew G. Knepley } else { 6185ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 61865a1bb5cfSMatthew G. Knepley } 61879df71ca4SMatthew G. Knepley size += dof; 61885a1bb5cfSMatthew G. Knepley } 618928351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 61909df71ca4SMatthew G. Knepley if (!*values) { 61915a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 61925a1bb5cfSMatthew G. Knepley *values = array; 61939df71ca4SMatthew G. Knepley } else { 619463a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 61958c312ff3SMatthew G. Knepley *csize = size; 61969df71ca4SMatthew G. Knepley } 61973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61985a1bb5cfSMatthew G. Knepley } 6199d9917b9dSMatthew G. Knepley 620027f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6201d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6202d71ae5a4SJacob Faibussowitsch { 620327f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 620427f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 620527f02ce8SMatthew G. Knepley 62069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 620727f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 620827f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 620927f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 621027f02ce8SMatthew G. Knepley points[q * 2] = r; 621127f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 621227f02ce8SMatthew G. Knepley ++q; 621327f02ce8SMatthew G. Knepley } 621427f02ce8SMatthew G. Knepley } 621527f02ce8SMatthew G. Knepley *numPoints = q; 62163ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 621727f02ce8SMatthew G. Knepley } 621827f02ce8SMatthew G. Knepley 621997529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 622007218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6221d71ae5a4SJacob Faibussowitsch { 622227f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6223923c78e0SToby Isaac PetscInt np, *pts = NULL; 6224923c78e0SToby Isaac 6225923c78e0SToby Isaac PetscFunctionBeginHot; 62269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 622707218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6228923c78e0SToby Isaac PetscInt dof, off; 6229923c78e0SToby Isaac 62309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 62319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 62329566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6233923c78e0SToby Isaac np = dof / 2; 62348e3a54c0SPierre Jolivet pts = PetscSafePointerPlusOffset((PetscInt *)cla, off); 623527f02ce8SMatthew G. Knepley } else { 623607218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 62379566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6238923c78e0SToby Isaac } 6239923c78e0SToby Isaac *numPoints = np; 6240923c78e0SToby Isaac *points = pts; 6241923c78e0SToby Isaac *clp = cla; 62423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6243923c78e0SToby Isaac } 6244923c78e0SToby Isaac 6245d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6246d71ae5a4SJacob Faibussowitsch { 6247923c78e0SToby Isaac PetscFunctionBeginHot; 6248923c78e0SToby Isaac if (!*clPoints) { 62499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6250923c78e0SToby Isaac } else { 62519566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6252923c78e0SToby Isaac } 6253923c78e0SToby Isaac *numPoints = 0; 6254923c78e0SToby Isaac *points = NULL; 6255923c78e0SToby Isaac *clSec = NULL; 6256923c78e0SToby Isaac *clPoints = NULL; 6257923c78e0SToby Isaac *clp = NULL; 62583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6259923c78e0SToby Isaac } 6260923c78e0SToby Isaac 6261d71ae5a4SJacob 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[]) 6262d71ae5a4SJacob Faibussowitsch { 62631a271a75SMatthew G. Knepley PetscInt offset = 0, p; 626497e99dd9SToby Isaac const PetscInt **perms = NULL; 626597e99dd9SToby Isaac const PetscScalar **flips = NULL; 62661a271a75SMatthew G. Knepley 62671a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6268fe02ba77SJed Brown *size = 0; 62699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 627097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 627197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 627297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 627397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 62741a271a75SMatthew G. Knepley PetscInt dof, off, d; 62751a271a75SMatthew G. Knepley const PetscScalar *varr; 62761a271a75SMatthew G. Knepley 62779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 62789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 62798e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 628097e99dd9SToby Isaac if (clperm) { 628197e99dd9SToby Isaac if (perm) { 628297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 62831a271a75SMatthew G. Knepley } else { 628497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 628597e99dd9SToby Isaac } 628697e99dd9SToby Isaac if (flip) { 628797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 628897e99dd9SToby Isaac } 628997e99dd9SToby Isaac } else { 629097e99dd9SToby Isaac if (perm) { 629197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 629297e99dd9SToby Isaac } else { 629397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 629497e99dd9SToby Isaac } 629597e99dd9SToby Isaac if (flip) { 629697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 62971a271a75SMatthew G. Knepley } 62981a271a75SMatthew G. Knepley } 629997e99dd9SToby Isaac offset += dof; 630097e99dd9SToby Isaac } 63019566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 63021a271a75SMatthew G. Knepley *size = offset; 63033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63041a271a75SMatthew G. Knepley } 63051a271a75SMatthew G. Knepley 6306d71ae5a4SJacob 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[]) 6307d71ae5a4SJacob Faibussowitsch { 63081a271a75SMatthew G. Knepley PetscInt offset = 0, f; 63091a271a75SMatthew G. Knepley 63101a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6311fe02ba77SJed Brown *size = 0; 63121a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 631397e99dd9SToby Isaac PetscInt p; 631497e99dd9SToby Isaac const PetscInt **perms = NULL; 631597e99dd9SToby Isaac const PetscScalar **flips = NULL; 63161a271a75SMatthew G. Knepley 63179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 631897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 631997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 632097e99dd9SToby Isaac PetscInt fdof, foff, b; 63211a271a75SMatthew G. Knepley const PetscScalar *varr; 632297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63241a271a75SMatthew G. Knepley 63259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 63269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 63271a271a75SMatthew G. Knepley varr = &vArray[foff]; 632897e99dd9SToby Isaac if (clperm) { 63299371c9d4SSatish Balay if (perm) { 6330ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 63311a271a75SMatthew G. Knepley } else { 6332ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 63339371c9d4SSatish Balay } 63349371c9d4SSatish Balay if (flip) { 6335ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 63369371c9d4SSatish Balay } 63379371c9d4SSatish Balay } else { 63389371c9d4SSatish Balay if (perm) { 6339ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 63409371c9d4SSatish Balay } else { 6341ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 63429371c9d4SSatish Balay } 63439371c9d4SSatish Balay if (flip) { 6344ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 63459371c9d4SSatish Balay } 63461a271a75SMatthew G. Knepley } 634797e99dd9SToby Isaac offset += fdof; 63481a271a75SMatthew G. Knepley } 63499566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 63501a271a75SMatthew G. Knepley } 63511a271a75SMatthew G. Knepley *size = offset; 63523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63531a271a75SMatthew G. Knepley } 63541a271a75SMatthew G. Knepley 6355e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 635607218a29SMatthew G. Knepley { 635707218a29SMatthew G. Knepley PetscSection clSection; 635807218a29SMatthew G. Knepley IS clPoints; 635907218a29SMatthew G. Knepley PetscInt *points = NULL; 6360e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 636107218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 636207218a29SMatthew G. Knepley 636307218a29SMatthew G. Knepley PetscFunctionBeginHot; 636407218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 636507218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 636607218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6367e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 636807218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 636907218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 637007218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 637107218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 637207218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 637307218a29SMatthew G. Knepley } 637407218a29SMatthew G. Knepley /* Get points */ 637507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 637607218a29SMatthew G. Knepley /* Get sizes */ 637707218a29SMatthew G. Knepley asize = 0; 637807218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 637907218a29SMatthew G. Knepley PetscInt dof; 638007218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 638107218a29SMatthew G. Knepley asize += dof; 638207218a29SMatthew G. Knepley } 638307218a29SMatthew G. Knepley if (values) { 638407218a29SMatthew G. Knepley const PetscScalar *vArray; 638507218a29SMatthew G. Knepley PetscInt size; 638607218a29SMatthew G. Knepley 638707218a29SMatthew G. Knepley if (*values) { 638807218a29SMatthew 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); 638907218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6390e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 639107218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 639207218a29SMatthew G. Knepley /* Get values */ 639307218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 639407218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 639507218a29SMatthew 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); 639607218a29SMatthew G. Knepley /* Cleanup array */ 639707218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 639807218a29SMatthew G. Knepley } 639907218a29SMatthew G. Knepley if (csize) *csize = asize; 640007218a29SMatthew G. Knepley /* Cleanup points */ 640107218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 640207218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 640307218a29SMatthew G. Knepley } 640407218a29SMatthew G. Knepley 6405552f7358SJed Brown /*@C 6406552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6407552f7358SJed Brown 6408552f7358SJed Brown Not collective 6409552f7358SJed Brown 6410552f7358SJed Brown Input Parameters: 6411a1cb98faSBarry Smith + dm - The `DM` 641220f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6413552f7358SJed Brown . v - The local vector 6414a1cb98faSBarry Smith - point - The point in the `DM` 6415552f7358SJed Brown 64166b867d5aSJose E. Roman Input/Output Parameters: 641720f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 641820f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically; 641920f4b53cSBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed 642022c1ee49SMatthew G. Knepley 6421552f7358SJed Brown Level: intermediate 6422552f7358SJed Brown 6423a1cb98faSBarry Smith Notes: 642420f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6425a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6426a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6427a1cb98faSBarry Smith 6428a1cb98faSBarry Smith A typical use could be 6429a1cb98faSBarry Smith .vb 6430a1cb98faSBarry Smith values = NULL; 6431a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6432a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6433a1cb98faSBarry Smith <Compute on closure> 6434a1cb98faSBarry Smith } 6435a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6436a1cb98faSBarry Smith .ve 6437a1cb98faSBarry Smith or 6438a1cb98faSBarry Smith .vb 6439a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6440a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6441a1cb98faSBarry Smith clSize = clMaxSize; 6442a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6443a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6444a1cb98faSBarry Smith <Compute on closure> 6445a1cb98faSBarry Smith } 6446a1cb98faSBarry Smith } 6447a1cb98faSBarry Smith PetscFree(values); 6448a1cb98faSBarry Smith .ve 6449a1cb98faSBarry Smith 645060225df5SJacob Faibussowitsch Fortran Notes: 645120f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6452a1cb98faSBarry Smith 64531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6454552f7358SJed Brown @*/ 6455d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6456d71ae5a4SJacob Faibussowitsch { 6457d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6458e8e188d2SZach Atkins PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 64593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6460552f7358SJed Brown } 6461552f7358SJed Brown 6462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6463d71ae5a4SJacob Faibussowitsch { 6464e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6465e5c487bfSMatthew G. Knepley PetscSection clSection; 6466e5c487bfSMatthew G. Knepley IS clPoints; 6467e5c487bfSMatthew G. Knepley PetscScalar *array; 6468e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6469e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6470c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6471c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6472e5c487bfSMatthew G. Knepley 6473e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6474e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64759566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6476e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6477e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 64799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 64809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6481e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 64829566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 64833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6484e5c487bfSMatthew G. Knepley } 6485e5c487bfSMatthew G. Knepley /* Get points */ 648607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6487c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6488c459fbc1SJed Brown PetscInt dof; 64899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6490c459fbc1SJed Brown clsize += dof; 6491c459fbc1SJed Brown } 64929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6493e5c487bfSMatthew G. Knepley /* Filter points */ 6494e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6495e5c487bfSMatthew G. Knepley PetscInt dep; 6496e5c487bfSMatthew G. Knepley 64979566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6498e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6499e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6500e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6501e5c487bfSMatthew G. Knepley ++Np; 6502e5c487bfSMatthew G. Knepley } 6503e5c487bfSMatthew G. Knepley /* Get array */ 6504e5c487bfSMatthew G. Knepley if (!values || !*values) { 6505e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6506e5c487bfSMatthew G. Knepley 6507e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 65089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6509e5c487bfSMatthew G. Knepley asize += dof; 6510e5c487bfSMatthew G. Knepley } 6511e5c487bfSMatthew G. Knepley if (!values) { 65129566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6513e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 65143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6515e5c487bfSMatthew G. Knepley } 65169566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6517e5c487bfSMatthew G. Knepley } else { 6518e5c487bfSMatthew G. Knepley array = *values; 6519e5c487bfSMatthew G. Knepley } 65209566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6521e5c487bfSMatthew G. Knepley /* Get values */ 65229566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 65239566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6524e5c487bfSMatthew G. Knepley /* Cleanup points */ 65259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6526e5c487bfSMatthew G. Knepley /* Cleanup array */ 65279566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6528e5c487bfSMatthew G. Knepley if (!*values) { 6529e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6530e5c487bfSMatthew G. Knepley *values = array; 6531e5c487bfSMatthew G. Knepley } else { 653263a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6533e5c487bfSMatthew G. Knepley *csize = size; 6534e5c487bfSMatthew G. Knepley } 65353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6536e5c487bfSMatthew G. Knepley } 6537e5c487bfSMatthew G. Knepley 6538552f7358SJed Brown /*@C 6539552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6540552f7358SJed Brown 6541552f7358SJed Brown Not collective 6542552f7358SJed Brown 6543552f7358SJed Brown Input Parameters: 6544a1cb98faSBarry Smith + dm - The `DM` 654520f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6546552f7358SJed Brown . v - The local vector 6547a1cb98faSBarry Smith . point - The point in the `DM` 654820f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6549552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6550552f7358SJed Brown 6551552f7358SJed Brown Level: intermediate 6552552f7358SJed Brown 6553a1cb98faSBarry Smith Note: 655420f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6555a1cb98faSBarry Smith 655660225df5SJacob Faibussowitsch Fortran Notes: 655720f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6558a1cb98faSBarry Smith 65591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6560552f7358SJed Brown @*/ 6561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6562d71ae5a4SJacob Faibussowitsch { 6563552f7358SJed Brown PetscInt size = 0; 6564552f7358SJed Brown 6565552f7358SJed Brown PetscFunctionBegin; 6566552f7358SJed Brown /* Should work without recalculating size */ 65679566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6568c9fdaa05SMatthew G. Knepley *values = NULL; 65693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6570552f7358SJed Brown } 6571552f7358SJed Brown 6572d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6573d71ae5a4SJacob Faibussowitsch { 65749371c9d4SSatish Balay *x += y; 65759371c9d4SSatish Balay } 6576d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6577d71ae5a4SJacob Faibussowitsch { 65789371c9d4SSatish Balay *x = y; 65799371c9d4SSatish Balay } 6580552f7358SJed Brown 6581d71ae5a4SJacob 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[]) 6582d71ae5a4SJacob Faibussowitsch { 6583552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6584552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6585552f7358SJed Brown PetscScalar *a; 6586552f7358SJed Brown PetscInt off, cind = 0, k; 6587552f7358SJed Brown 6588552f7358SJed Brown PetscFunctionBegin; 65899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 65909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6591552f7358SJed Brown a = &array[off]; 6592552f7358SJed Brown if (!cdof || setBC) { 659397e99dd9SToby Isaac if (clperm) { 65949371c9d4SSatish Balay if (perm) { 6595ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6596552f7358SJed Brown } else { 6597ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 65989371c9d4SSatish Balay } 65999371c9d4SSatish Balay } else { 66009371c9d4SSatish Balay if (perm) { 6601ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 66029371c9d4SSatish Balay } else { 6603ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 66049371c9d4SSatish Balay } 6605552f7358SJed Brown } 6606552f7358SJed Brown } else { 66079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 660897e99dd9SToby Isaac if (clperm) { 66099371c9d4SSatish Balay if (perm) { 66109371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 66119371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66129371c9d4SSatish Balay ++cind; 66139371c9d4SSatish Balay continue; 66149371c9d4SSatish Balay } 661597e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6616552f7358SJed Brown } 6617552f7358SJed Brown } else { 6618552f7358SJed Brown for (k = 0; k < dof; ++k) { 66199371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66209371c9d4SSatish Balay ++cind; 66219371c9d4SSatish Balay continue; 66229371c9d4SSatish Balay } 662397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 662497e99dd9SToby Isaac } 662597e99dd9SToby Isaac } 662697e99dd9SToby Isaac } else { 662797e99dd9SToby Isaac if (perm) { 662897e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66299371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66309371c9d4SSatish Balay ++cind; 66319371c9d4SSatish Balay continue; 66329371c9d4SSatish Balay } 663397e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 663497e99dd9SToby Isaac } 663597e99dd9SToby Isaac } else { 663697e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66379371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66389371c9d4SSatish Balay ++cind; 66399371c9d4SSatish Balay continue; 66409371c9d4SSatish Balay } 664197e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 664297e99dd9SToby Isaac } 6643552f7358SJed Brown } 6644552f7358SJed Brown } 6645552f7358SJed Brown } 66463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6647552f7358SJed Brown } 6648552f7358SJed Brown 6649d71ae5a4SJacob 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[]) 6650d71ae5a4SJacob Faibussowitsch { 6651a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6652a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6653a5e93ea8SMatthew G. Knepley PetscScalar *a; 6654a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6655a5e93ea8SMatthew G. Knepley 6656a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 66579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 66589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6659a5e93ea8SMatthew G. Knepley a = &array[off]; 6660a5e93ea8SMatthew G. Knepley if (cdof) { 66619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 666297e99dd9SToby Isaac if (clperm) { 666397e99dd9SToby Isaac if (perm) { 6664a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6665a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 666697e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 666797e99dd9SToby Isaac cind++; 6668a5e93ea8SMatthew G. Knepley } 6669a5e93ea8SMatthew G. Knepley } 6670a5e93ea8SMatthew G. Knepley } else { 6671a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6672a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 667397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 667497e99dd9SToby Isaac cind++; 667597e99dd9SToby Isaac } 667697e99dd9SToby Isaac } 667797e99dd9SToby Isaac } 667897e99dd9SToby Isaac } else { 667997e99dd9SToby Isaac if (perm) { 668097e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 668197e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 668297e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 668397e99dd9SToby Isaac cind++; 668497e99dd9SToby Isaac } 668597e99dd9SToby Isaac } 668697e99dd9SToby Isaac } else { 668797e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 668897e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 668997e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 669097e99dd9SToby Isaac cind++; 669197e99dd9SToby Isaac } 6692a5e93ea8SMatthew G. Knepley } 6693a5e93ea8SMatthew G. Knepley } 6694a5e93ea8SMatthew G. Knepley } 6695a5e93ea8SMatthew G. Knepley } 66963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6697a5e93ea8SMatthew G. Knepley } 6698a5e93ea8SMatthew G. Knepley 6699d71ae5a4SJacob 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[]) 6700d71ae5a4SJacob Faibussowitsch { 6701552f7358SJed Brown PetscScalar *a; 67021a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 67031a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 670497e99dd9SToby Isaac PetscInt cind = 0, b; 6705552f7358SJed Brown 6706552f7358SJed Brown PetscFunctionBegin; 67079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67101a271a75SMatthew G. Knepley a = &array[foff]; 6711552f7358SJed Brown if (!fcdof || setBC) { 671297e99dd9SToby Isaac if (clperm) { 67139371c9d4SSatish Balay if (perm) { 6714ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6715552f7358SJed Brown } else { 6716ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 67179371c9d4SSatish Balay } 67189371c9d4SSatish Balay } else { 67199371c9d4SSatish Balay if (perm) { 6720ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 67219371c9d4SSatish Balay } else { 6722ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 67239371c9d4SSatish Balay } 6724552f7358SJed Brown } 6725552f7358SJed Brown } else { 67269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 672797e99dd9SToby Isaac if (clperm) { 672897e99dd9SToby Isaac if (perm) { 672997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67309371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67319371c9d4SSatish Balay ++cind; 67329371c9d4SSatish Balay continue; 67339371c9d4SSatish Balay } 673497e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6735552f7358SJed Brown } 6736552f7358SJed Brown } else { 673797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67389371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67399371c9d4SSatish Balay ++cind; 67409371c9d4SSatish Balay continue; 67419371c9d4SSatish Balay } 674297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 674397e99dd9SToby Isaac } 674497e99dd9SToby Isaac } 674597e99dd9SToby Isaac } else { 674697e99dd9SToby Isaac if (perm) { 674797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67489371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67499371c9d4SSatish Balay ++cind; 67509371c9d4SSatish Balay continue; 67519371c9d4SSatish Balay } 675297e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 675397e99dd9SToby Isaac } 675497e99dd9SToby Isaac } else { 675597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67569371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67579371c9d4SSatish Balay ++cind; 67589371c9d4SSatish Balay continue; 67599371c9d4SSatish Balay } 676097e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6761552f7358SJed Brown } 6762552f7358SJed Brown } 6763552f7358SJed Brown } 6764552f7358SJed Brown } 67651a271a75SMatthew G. Knepley *offset += fdof; 67663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6767552f7358SJed Brown } 6768552f7358SJed Brown 6769d71ae5a4SJacob 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[]) 6770d71ae5a4SJacob Faibussowitsch { 6771a5e93ea8SMatthew G. Knepley PetscScalar *a; 67721a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 67731a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67745da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6775ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6776a5e93ea8SMatthew G. Knepley 6777a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 67789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 67799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67821a271a75SMatthew G. Knepley a = &array[foff]; 6783a5e93ea8SMatthew G. Knepley if (fcdof) { 6784ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 67859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 678697e99dd9SToby Isaac if (clperm) { 678797e99dd9SToby Isaac if (perm) { 6788ba322698SMatthew G. Knepley if (comps) { 6789ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6790ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67919371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67929371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67939371c9d4SSatish Balay ncSet = PETSC_TRUE; 67949371c9d4SSatish Balay } 67959371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67969371c9d4SSatish Balay ++cind; 67979371c9d4SSatish Balay fcSet = PETSC_TRUE; 67989371c9d4SSatish Balay } 6799ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6800ba322698SMatthew G. Knepley } 6801ba322698SMatthew G. Knepley } else { 680297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 680397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 680497e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6805a5e93ea8SMatthew G. Knepley ++cind; 6806a5e93ea8SMatthew G. Knepley } 6807a5e93ea8SMatthew G. Knepley } 6808ba322698SMatthew G. Knepley } 6809ba322698SMatthew G. Knepley } else { 6810ba322698SMatthew G. Knepley if (comps) { 6811ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6812ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68139371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68149371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68159371c9d4SSatish Balay ncSet = PETSC_TRUE; 68169371c9d4SSatish Balay } 68179371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68189371c9d4SSatish Balay ++cind; 68199371c9d4SSatish Balay fcSet = PETSC_TRUE; 68209371c9d4SSatish Balay } 6821ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6822ba322698SMatthew G. Knepley } 6823a5e93ea8SMatthew G. Knepley } else { 682497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 682597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 682697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 682797e99dd9SToby Isaac ++cind; 682897e99dd9SToby Isaac } 682997e99dd9SToby Isaac } 683097e99dd9SToby Isaac } 6831ba322698SMatthew G. Knepley } 683297e99dd9SToby Isaac } else { 683397e99dd9SToby Isaac if (perm) { 6834ba322698SMatthew G. Knepley if (comps) { 6835ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6836ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68379371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68389371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68399371c9d4SSatish Balay ncSet = PETSC_TRUE; 68409371c9d4SSatish Balay } 68419371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68429371c9d4SSatish Balay ++cind; 68439371c9d4SSatish Balay fcSet = PETSC_TRUE; 68449371c9d4SSatish Balay } 6845ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6846ba322698SMatthew G. Knepley } 6847ba322698SMatthew G. Knepley } else { 684897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 684997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 685097e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 685197e99dd9SToby Isaac ++cind; 685297e99dd9SToby Isaac } 685397e99dd9SToby Isaac } 6854ba322698SMatthew G. Knepley } 6855ba322698SMatthew G. Knepley } else { 6856ba322698SMatthew G. Knepley if (comps) { 6857ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6858ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68599371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68609371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68619371c9d4SSatish Balay ncSet = PETSC_TRUE; 68629371c9d4SSatish Balay } 68639371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68649371c9d4SSatish Balay ++cind; 68659371c9d4SSatish Balay fcSet = PETSC_TRUE; 68669371c9d4SSatish Balay } 6867ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6868ba322698SMatthew G. Knepley } 686997e99dd9SToby Isaac } else { 687097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 687197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 687297e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6873a5e93ea8SMatthew G. Knepley ++cind; 6874a5e93ea8SMatthew G. Knepley } 6875a5e93ea8SMatthew G. Knepley } 6876a5e93ea8SMatthew G. Knepley } 6877a5e93ea8SMatthew G. Knepley } 6878a5e93ea8SMatthew G. Knepley } 6879ba322698SMatthew G. Knepley } 68801a271a75SMatthew G. Knepley *offset += fdof; 68813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6882a5e93ea8SMatthew G. Knepley } 6883a5e93ea8SMatthew G. Knepley 6884d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6885d71ae5a4SJacob Faibussowitsch { 6886552f7358SJed Brown PetscScalar *array; 68871b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 68881b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6889552f7358SJed Brown 68901b406b76SMatthew G. Knepley PetscFunctionBeginHot; 68919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 68929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 68939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 68949566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 68959566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6896b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6897b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6898b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6899b6ebb6e6SMatthew G. Knepley 69009371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 69019371c9d4SSatish Balay dof = 0; 69029371c9d4SSatish Balay continue; 69039371c9d4SSatish Balay } 69049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6905b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6906b6ebb6e6SMatthew G. Knepley { 6907b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6908b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6909b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6910b6ebb6e6SMatthew G. Knepley 69119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 69129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6913b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6914b6ebb6e6SMatthew G. Knepley if (!cdof) { 6915b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6916ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6917b6ebb6e6SMatthew G. Knepley } else { 6918ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6919b6ebb6e6SMatthew G. Knepley } 6920b6ebb6e6SMatthew G. Knepley } else { 69219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6922b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6923b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69249371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69259371c9d4SSatish Balay ++cind; 69269371c9d4SSatish Balay continue; 69279371c9d4SSatish Balay } 6928b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6929b6ebb6e6SMatthew G. Knepley } 6930b6ebb6e6SMatthew G. Knepley } else { 6931b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69329371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69339371c9d4SSatish Balay ++cind; 69349371c9d4SSatish Balay continue; 69359371c9d4SSatish Balay } 6936b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6937b6ebb6e6SMatthew G. Knepley } 6938b6ebb6e6SMatthew G. Knepley } 6939b6ebb6e6SMatthew G. Knepley } 6940b6ebb6e6SMatthew G. Knepley } 6941b6ebb6e6SMatthew G. Knepley } 69429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 69433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6944b6ebb6e6SMatthew G. Knepley } 69451b406b76SMatthew G. Knepley 69461b406b76SMatthew G. Knepley /*@C 694720f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 69481b406b76SMatthew G. Knepley 69491b406b76SMatthew G. Knepley Not collective 69501b406b76SMatthew G. Knepley 69511b406b76SMatthew G. Knepley Input Parameters: 6952a1cb98faSBarry Smith + dm - The `DM` 695320f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 69541b406b76SMatthew G. Knepley . v - The local vector 695520f4b53cSBarry Smith . point - The point in the `DM` 69561b406b76SMatthew G. Knepley . values - The array of values 6957a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6958a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 69591b406b76SMatthew G. Knepley 69601b406b76SMatthew G. Knepley Level: intermediate 69611b406b76SMatthew G. Knepley 69621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 69631b406b76SMatthew G. Knepley @*/ 6964d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6965d71ae5a4SJacob Faibussowitsch { 69661b406b76SMatthew G. Knepley PetscSection clSection; 69671b406b76SMatthew G. Knepley IS clPoints; 69681b406b76SMatthew G. Knepley PetscScalar *array; 69691b406b76SMatthew G. Knepley PetscInt *points = NULL; 697027f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6971c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 69721b406b76SMatthew G. Knepley 69731a271a75SMatthew G. Knepley PetscFunctionBeginHot; 69741b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 69759566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 69761a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 69771a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 69789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 69799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 69801b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 69819566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 69823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69831b406b76SMatthew G. Knepley } 69841a271a75SMatthew G. Knepley /* Get points */ 698507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6986c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6987c459fbc1SJed Brown PetscInt dof; 69889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6989c459fbc1SJed Brown clsize += dof; 6990c459fbc1SJed Brown } 69919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 69921a271a75SMatthew G. Knepley /* Get array */ 69939566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 69941a271a75SMatthew G. Knepley /* Get values */ 6995ef90cfe2SMatthew G. Knepley if (numFields > 0) { 699697e99dd9SToby Isaac PetscInt offset = 0, f; 6997552f7358SJed Brown for (f = 0; f < numFields; ++f) { 699897e99dd9SToby Isaac const PetscInt **perms = NULL; 699997e99dd9SToby Isaac const PetscScalar **flips = NULL; 700097e99dd9SToby Isaac 70019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7002552f7358SJed Brown switch (mode) { 7003552f7358SJed Brown case INSERT_VALUES: 700497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 700597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 700697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 700797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70083ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 70099371c9d4SSatish Balay } 70109371c9d4SSatish Balay break; 7011552f7358SJed Brown case INSERT_ALL_VALUES: 701297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 701397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 701497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 701597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70163ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 70179371c9d4SSatish Balay } 70189371c9d4SSatish Balay break; 7019a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 702097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 702197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 702297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 702397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70243ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 70259371c9d4SSatish Balay } 70269371c9d4SSatish Balay break; 7027552f7358SJed Brown case ADD_VALUES: 702897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 702997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 703097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 703197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70323ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 70339371c9d4SSatish Balay } 70349371c9d4SSatish Balay break; 7035552f7358SJed Brown case ADD_ALL_VALUES: 703697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 703797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 703897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 703997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70403ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 70419371c9d4SSatish Balay } 70429371c9d4SSatish Balay break; 7043304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 704497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 704597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 704697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 704797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70483ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 70499371c9d4SSatish Balay } 70509371c9d4SSatish Balay break; 7051d71ae5a4SJacob Faibussowitsch default: 7052d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7053552f7358SJed Brown } 70549566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 70551a271a75SMatthew G. Knepley } 7056552f7358SJed Brown } else { 70571a271a75SMatthew G. Knepley PetscInt dof, off; 705897e99dd9SToby Isaac const PetscInt **perms = NULL; 705997e99dd9SToby Isaac const PetscScalar **flips = NULL; 70601a271a75SMatthew G. Knepley 70619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 7062552f7358SJed Brown switch (mode) { 7063552f7358SJed Brown case INSERT_VALUES: 706497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 706597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 706697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 706797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70693ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70709371c9d4SSatish Balay } 70719371c9d4SSatish Balay break; 7072552f7358SJed Brown case INSERT_ALL_VALUES: 707397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 707497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 707597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 707697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70783ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 70799371c9d4SSatish Balay } 70809371c9d4SSatish Balay break; 7081a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 708297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 708397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 708497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 708597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70873ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 70889371c9d4SSatish Balay } 70899371c9d4SSatish Balay break; 7090552f7358SJed Brown case ADD_VALUES: 709197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 709297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 709397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 709497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70963ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70979371c9d4SSatish Balay } 70989371c9d4SSatish Balay break; 7099552f7358SJed Brown case ADD_ALL_VALUES: 710097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 710197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 710297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 710397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71053ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 71069371c9d4SSatish Balay } 71079371c9d4SSatish Balay break; 7108304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 710997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 711097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 711197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 711297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71143ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 71159371c9d4SSatish Balay } 71169371c9d4SSatish Balay break; 7117d71ae5a4SJacob Faibussowitsch default: 7118d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7119552f7358SJed Brown } 71209566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7121552f7358SJed Brown } 71221a271a75SMatthew G. Knepley /* Cleanup points */ 71239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 71241a271a75SMatthew G. Knepley /* Cleanup array */ 71259566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 71263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7127552f7358SJed Brown } 7128552f7358SJed Brown 71295f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7130d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7131d71ae5a4SJacob Faibussowitsch { 71325f790a90SMatthew G. Knepley PetscFunctionBegin; 713311cc89d2SBarry Smith *contains = PETSC_TRUE; 71345f790a90SMatthew G. Knepley if (label) { 7135d6177c40SToby Isaac PetscInt fdof; 71365f790a90SMatthew G. Knepley 713711cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 713811cc89d2SBarry Smith if (!*contains) { 71399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 71405f790a90SMatthew G. Knepley *offset += fdof; 71413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71425f790a90SMatthew G. Knepley } 71435f790a90SMatthew G. Knepley } 71443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71455f790a90SMatthew G. Knepley } 71465f790a90SMatthew G. Knepley 714797529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7148d71ae5a4SJacob 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) 7149d71ae5a4SJacob Faibussowitsch { 7150e07394fbSMatthew G. Knepley PetscSection clSection; 7151e07394fbSMatthew G. Knepley IS clPoints; 7152e07394fbSMatthew G. Knepley PetscScalar *array; 7153e07394fbSMatthew G. Knepley PetscInt *points = NULL; 715497529cf3SJed Brown const PetscInt *clp; 7155e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 715697e99dd9SToby Isaac PetscInt offset = 0, f; 7157e07394fbSMatthew G. Knepley 7158e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7159e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 71609566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7161e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7162e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 71639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7164e07394fbSMatthew G. Knepley /* Get points */ 716507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7166e07394fbSMatthew G. Knepley /* Get array */ 71679566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7168e07394fbSMatthew G. Knepley /* Get values */ 7169e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 717097e99dd9SToby Isaac const PetscInt **perms = NULL; 717197e99dd9SToby Isaac const PetscScalar **flips = NULL; 717211cc89d2SBarry Smith PetscBool contains; 717397e99dd9SToby Isaac 7174e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7175e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7176e07394fbSMatthew G. Knepley PetscInt fdof; 71779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7178e07394fbSMatthew G. Knepley offset += fdof; 7179e07394fbSMatthew G. Knepley } 7180e07394fbSMatthew G. Knepley continue; 7181e07394fbSMatthew G. Knepley } 71829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7183e07394fbSMatthew G. Knepley switch (mode) { 7184e07394fbSMatthew G. Knepley case INSERT_VALUES: 718597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 718697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 718797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 718897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 718911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 719011cc89d2SBarry Smith if (!contains) continue; 71919566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 71929371c9d4SSatish Balay } 71939371c9d4SSatish Balay break; 7194e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 719597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 719697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 719797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 719897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 719911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 720011cc89d2SBarry Smith if (!contains) continue; 72019566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 72029371c9d4SSatish Balay } 72039371c9d4SSatish Balay break; 7204e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 720597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 720697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 720797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 720897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 720911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 721011cc89d2SBarry Smith if (!contains) continue; 72119566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 72129371c9d4SSatish Balay } 72139371c9d4SSatish Balay break; 7214e07394fbSMatthew G. Knepley case ADD_VALUES: 721597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 721697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 721797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 721897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 721911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 722011cc89d2SBarry Smith if (!contains) continue; 72219566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 72229371c9d4SSatish Balay } 72239371c9d4SSatish Balay break; 7224e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 722597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 722697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 722797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 722897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 722911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 723011cc89d2SBarry Smith if (!contains) continue; 72319566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 72329371c9d4SSatish Balay } 72339371c9d4SSatish Balay break; 7234d71ae5a4SJacob Faibussowitsch default: 7235d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7236e07394fbSMatthew G. Knepley } 72379566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7238e07394fbSMatthew G. Knepley } 7239e07394fbSMatthew G. Knepley /* Cleanup points */ 72409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7241e07394fbSMatthew G. Knepley /* Cleanup array */ 72429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 72433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7244e07394fbSMatthew G. Knepley } 7245e07394fbSMatthew G. Knepley 7246d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7247d71ae5a4SJacob Faibussowitsch { 7248552f7358SJed Brown PetscMPIInt rank; 7249552f7358SJed Brown PetscInt i, j; 7250552f7358SJed Brown 7251552f7358SJed Brown PetscFunctionBegin; 72529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 725363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 725463a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 725563a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7256b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 72573ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7258b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 72599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7260b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7261519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 72629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7263552f7358SJed Brown #else 72649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7265552f7358SJed Brown #endif 7266552f7358SJed Brown } 72679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7268552f7358SJed Brown } 72693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7270552f7358SJed Brown } 7271552f7358SJed Brown 727205586334SMatthew G. Knepley /* 727305586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 727405586334SMatthew G. Knepley 727505586334SMatthew G. Knepley Input Parameters: 727605586334SMatthew G. Knepley + section - The section for this data layout 727736fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 727805586334SMatthew G. Knepley . point - The point contributing dofs with these indices 727905586334SMatthew G. Knepley . off - The global offset of this point 728005586334SMatthew G. Knepley . loff - The local offset of each field 7281a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 728205586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 728305586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 728405586334SMatthew G. Knepley 728505586334SMatthew G. Knepley Output Parameter: 728605586334SMatthew G. Knepley . indices - Indices for dofs on this point 728705586334SMatthew G. Knepley 728805586334SMatthew G. Knepley Level: developer 728905586334SMatthew G. Knepley 729005586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 729105586334SMatthew G. Knepley */ 7292d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7293d71ae5a4SJacob Faibussowitsch { 7294e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7295552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7296552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7297552f7358SJed Brown PetscInt cind = 0, k; 7298552f7358SJed Brown 7299552f7358SJed Brown PetscFunctionBegin; 730008401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 73029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7303552f7358SJed Brown if (!cdof || setBC) { 730405586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 730505586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 730605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 730705586334SMatthew G. Knepley 730805586334SMatthew G. Knepley indices[ind] = off + k; 7309552f7358SJed Brown } 7310552f7358SJed Brown } else { 73119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 73124acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 731305586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 731405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 731505586334SMatthew G. Knepley 73164acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 73174acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 731805586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 73194acb8e1eSToby Isaac ++cind; 73204acb8e1eSToby Isaac } else { 732136fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7322552f7358SJed Brown } 7323552f7358SJed Brown } 7324552f7358SJed Brown } 7325e6ccafaeSMatthew G Knepley *loff += dof; 73263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7327552f7358SJed Brown } 7328552f7358SJed Brown 73297e29afd2SMatthew G. Knepley /* 733036fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 73317e29afd2SMatthew G. Knepley 733236fa2b79SJed Brown Input Parameters: 733336fa2b79SJed Brown + section - a section (global or local) 733420f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 733536fa2b79SJed Brown . point - point within section 733636fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 733736fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 733836fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 733936fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 734036fa2b79SJed Brown . permsoff - offset 734136fa2b79SJed Brown - indperm - index permutation 734236fa2b79SJed Brown 734336fa2b79SJed Brown Output Parameter: 734436fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 734536fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 734636fa2b79SJed Brown 734736fa2b79SJed Brown Notes: 734836fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 734936fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 735036fa2b79SJed Brown in the local vector. 735136fa2b79SJed Brown 735236fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 735336fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 735436fa2b79SJed Brown 735536fa2b79SJed Brown Developer Note: 735636fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 735736fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 735836fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 735936fa2b79SJed Brown 736036fa2b79SJed Brown Example: 736136fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 736236fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 736336fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 736436fa2b79SJed 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. 736536fa2b79SJed Brown 736636fa2b79SJed Brown Level: developer 73677e29afd2SMatthew G. Knepley */ 7368d71ae5a4SJacob 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[]) 7369d71ae5a4SJacob Faibussowitsch { 7370552f7358SJed Brown PetscInt numFields, foff, f; 7371552f7358SJed Brown 7372552f7358SJed Brown PetscFunctionBegin; 737308401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7375552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 73764acb8e1eSToby Isaac PetscInt fdof, cfdof; 7377552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 73784acb8e1eSToby Isaac PetscInt cind = 0, b; 73794acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7380552f7358SJed Brown 73819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 73829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7383552f7358SJed Brown if (!cfdof || setBC) { 738405586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 738505586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 738605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 738705586334SMatthew G. Knepley 738805586334SMatthew G. Knepley indices[ind] = off + foff + b; 738905586334SMatthew G. Knepley } 7390552f7358SJed Brown } else { 73919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 739205586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 739305586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 739405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 739505586334SMatthew G. Knepley 73964acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 739705586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7398552f7358SJed Brown ++cind; 7399552f7358SJed Brown } else { 740036fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7401552f7358SJed Brown } 7402552f7358SJed Brown } 7403552f7358SJed Brown } 740436fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7405552f7358SJed Brown foffs[f] += fdof; 7406552f7358SJed Brown } 74073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7408552f7358SJed Brown } 7409552f7358SJed Brown 74107e29afd2SMatthew G. Knepley /* 74117e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 74127e29afd2SMatthew G. Knepley 74137e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7414645102dcSJed Brown 7415645102dcSJed Brown Notes: 7416645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7417645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 74187e29afd2SMatthew G. Knepley */ 7419d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7420d71ae5a4SJacob Faibussowitsch { 74217e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 74227e29afd2SMatthew G. Knepley 74237e29afd2SMatthew G. Knepley PetscFunctionBegin; 74249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 74257e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 74267e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 74277e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 74287e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 74297e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 74307e29afd2SMatthew G. Knepley 74319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 74329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 74339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7434645102dcSJed Brown if (!cfdof) { 743505586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 743605586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 743705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 743805586334SMatthew G. Knepley 743905586334SMatthew G. Knepley indices[ind] = foff + b; 744005586334SMatthew G. Knepley } 74417e29afd2SMatthew G. Knepley } else { 74429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 744305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 744405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 744505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 744605586334SMatthew G. Knepley 74477e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 744805586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 74497e29afd2SMatthew G. Knepley ++cind; 74507e29afd2SMatthew G. Knepley } else { 745105586334SMatthew G. Knepley indices[ind] = foff + b - cind; 74527e29afd2SMatthew G. Knepley } 74537e29afd2SMatthew G. Knepley } 74547e29afd2SMatthew G. Knepley } 74557e29afd2SMatthew G. Knepley foffs[f] += fdof; 74567e29afd2SMatthew G. Knepley } 74573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74587e29afd2SMatthew G. Knepley } 74597e29afd2SMatthew G. Knepley 7460c789d87fSToby Isaac static PetscErrorCode DMPlexAnchorsGetSubMatIndices(PetscInt nPoints, const PetscInt pnts[], PetscSection section, PetscSection cSec, PetscInt tmpIndices[], PetscInt fieldOffsets[], PetscInt indices[], const PetscInt ***perms) 7461c789d87fSToby Isaac { 7462c789d87fSToby Isaac PetscInt numFields, sStart, sEnd, cStart, cEnd; 7463c789d87fSToby Isaac 7464c789d87fSToby Isaac PetscFunctionBegin; 7465c789d87fSToby Isaac PetscCall(PetscSectionGetNumFields(section, &numFields)); 7466c789d87fSToby Isaac PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7467c789d87fSToby Isaac PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7468c789d87fSToby Isaac for (PetscInt p = 0; p < nPoints; p++) { 7469c789d87fSToby Isaac PetscInt b = pnts[2 * p]; 7470c789d87fSToby Isaac PetscInt bSecDof = 0, bOff; 7471c789d87fSToby Isaac PetscInt cSecDof = 0; 7472c789d87fSToby Isaac PetscSection indices_section; 7473c789d87fSToby Isaac 7474c789d87fSToby Isaac if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7475c789d87fSToby Isaac if (!bSecDof) continue; 7476c789d87fSToby Isaac if (b >= cStart && b < cEnd) PetscCall(PetscSectionGetDof(cSec, b, &cSecDof)); 7477c789d87fSToby Isaac indices_section = cSecDof > 0 ? cSec : section; 7478c789d87fSToby Isaac if (numFields) { 7479c789d87fSToby Isaac PetscInt fStart[32], fEnd[32]; 7480c789d87fSToby Isaac 7481c789d87fSToby Isaac fStart[0] = 0; 7482c789d87fSToby Isaac fEnd[0] = 0; 7483c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7484c789d87fSToby Isaac PetscInt fDof = 0; 7485c789d87fSToby Isaac 7486c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(indices_section, b, f, &fDof)); 7487c789d87fSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7488c789d87fSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7489c789d87fSToby Isaac } 7490c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7491c789d87fSToby Isaac // only apply permutations on one side 7492c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPointFields_Internal(indices_section, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, perms ? p : -1, NULL, tmpIndices)); 7493c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7494c789d87fSToby Isaac for (PetscInt i = fStart[f]; i < fEnd[f]; i++) { indices[fieldOffsets[f]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); } 7495c789d87fSToby Isaac } 7496c789d87fSToby Isaac } else { 7497c789d87fSToby Isaac PetscInt bEnd = 0; 7498c789d87fSToby Isaac 7499c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7500c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPoint_Internal(indices_section, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, tmpIndices)); 7501c789d87fSToby Isaac 7502c789d87fSToby Isaac for (PetscInt i = 0; i < bEnd; i++) indices[fieldOffsets[0]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); 7503c789d87fSToby Isaac } 7504c789d87fSToby Isaac } 7505c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7506c789d87fSToby Isaac } 7507c789d87fSToby Isaac 7508c789d87fSToby 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[]) 7509d71ae5a4SJacob Faibussowitsch { 7510d3d1a6afSToby Isaac Mat cMat; 7511d3d1a6afSToby Isaac PetscSection aSec, cSec; 7512d3d1a6afSToby Isaac IS aIS; 7513d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7514a19ea1e9SMatthew G. Knepley PetscInt sStart = -1, sEnd = -1; 7515a19ea1e9SMatthew G. Knepley PetscInt cStart = -1, cEnd = -1; 7516d3d1a6afSToby Isaac const PetscInt *anchors; 7517e969e7a5SJose E. Roman PetscInt numFields, p; 7518d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7519c789d87fSToby Isaac PetscInt *newPoints, *indices, *newIndices, *tmpIndices, *tmpNewIndices; 7520c789d87fSToby Isaac PetscInt oldOffsets[32]; 7521d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7522c789d87fSToby Isaac PetscInt oldOffsetsCopy[32]; 7523c789d87fSToby Isaac PetscInt newOffsetsCopy[32]; 7524c789d87fSToby Isaac PetscScalar *modMat = NULL; 7525d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7526d3d1a6afSToby Isaac 7527d3d1a6afSToby Isaac PetscFunctionBegin; 7528d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7529d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 75309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7531d3d1a6afSToby Isaac 75329566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7533d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7534d3d1a6afSToby Isaac if (aSec) { 75359566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 7536c789d87fSToby Isaac PetscCall(PetscArrayzero(oldOffsets, 32)); 75379566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 75389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7539a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7540d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7541d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7542d3d1a6afSToby Isaac * into the global matrix anyway) */ 7543d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7544d3d1a6afSToby Isaac PetscInt b = points[p]; 7545a19ea1e9SMatthew G. Knepley PetscInt bDof = 0, bSecDof = 0; 7546d3d1a6afSToby Isaac 7547a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7548ad540459SPierre Jolivet if (!bSecDof) continue; 7549c789d87fSToby Isaac 7550c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7551c789d87fSToby Isaac PetscInt fDof = 0; 7552c789d87fSToby Isaac 7553c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7554c789d87fSToby Isaac oldOffsets[f + 1] += fDof; 7555c789d87fSToby Isaac } 755648a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7557d3d1a6afSToby Isaac if (bDof) { 7558d3d1a6afSToby Isaac /* this point is constrained */ 7559d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7560d3d1a6afSToby Isaac PetscInt bOff, q; 7561d3d1a6afSToby Isaac 75629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7563d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7564d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7565a19ea1e9SMatthew G. Knepley PetscInt aDof = 0; 7566d3d1a6afSToby Isaac 7567a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7568c789d87fSToby Isaac if (aDof) { 7569c789d87fSToby Isaac anyConstrained = PETSC_TRUE; 7570c789d87fSToby Isaac newNumPoints += 1; 7571c789d87fSToby Isaac } 7572d3d1a6afSToby Isaac newNumIndices += aDof; 7573e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) { 7574a19ea1e9SMatthew G. Knepley PetscInt fDof = 0; 7575d3d1a6afSToby Isaac 7576a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7577d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7578d3d1a6afSToby Isaac } 7579d3d1a6afSToby Isaac } 75809371c9d4SSatish Balay } else { 7581d3d1a6afSToby Isaac /* this point is not constrained */ 7582d3d1a6afSToby Isaac newNumPoints++; 75834b2f2278SToby Isaac newNumIndices += bSecDof; 7584e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) { 7585d3d1a6afSToby Isaac PetscInt fDof; 7586d3d1a6afSToby Isaac 75879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7588d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7589d3d1a6afSToby Isaac } 7590d3d1a6afSToby Isaac } 7591d3d1a6afSToby Isaac } 7592d3d1a6afSToby Isaac } 7593d3d1a6afSToby Isaac if (!anyConstrained) { 759472b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 759572b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 759672b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 7597c789d87fSToby Isaac if (outMat) *outMat = NULL; 75989566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 75993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7600d3d1a6afSToby Isaac } 7601d3d1a6afSToby Isaac 76026ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 76036ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 76046ecaa68aSToby Isaac 7605e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7606e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) oldOffsets[f + 1] += oldOffsets[f]; 7607d3d1a6afSToby Isaac 7608c789d87fSToby Isaac if (!outPoints && !outMat) { 76096ecaa68aSToby Isaac if (offsets) { 7610e969e7a5SJose E. Roman for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 76116ecaa68aSToby Isaac } 76129566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 76133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 76146ecaa68aSToby Isaac } 76156ecaa68aSToby Isaac 76161dca8a05SBarry 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); 7617c789d87fSToby 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); 7618d3d1a6afSToby Isaac 76199566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7620a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7621d3d1a6afSToby Isaac 76226ecaa68aSToby Isaac /* output arrays */ 76239566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 7624c789d87fSToby Isaac PetscCall(PetscArrayzero(newPoints, 2 * newNumPoints)); 76256ecaa68aSToby Isaac 7626c789d87fSToby Isaac // get the new Points 7627c789d87fSToby Isaac for (PetscInt p = 0, newP = 0; p < numPoints; p++) { 7628d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7629c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 7630d3d1a6afSToby Isaac 7631a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7632ad540459SPierre Jolivet if (!bSecDof) continue; 763348a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7634d3d1a6afSToby Isaac if (bDof) { 76359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7636c789d87fSToby Isaac for (PetscInt q = 0; q < bDof; q++) { 7637a19ea1e9SMatthew G. Knepley PetscInt a = anchors[bOff + q], aDof = 0; 7638d3d1a6afSToby Isaac 7639a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7640c789d87fSToby Isaac if (aDof) { 7641c789d87fSToby Isaac newPoints[2 * newP] = a; 7642c789d87fSToby Isaac newPoints[2 * newP + 1] = 0; // orientations are accounted for in constructing the matrix, newly added points are in default orientation 7643d3d1a6afSToby Isaac newP++; 7644d3d1a6afSToby Isaac } 7645d3d1a6afSToby Isaac } 7646d3d1a6afSToby Isaac } else { 7647d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7648c789d87fSToby Isaac newPoints[2 * newP + 1] = points[2 * p + 1]; 7649d3d1a6afSToby Isaac newP++; 7650d3d1a6afSToby Isaac } 7651d3d1a6afSToby Isaac } 7652d3d1a6afSToby Isaac 7653c789d87fSToby Isaac if (outMat) { 7654c789d87fSToby Isaac PetscScalar *tmpMat; 7655c789d87fSToby Isaac PetscCall(PetscArraycpy(oldOffsetsCopy, oldOffsets, 32)); 7656c789d87fSToby Isaac PetscCall(PetscArraycpy(newOffsetsCopy, newOffsets, 32)); 7657c789d87fSToby Isaac 7658c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &indices)); 7659c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 7660c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 7661c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 7662c789d87fSToby Isaac 7663c789d87fSToby Isaac for (PetscInt i = 0; i < numIndices; i++) indices[i] = -1; 7664c789d87fSToby Isaac for (PetscInt i = 0; i < newNumIndices; i++) newIndices[i] = -1; 7665c789d87fSToby Isaac 7666c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(numPoints, points, section, cSec, tmpIndices, oldOffsetsCopy, indices, perms)); 7667c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(newNumPoints, newPoints, section, section, tmpNewIndices, newOffsetsCopy, newIndices, NULL)); 7668c789d87fSToby Isaac 7669c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 7670c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 7671c789d87fSToby Isaac PetscCall(PetscArrayzero(modMat, newNumIndices * numIndices)); 7672c789d87fSToby Isaac // for each field, insert the anchor modification into modMat 7673c789d87fSToby Isaac for (PetscInt f = 0; f < PetscMax(1, numFields); f++) { 7674c789d87fSToby Isaac PetscInt fStart = oldOffsets[f]; 7675c789d87fSToby Isaac PetscInt fNewStart = newOffsets[f]; 7676c789d87fSToby Isaac for (PetscInt p = 0, newP = 0, o = fStart, oNew = fNewStart; p < numPoints; p++) { 7677c789d87fSToby Isaac PetscInt b = points[2 * p]; 7678c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 7679c789d87fSToby Isaac 7680c789d87fSToby Isaac if (b >= sStart && b < sEnd) { 7681d3d1a6afSToby Isaac if (numFields) { 7682c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &bSecDof)); 76839371c9d4SSatish Balay } else { 7684c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7685d3d1a6afSToby Isaac } 7686d3d1a6afSToby Isaac } 7687c789d87fSToby Isaac if (!bSecDof) continue; 7688c789d87fSToby Isaac if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7689c789d87fSToby Isaac if (bDof) { 7690c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7691c789d87fSToby Isaac for (PetscInt q = 0; q < bDof; q++, newP++) { 7692c789d87fSToby Isaac PetscInt a = anchors[bOff + q], aDof = 0; 7693d3d1a6afSToby Isaac 7694c789d87fSToby Isaac if (a >= sStart && a < sEnd) { 7695d3d1a6afSToby Isaac if (numFields) { 7696c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 7697c789d87fSToby Isaac } else { 7698c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, a, &aDof)); 7699d3d1a6afSToby Isaac } 7700d3d1a6afSToby Isaac } 7701c789d87fSToby Isaac if (aDof) { 7702c789d87fSToby Isaac PetscCall(MatGetValues(cMat, bSecDof, &indices[o], aDof, &newIndices[oNew], tmpMat)); 7703c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) { 7704c789d87fSToby Isaac for (PetscInt e = 0; e < aDof; e++) modMat[(o + d) * newNumIndices + oNew + e] = tmpMat[d * aDof + e]; 7705c789d87fSToby Isaac } 7706c789d87fSToby Isaac } 7707c789d87fSToby Isaac oNew += aDof; 7708c789d87fSToby Isaac } 77099371c9d4SSatish Balay } else { 7710c789d87fSToby Isaac // Insert the identity matrix in this block 7711c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) modMat[(o + d) * newNumIndices + oNew + d] = 1; 7712c789d87fSToby Isaac oNew += bSecDof; 7713c789d87fSToby Isaac newP++; 7714d3d1a6afSToby Isaac } 7715c789d87fSToby Isaac o += bSecDof; 7716d3d1a6afSToby Isaac } 7717d3d1a6afSToby Isaac } 7718d3d1a6afSToby Isaac 7719c789d87fSToby Isaac *outMat = modMat; 77206ecaa68aSToby Isaac 7721c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 7722c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 7723c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 7724c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 7725c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices)); 7726d3d1a6afSToby Isaac } 77279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7728d3d1a6afSToby Isaac 7729d3d1a6afSToby Isaac /* output */ 77306ecaa68aSToby Isaac if (outPoints) { 7731d3d1a6afSToby Isaac *outPoints = newPoints; 77329371c9d4SSatish Balay } else { 77339566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 77346ecaa68aSToby Isaac } 7735e969e7a5SJose E. Roman for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 77363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7737d3d1a6afSToby Isaac } 7738d3d1a6afSToby Isaac 7739c789d87fSToby 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) 7740c789d87fSToby Isaac { 7741c789d87fSToby Isaac PetscScalar *modMat = NULL; 7742c789d87fSToby Isaac PetscInt newNumIndices = -1; 77437cd05799SMatthew G. Knepley 7744c789d87fSToby Isaac PetscFunctionBegin; 7745c789d87fSToby 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. 7746c789d87fSToby Isaac modMat is that matrix C */ 7747c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatModification(dm, section, numPoints, numIndices, points, perms, outNumPoints, &newNumIndices, outPoints, offsets, outValues ? &modMat : NULL)); 7748c789d87fSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 7749c789d87fSToby Isaac if (modMat) { 7750c789d87fSToby Isaac const PetscScalar *newValues = values; 77517cd05799SMatthew G. Knepley 7752c789d87fSToby Isaac if (multiplyRight) { 7753c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 7754c789d87fSToby Isaac PetscBLASInt M = newNumIndices; 7755c789d87fSToby Isaac PetscBLASInt N = numRows; 7756c789d87fSToby Isaac PetscBLASInt K = numIndices; 7757c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 77587cd05799SMatthew G. Knepley 7759c789d87fSToby 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); 77607cd05799SMatthew G. Knepley 7761c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numRows * newNumIndices, MPIU_SCALAR, &newNewValues)); 7762c789d87fSToby Isaac // row-major to column-major conversion, right multiplication becomes left multiplication 7763c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &M, &N, &K, &a, modMat, &M, newValues, &K, &b, newNewValues, &M)); 776436fa2b79SJed Brown 7765c789d87fSToby Isaac numCols = newNumIndices; 7766c789d87fSToby Isaac newValues = newNewValues; 7767c789d87fSToby Isaac } 7768a1cb98faSBarry Smith 7769c789d87fSToby Isaac if (multiplyLeft) { 7770c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 7771c789d87fSToby Isaac PetscBLASInt M = numCols; 7772c789d87fSToby Isaac PetscBLASInt N = newNumIndices; 7773c789d87fSToby Isaac PetscBLASInt K = numIndices; 7774c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 77757cd05799SMatthew G. Knepley 7776c789d87fSToby 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); 7777c789d87fSToby Isaac 7778c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices * numCols, MPIU_SCALAR, &newNewValues)); 7779c789d87fSToby Isaac // row-major to column-major conversion, left multiplication becomes right multiplication 7780c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &M, &N, &K, &a, newValues, &M, modMat, &N, &b, newNewValues, &M)); 7781c789d87fSToby Isaac if (newValues != values) PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &newValues)); 7782c789d87fSToby Isaac newValues = newNewValues; 7783c789d87fSToby Isaac } 7784c789d87fSToby Isaac *outValues = (PetscScalar *)newValues; 7785c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 7786c789d87fSToby Isaac } 7787c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7788c789d87fSToby Isaac } 7789c789d87fSToby Isaac 7790c789d87fSToby 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) 7791c789d87fSToby Isaac { 7792c789d87fSToby Isaac PetscFunctionBegin; 7793c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, numPoints, numIndices, points, perms, numIndices, numIndices, values, outNumPoints, outNumIndices, outPoints, outValues, offsets, PETSC_TRUE, multiplyLeft)); 7794c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7795c789d87fSToby Isaac } 7796c789d87fSToby Isaac 7797c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndicesSize_Internal(DM dm, PetscSection section, PetscInt point, PetscInt *closureSize) 7798c789d87fSToby Isaac { 7799c789d87fSToby Isaac /* Closure ordering */ 7800c789d87fSToby Isaac PetscSection clSection; 7801c789d87fSToby Isaac IS clPoints; 7802c789d87fSToby Isaac const PetscInt *clp; 7803c789d87fSToby Isaac PetscInt *points; 7804c789d87fSToby Isaac PetscInt Ncl, Ni = 0; 7805c789d87fSToby Isaac 7806c789d87fSToby Isaac PetscFunctionBeginHot; 7807c789d87fSToby Isaac PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7808c789d87fSToby Isaac for (PetscInt p = 0; p < Ncl * 2; p += 2) { 7809c789d87fSToby Isaac PetscInt dof; 7810c789d87fSToby Isaac 7811c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, points[p], &dof)); 7812c789d87fSToby Isaac Ni += dof; 7813c789d87fSToby Isaac } 7814c789d87fSToby Isaac PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7815c789d87fSToby Isaac *closureSize = Ni; 7816c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7817c789d87fSToby Isaac } 7818c789d87fSToby Isaac 7819c789d87fSToby 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) 7820d71ae5a4SJacob Faibussowitsch { 782171f0bbf9SMatthew G. Knepley /* Closure ordering */ 78227773e69fSMatthew G. Knepley PetscSection clSection; 78237773e69fSMatthew G. Knepley IS clPoints; 782471f0bbf9SMatthew G. Knepley const PetscInt *clp; 782571f0bbf9SMatthew G. Knepley PetscInt *points; 782671f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 782771f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 78284acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 782971f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 783071f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 783171f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 783271f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 783371f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 783471f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 783571f0bbf9SMatthew G. Knepley 783671f0bbf9SMatthew G. Knepley PetscInt *idx; 783771f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 783871f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 78397caea556SToby Isaac PetscInt idxStart, idxEnd; 7840c789d87fSToby Isaac PetscInt nRows, nCols; 78417773e69fSMatthew G. Knepley 784271f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 78437773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 78447773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 784536fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7846c789d87fSToby Isaac PetscAssertPointer(numRows, 6); 7847c789d87fSToby Isaac PetscAssertPointer(numCols, 7); 7848c789d87fSToby Isaac if (indices) PetscAssertPointer(indices, 8); 7849c789d87fSToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 9); 7850c789d87fSToby Isaac if (values) PetscAssertPointer(values, 10); 78519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 785263a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 78539566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 785471f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 785507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7856c459fbc1SJed Brown if (useClPerm) { 7857c459fbc1SJed Brown PetscInt depth, clsize; 78589566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7859c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7860c459fbc1SJed Brown PetscInt dof; 78619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7862c459fbc1SJed Brown clsize += dof; 7863c459fbc1SJed Brown } 78649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7865c459fbc1SJed Brown } 786671f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 786771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 78687773e69fSMatthew G. Knepley PetscInt dof, fdof; 78697773e69fSMatthew G. Knepley 78709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 78717773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 78729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 78737773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 78747773e69fSMatthew G. Knepley } 787571f0bbf9SMatthew G. Knepley Ni += dof; 78767773e69fSMatthew G. Knepley } 7877c789d87fSToby Isaac if (*numRows == -1) *numRows = Ni; 7878c789d87fSToby Isaac if (*numCols == -1) *numCols = Ni; 7879c789d87fSToby Isaac nRows = *numRows; 7880c789d87fSToby Isaac nCols = *numCols; 78817773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 78821dca8a05SBarry 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); 788371f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7884c789d87fSToby Isaac if (multiplyRight) PetscCheck(nCols == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " columns, got %" PetscInt_FMT, Ni, nCols); 7885c789d87fSToby Isaac if (multiplyLeft) PetscCheck(nRows == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " rows, got %" PetscInt_FMT, Ni, nRows); 788671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 78879566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 78889566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 788971f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 789071f0bbf9SMatthew G. Knepley if (values && flips[f]) { 789171f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 78926ecaa68aSToby Isaac 789371f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 789471f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 789571f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 789671f0bbf9SMatthew G. Knepley 78979566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 78989566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 789971f0bbf9SMatthew G. Knepley if (flip) { 790071f0bbf9SMatthew G. Knepley PetscInt i, j, k; 790171f0bbf9SMatthew G. Knepley 790271f0bbf9SMatthew G. Knepley if (!valCopy) { 79039566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 790471f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 790571f0bbf9SMatthew G. Knepley *values = valCopy; 790671f0bbf9SMatthew G. Knepley } 790771f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 790871f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 790971f0bbf9SMatthew G. Knepley 7910c789d87fSToby Isaac if (multiplyRight) { 7911c789d87fSToby Isaac for (k = 0; k < nRows; ++k) { valCopy[Ni * k + (foffset + i)] *= fval; } 7912c789d87fSToby Isaac } 7913c789d87fSToby Isaac if (multiplyLeft) { 7914c789d87fSToby Isaac for (k = 0; k < nCols; ++k) { valCopy[nCols * (foffset + i) + k] *= fval; } 79156ecaa68aSToby Isaac } 79166ecaa68aSToby Isaac } 791771f0bbf9SMatthew G. Knepley } 791871f0bbf9SMatthew G. Knepley foffset += fdof; 791971f0bbf9SMatthew G. Knepley } 792071f0bbf9SMatthew G. Knepley } 792171f0bbf9SMatthew G. Knepley } 792271f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7923c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, Ncl, Ni, points, perms, nRows, nCols, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, multiplyRight, multiplyLeft)); 792471f0bbf9SMatthew G. Knepley if (NclC) { 7925c789d87fSToby Isaac if (multiplyRight) { *numCols = nCols = NiC; } 7926c789d87fSToby Isaac if (multiplyLeft) { *numRows = nRows = NiC; } 79279566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 792871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79299566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 79309566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 793171f0bbf9SMatthew G. Knepley } 793271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79339566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 79349566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 793571f0bbf9SMatthew G. Knepley } 79369566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 793771f0bbf9SMatthew G. Knepley Ncl = NclC; 793871f0bbf9SMatthew G. Knepley Ni = NiC; 793971f0bbf9SMatthew G. Knepley points = pointsC; 794071f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 794171f0bbf9SMatthew G. Knepley } 794271f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 79439566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 79447caea556SToby Isaac PetscCall(PetscSectionGetChart(idxSection, &idxStart, &idxEnd)); 794571f0bbf9SMatthew G. Knepley if (Nf) { 794671f0bbf9SMatthew G. Knepley PetscInt idxOff; 794771f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 794871f0bbf9SMatthew G. Knepley 79499371c9d4SSatish Balay if (outOffsets) { 79509371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 79519371c9d4SSatish Balay } 79529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 795371f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 795471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 795571f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 795671f0bbf9SMatthew G. Knepley 79579566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 79587773e69fSMatthew G. Knepley } 79597773e69fSMatthew G. Knepley } else { 796071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 796171f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 796271f0bbf9SMatthew G. Knepley 79637caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 79649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 796571f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 796671f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 796771f0bbf9SMatthew G. Knepley * global section. */ 79689566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 796971f0bbf9SMatthew G. Knepley } 797071f0bbf9SMatthew G. Knepley } 797171f0bbf9SMatthew G. Knepley } else { 797271f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 797371f0bbf9SMatthew G. Knepley 797471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 797571f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 79764acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 79774acb8e1eSToby Isaac 79787caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 79799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 798071f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 798171f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 79829566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 79837773e69fSMatthew G. Knepley } 79847773e69fSMatthew G. Knepley } 798571f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 798671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79879566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 79889566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 79894acb8e1eSToby Isaac } 799071f0bbf9SMatthew G. Knepley if (NclC) { 79919566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 79927773e69fSMatthew G. Knepley } else { 79939566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 79947773e69fSMatthew G. Knepley } 799571f0bbf9SMatthew G. Knepley 799671f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 79973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79987773e69fSMatthew G. Knepley } 79997773e69fSMatthew G. Knepley 8000d3d1a6afSToby Isaac /*@C 8001d3d1a6afSToby Isaac DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 8002d3d1a6afSToby Isaac 8003d3d1a6afSToby Isaac Not collective 8004d3d1a6afSToby Isaac 8005d3d1a6afSToby Isaac Input Parameters: 8006d3d1a6afSToby Isaac + dm - The `DM` 8007d3d1a6afSToby Isaac . section - The `PetscSection` describing the points (a local section) 8008d3d1a6afSToby Isaac . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 8009d3d1a6afSToby Isaac . point - The point defining the closure 8010d3d1a6afSToby Isaac - useClPerm - Use the closure point permutation if available 8011d3d1a6afSToby Isaac 8012d3d1a6afSToby Isaac Output Parameters: 8013d3d1a6afSToby Isaac + numIndices - The number of dof indices in the closure of point with the input sections 8014d3d1a6afSToby Isaac . indices - The dof indices 8015d3d1a6afSToby Isaac . outOffsets - Array to write the field offsets into, or `NULL` 8016d3d1a6afSToby Isaac - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 8017d3d1a6afSToby Isaac 8018d3d1a6afSToby Isaac Level: advanced 8019d3d1a6afSToby Isaac 8020d3d1a6afSToby Isaac Notes: 8021d3d1a6afSToby Isaac Must call `DMPlexRestoreClosureIndices()` to free allocated memory 8022d3d1a6afSToby Isaac 8023d3d1a6afSToby Isaac If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 8024d3d1a6afSToby Isaac of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 8025d3d1a6afSToby Isaac of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 8026d3d1a6afSToby Isaac indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 8027d3d1a6afSToby Isaac indices (with the above semantics) are implied. 8028d3d1a6afSToby Isaac 8029d3d1a6afSToby Isaac .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 8030d3d1a6afSToby Isaac `PetscSection`, `DMGetGlobalSection()` 8031d3d1a6afSToby Isaac @*/ 8032d3d1a6afSToby Isaac PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8033d3d1a6afSToby Isaac { 8034c789d87fSToby Isaac PetscInt numRows = -1, numCols = -1; 8035d3d1a6afSToby Isaac 8036d3d1a6afSToby Isaac PetscFunctionBeginHot; 8037c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dm, section, idxSection, point, useClPerm, &numRows, &numCols, indices, outOffsets, values, PETSC_TRUE, PETSC_TRUE)); 8038c789d87fSToby Isaac PetscCheck(numRows == numCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Symmetric matrix transformation produces rectangular dimensions (%" PetscInt_FMT ", %" PetscInt_FMT ")", numRows, numCols); 8039c789d87fSToby Isaac *numIndices = numRows; 80407773e69fSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 80417773e69fSMatthew G. Knepley } 80427773e69fSMatthew G. Knepley 80437cd05799SMatthew G. Knepley /*@C 804471f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 80457cd05799SMatthew G. Knepley 80467cd05799SMatthew G. Knepley Not collective 80477cd05799SMatthew G. Knepley 80487cd05799SMatthew G. Knepley Input Parameters: 8049a1cb98faSBarry Smith + dm - The `DM` 8050a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8051a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 805271f0bbf9SMatthew G. Knepley . point - The point defining the closure 805371f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 805471f0bbf9SMatthew G. Knepley 805571f0bbf9SMatthew G. Knepley Output Parameters: 805671f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 805771f0bbf9SMatthew G. Knepley . indices - The dof indices 805820f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 805920f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 806071f0bbf9SMatthew G. Knepley 8061a1cb98faSBarry Smith Level: advanced 806271f0bbf9SMatthew G. Knepley 8063a1cb98faSBarry Smith Notes: 8064a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8065a1cb98faSBarry Smith 8066a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 806771f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 806871f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 806971f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 807071f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 80717cd05799SMatthew G. Knepley 80721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 80737cd05799SMatthew G. Knepley @*/ 8074d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8075d71ae5a4SJacob Faibussowitsch { 80767773e69fSMatthew G. Knepley PetscFunctionBegin; 80777773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80784f572ea9SToby Isaac PetscAssertPointer(indices, 7); 80799566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 80803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80817773e69fSMatthew G. Knepley } 80827773e69fSMatthew G. Knepley 8083e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8084d71ae5a4SJacob Faibussowitsch { 8085552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8086552f7358SJed Brown PetscInt *indices; 808771f0bbf9SMatthew G. Knepley PetscInt numIndices; 808871f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8089552f7358SJed Brown PetscErrorCode ierr; 8090552f7358SJed Brown 8091552f7358SJed Brown PetscFunctionBegin; 8092552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80939566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 80943dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 80959566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 80963dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8097e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8098552f7358SJed Brown 8099e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81000d644c17SKarl Rupp 81019566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8102d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 81034a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8104552f7358SJed Brown if (ierr) { 8105552f7358SJed Brown PetscMPIInt rank; 8106552f7358SJed Brown 81079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 81089566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 81099566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 81109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81119566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8112c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8113552f7358SJed Brown } 81144a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 81154a1e0b3eSMatthew G. Knepley PetscInt i; 81169566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 811763a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 81189566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 81194a1e0b3eSMatthew G. Knepley } 812071f0bbf9SMatthew G. Knepley 81219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81229566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 81233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81244acb8e1eSToby Isaac } 812571f0bbf9SMatthew G. Knepley 81264a1e0b3eSMatthew G. Knepley /*@C 8127e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8128e8e188d2SZach Atkins 8129e8e188d2SZach Atkins Not collective 8130e8e188d2SZach Atkins 8131e8e188d2SZach Atkins Input Parameters: 8132e8e188d2SZach Atkins + dm - The `DM` 8133e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8134e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8135e8e188d2SZach Atkins . A - The matrix 8136e8e188d2SZach Atkins . point - The point in the `DM` 8137e8e188d2SZach Atkins . values - The array of values 8138e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8139e8e188d2SZach Atkins 8140e8e188d2SZach Atkins Level: intermediate 8141e8e188d2SZach Atkins 8142e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8143e8e188d2SZach Atkins @*/ 8144e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8145e8e188d2SZach Atkins { 8146e8e188d2SZach Atkins PetscFunctionBegin; 8147e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8148e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8149e8e188d2SZach Atkins } 8150e8e188d2SZach Atkins 8151e8e188d2SZach Atkins /*@C 815260225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 81534a1e0b3eSMatthew G. Knepley 81544a1e0b3eSMatthew G. Knepley Not collective 81554a1e0b3eSMatthew G. Knepley 81564a1e0b3eSMatthew G. Knepley Input Parameters: 8157a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 815820f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8159e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 816020f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8161a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 816220f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8163e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 816420f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 81654a1e0b3eSMatthew G. Knepley . A - The matrix 8166a1cb98faSBarry Smith . point - The point in the `DM` 81674a1e0b3eSMatthew G. Knepley . values - The array of values 8168a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 81694a1e0b3eSMatthew G. Knepley 81704a1e0b3eSMatthew G. Knepley Level: intermediate 81714a1e0b3eSMatthew G. Knepley 81721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 81734a1e0b3eSMatthew G. Knepley @*/ 8174e8e188d2SZach 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) 8175d71ae5a4SJacob Faibussowitsch { 817671f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 817771f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 8178c789d87fSToby Isaac PetscInt numIndicesRow = -1, numIndicesCol = -1; 81797caea556SToby Isaac const PetscScalar *valuesV0 = values, *valuesV1, *valuesV2; 8180c789d87fSToby Isaac 818171f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 818271f0bbf9SMatthew G. Knepley 818371f0bbf9SMatthew G. Knepley PetscFunctionBegin; 818471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 81859566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 818671f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 81879566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 818871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8189e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 81909566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8191e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 81929566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8193e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8194e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 819571f0bbf9SMatthew G. Knepley 8196c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmRow, sectionRow, point, &numIndicesRow)); 8197c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmCol, sectionCol, point, &numIndicesCol)); 81987caea556SToby Isaac valuesV1 = valuesV0; 8199c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV1, PETSC_FALSE, PETSC_TRUE)); 82007caea556SToby Isaac valuesV2 = valuesV1; 8201c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesRow, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2, PETSC_TRUE, PETSC_FALSE)); 820271f0bbf9SMatthew G. Knepley 8203c789d87fSToby Isaac if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2)); 8204d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8205c789d87fSToby Isaac ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2, mode); 820671f0bbf9SMatthew G. Knepley if (ierr) { 820771f0bbf9SMatthew G. Knepley PetscMPIInt rank; 820871f0bbf9SMatthew G. Knepley 82099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 82109566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 82119566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 82127caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV2)); 82137caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 82147caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 82157caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 8216d3d1a6afSToby Isaac } 821771f0bbf9SMatthew G. Knepley 82187caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2)); 82197caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 82207caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 82217caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 82223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8223552f7358SJed Brown } 8224552f7358SJed Brown 8225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8226d71ae5a4SJacob Faibussowitsch { 8227de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8228de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8229de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8230de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 823117c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8232de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8233412e9a14SMatthew G. Knepley DMPolytopeType ct; 82344ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8235de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8236de41b84cSMatthew G. Knepley 8237de41b84cSMatthew G. Knepley PetscFunctionBegin; 8238de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8239de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 82409566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8241de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 82429566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8243de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 82449566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8245de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 82469566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8247de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8248de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 82499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 825063a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 82519566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 82529566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8253de41b84cSMatthew G. Knepley /* Column indices */ 82549566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 82554ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8256de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8257de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 82589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8259de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8260de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8261de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8262de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8263de41b84cSMatthew G. Knepley ++q; 8264de41b84cSMatthew G. Knepley } 8265de41b84cSMatthew G. Knepley } 8266de41b84cSMatthew G. Knepley numCPoints = q; 8267de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8268de41b84cSMatthew G. Knepley PetscInt fdof; 8269de41b84cSMatthew G. Knepley 82709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 82714ca5e9f5SMatthew G. Knepley if (!dof) continue; 8272de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 82739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8274de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8275de41b84cSMatthew G. Knepley } 8276de41b84cSMatthew G. Knepley numCIndices += dof; 8277de41b84cSMatthew G. Knepley } 8278de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8279de41b84cSMatthew G. Knepley /* Row indices */ 82809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8281412e9a14SMatthew G. Knepley { 8282012bc364SMatthew G. Knepley DMPlexTransform tr; 8283012bc364SMatthew G. Knepley DMPolytopeType *rct; 8284012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8285012bc364SMatthew G. Knepley 82869566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 82879566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 82889566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8289012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 82909566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8291412e9a14SMatthew G. Knepley } 82929566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8293de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8294de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 82959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8296de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 82979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8298de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8299de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 83009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 83014ca5e9f5SMatthew G. Knepley if (!dof) continue; 83029371c9d4SSatish Balay for (s = 0; s < q; ++s) 83039371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 83044ca5e9f5SMatthew G. Knepley if (s < q) continue; 8305de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8306de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8307de41b84cSMatthew G. Knepley ++q; 8308de41b84cSMatthew G. Knepley } 8309de41b84cSMatthew G. Knepley } 83109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8311de41b84cSMatthew G. Knepley } 8312de41b84cSMatthew G. Knepley numFPoints = q; 8313de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8314de41b84cSMatthew G. Knepley PetscInt fdof; 8315de41b84cSMatthew G. Knepley 83169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 83174ca5e9f5SMatthew G. Knepley if (!dof) continue; 8318de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8320de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8321de41b84cSMatthew G. Knepley } 8322de41b84cSMatthew G. Knepley numFIndices += dof; 8323de41b84cSMatthew G. Knepley } 8324de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8325de41b84cSMatthew G. Knepley 83261dca8a05SBarry 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); 83271dca8a05SBarry 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); 83289566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83299566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8330de41b84cSMatthew G. Knepley if (numFields) { 83314acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 83324acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 83334acb8e1eSToby Isaac 83344acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 83359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 83369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8337de41b84cSMatthew G. Knepley } 83384acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 83399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 83409566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 83414acb8e1eSToby Isaac } 83424acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 83439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 83449566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 83454acb8e1eSToby Isaac } 83464acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 83479566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 83489566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8349de41b84cSMatthew G. Knepley } 8350de41b84cSMatthew G. Knepley } else { 83514acb8e1eSToby Isaac const PetscInt **permsF = NULL; 83524acb8e1eSToby Isaac const PetscInt **permsC = NULL; 83534acb8e1eSToby Isaac 83549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 83559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 83564acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 83574acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 83584acb8e1eSToby Isaac 83599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 83609566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8361de41b84cSMatthew G. Knepley } 83624acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 83634acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 83644acb8e1eSToby Isaac 83659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 83669566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8367de41b84cSMatthew G. Knepley } 83689566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 83699566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8370de41b84cSMatthew G. Knepley } 83719566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 83724acb8e1eSToby Isaac /* TODO: flips */ 8373d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8374de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8375de41b84cSMatthew G. Knepley if (ierr) { 8376de41b84cSMatthew G. Knepley PetscMPIInt rank; 8377de41b84cSMatthew G. Knepley 83789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 83799566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 83809566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 83819566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83829566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8383de41b84cSMatthew G. Knepley } 83849566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 83859566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83869566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83879566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 83883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8389de41b84cSMatthew G. Knepley } 8390de41b84cSMatthew G. Knepley 8391d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8392d71ae5a4SJacob Faibussowitsch { 83937c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 83947c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 8395230af79eSStefano Zampini PetscInt foffsets[32] = {0}, coffsets[32] = {0}; 839617c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8397412e9a14SMatthew G. Knepley DMPolytopeType ct; 83987c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 83997c927364SMatthew G. Knepley 84007c927364SMatthew G. Knepley PetscFunctionBegin; 84017c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 84027c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 84039566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 84047c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 84059566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 84067c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 84079566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 84087c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 84099566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 84107c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 84119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 841263a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 84137c927364SMatthew G. Knepley /* Column indices */ 84149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84157c927364SMatthew G. Knepley maxFPoints = numCPoints; 84167c927364SMatthew G. Knepley /* Compress out points not in the section */ 84177c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 84189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 84197c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 84207c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 84217c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 84227c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 84237c927364SMatthew G. Knepley ++q; 84247c927364SMatthew G. Knepley } 84257c927364SMatthew G. Knepley } 84267c927364SMatthew G. Knepley numCPoints = q; 84277c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 84287c927364SMatthew G. Knepley PetscInt fdof; 84297c927364SMatthew G. Knepley 84309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 84317c927364SMatthew G. Knepley if (!dof) continue; 84327c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 84347c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 84357c927364SMatthew G. Knepley } 84367c927364SMatthew G. Knepley numCIndices += dof; 84377c927364SMatthew G. Knepley } 84387c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 84397c927364SMatthew G. Knepley /* Row indices */ 84409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8441412e9a14SMatthew G. Knepley { 8442012bc364SMatthew G. Knepley DMPlexTransform tr; 8443012bc364SMatthew G. Knepley DMPolytopeType *rct; 8444012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8445012bc364SMatthew G. Knepley 84469566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 84479566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 84489566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8449012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 84509566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8451412e9a14SMatthew G. Knepley } 84529566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 84537c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 84547c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 84559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 84567c927364SMatthew G. Knepley /* Compress out points not in the section */ 84579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 84587c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 84597c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 84609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 84617c927364SMatthew G. Knepley if (!dof) continue; 84629371c9d4SSatish Balay for (s = 0; s < q; ++s) 84639371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 84647c927364SMatthew G. Knepley if (s < q) continue; 84657c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 84667c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 84677c927364SMatthew G. Knepley ++q; 84687c927364SMatthew G. Knepley } 84697c927364SMatthew G. Knepley } 84709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 84717c927364SMatthew G. Knepley } 84727c927364SMatthew G. Knepley numFPoints = q; 84737c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 84747c927364SMatthew G. Knepley PetscInt fdof; 84757c927364SMatthew G. Knepley 84769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 84777c927364SMatthew G. Knepley if (!dof) continue; 84787c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 84807c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 84817c927364SMatthew G. Knepley } 84827c927364SMatthew G. Knepley numFIndices += dof; 84837c927364SMatthew G. Knepley } 84847c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 84857c927364SMatthew G. Knepley 84861dca8a05SBarry 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); 84871dca8a05SBarry 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); 84887c927364SMatthew G. Knepley if (numFields) { 84894acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 84904acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 84914acb8e1eSToby Isaac 84924acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 84957c927364SMatthew G. Knepley } 84964acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 84979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84989566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 84994acb8e1eSToby Isaac } 85004acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 85019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85029566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 85034acb8e1eSToby Isaac } 85044acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85059566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85069566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85077c927364SMatthew G. Knepley } 85087c927364SMatthew G. Knepley } else { 85094acb8e1eSToby Isaac const PetscInt **permsF = NULL; 85104acb8e1eSToby Isaac const PetscInt **permsC = NULL; 85114acb8e1eSToby Isaac 85129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85144acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 85154acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 85164acb8e1eSToby Isaac 85179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85189566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 85197c927364SMatthew G. Knepley } 85204acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 85214acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 85224acb8e1eSToby Isaac 85239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85249566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 85257c927364SMatthew G. Knepley } 85269566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85279566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85287c927364SMatthew G. Knepley } 85299566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 85309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 85313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 85327c927364SMatthew G. Knepley } 85337c927364SMatthew G. Knepley 85347cd05799SMatthew G. Knepley /*@C 85357cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 85367cd05799SMatthew G. Knepley 85377cd05799SMatthew G. Knepley Input Parameter: 8538a1cb98faSBarry Smith . dm - The `DMPLEX` object 85397cd05799SMatthew G. Knepley 85407cd05799SMatthew G. Knepley Output Parameter: 85417cd05799SMatthew G. Knepley . cellHeight - The height of a cell 85427cd05799SMatthew G. Knepley 85437cd05799SMatthew G. Knepley Level: developer 85447cd05799SMatthew G. Knepley 85451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 85467cd05799SMatthew G. Knepley @*/ 8547d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8548d71ae5a4SJacob Faibussowitsch { 8549552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8550552f7358SJed Brown 8551552f7358SJed Brown PetscFunctionBegin; 8552552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85534f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8554552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 85553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8556552f7358SJed Brown } 8557552f7358SJed Brown 85587cd05799SMatthew G. Knepley /*@C 85597cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 85607cd05799SMatthew G. Knepley 85617cd05799SMatthew G. Knepley Input Parameters: 8562a1cb98faSBarry Smith + dm - The `DMPLEX` object 85637cd05799SMatthew G. Knepley - cellHeight - The height of a cell 85647cd05799SMatthew G. Knepley 85657cd05799SMatthew G. Knepley Level: developer 85667cd05799SMatthew G. Knepley 85671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 85687cd05799SMatthew G. Knepley @*/ 8569d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8570d71ae5a4SJacob Faibussowitsch { 8571552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8572552f7358SJed Brown 8573552f7358SJed Brown PetscFunctionBegin; 8574552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8575552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 85763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8577552f7358SJed Brown } 8578552f7358SJed Brown 8579e6139122SMatthew G. Knepley /*@ 85802827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8581e6139122SMatthew G. Knepley 85822827ebadSStefano Zampini Input Parameters: 85832827ebadSStefano Zampini + dm - The `DMPLEX` object 85842827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8585e6139122SMatthew G. Knepley 8586e6139122SMatthew G. Knepley Output Parameters: 85872827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 85882827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8589e6139122SMatthew G. Knepley 85902a9f31c0SMatthew G. Knepley Level: advanced 8591e6139122SMatthew G. Knepley 85922827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8593e6139122SMatthew G. Knepley @*/ 85942827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8595d71ae5a4SJacob Faibussowitsch { 85962827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 85972827ebadSStefano Zampini DMLabel label; 85982827ebadSStefano Zampini PetscInt pStart, pEnd; 8599e6139122SMatthew G. Knepley 8600e6139122SMatthew G. Knepley PetscFunctionBegin; 8601e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86022827ebadSStefano Zampini if (start) { 86034f572ea9SToby Isaac PetscAssertPointer(start, 3); 86042827ebadSStefano Zampini *start = 0; 86052827ebadSStefano Zampini } 86062827ebadSStefano Zampini if (end) { 86074f572ea9SToby Isaac PetscAssertPointer(end, 4); 86082827ebadSStefano Zampini *end = 0; 86092827ebadSStefano Zampini } 86102827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86112827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 86122827ebadSStefano Zampini if (mesh->tr) { 86132827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 86142827ebadSStefano Zampini } else { 86152827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 86162827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 86172827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 86182827ebadSStefano Zampini } 86193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8620e6139122SMatthew G. Knepley } 8621e6139122SMatthew G. Knepley 8622d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8623d71ae5a4SJacob Faibussowitsch { 8624552f7358SJed Brown PetscSection section, globalSection; 8625552f7358SJed Brown PetscInt *numbers, p; 8626552f7358SJed Brown 8627552f7358SJed Brown PetscFunctionBegin; 8628d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 86299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 86309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 863148a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 86329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8633eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection)); 86349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8635552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 86369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8637ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8638ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8639552f7358SJed Brown } 86409566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8641ef48cebcSMatthew G. Knepley if (globalSize) { 8642ef48cebcSMatthew G. Knepley PetscLayout layout; 86439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 86449566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 86459566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8646ef48cebcSMatthew G. Knepley } 86479566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 86489566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 86493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8650552f7358SJed Brown } 8651552f7358SJed Brown 8652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8653d71ae5a4SJacob Faibussowitsch { 8654412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8655552f7358SJed Brown 8656552f7358SJed Brown PetscFunctionBegin; 86579566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 86589566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 86599566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 86609566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 86613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8662552f7358SJed Brown } 866381ed3555SMatthew G. Knepley 86648dab3259SMatthew G. Knepley /*@ 86657cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 86667cd05799SMatthew G. Knepley 86677cd05799SMatthew G. Knepley Input Parameter: 8668a1cb98faSBarry Smith . dm - The `DMPLEX` object 86697cd05799SMatthew G. Knepley 86707cd05799SMatthew G. Knepley Output Parameter: 86717cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 86727cd05799SMatthew G. Knepley 86737cd05799SMatthew G. Knepley Level: developer 86747cd05799SMatthew G. Knepley 86751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 86767cd05799SMatthew G. Knepley @*/ 8677d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8678d71ae5a4SJacob Faibussowitsch { 867981ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 868081ed3555SMatthew G. Knepley 868181ed3555SMatthew G. Knepley PetscFunctionBegin; 868281ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86839566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8684552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 86853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8686552f7358SJed Brown } 8687552f7358SJed Brown 8688d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8689d71ae5a4SJacob Faibussowitsch { 8690412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 869181ed3555SMatthew G. Knepley 869281ed3555SMatthew G. Knepley PetscFunctionBegin; 869381ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86949566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 86959566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 86963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 869781ed3555SMatthew G. Knepley } 869881ed3555SMatthew G. Knepley 86998dab3259SMatthew G. Knepley /*@ 87006aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 87017cd05799SMatthew G. Knepley 87027cd05799SMatthew G. Knepley Input Parameter: 8703a1cb98faSBarry Smith . dm - The `DMPLEX` object 87047cd05799SMatthew G. Knepley 87057cd05799SMatthew G. Knepley Output Parameter: 87067cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 87077cd05799SMatthew G. Knepley 87087cd05799SMatthew G. Knepley Level: developer 87097cd05799SMatthew G. Knepley 87101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87117cd05799SMatthew G. Knepley @*/ 8712d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8713d71ae5a4SJacob Faibussowitsch { 8714552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8715552f7358SJed Brown 8716552f7358SJed Brown PetscFunctionBegin; 8717552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87189566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8719552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 87203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8721552f7358SJed Brown } 8722552f7358SJed Brown 87238dab3259SMatthew G. Knepley /*@ 8724966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8725966484cfSJed Brown 872620f4b53cSBarry Smith Collective 87277cd05799SMatthew G. Knepley 87287cd05799SMatthew G. Knepley Input Parameter: 8729a1cb98faSBarry Smith . dm - The `DMPLEX` object 87307cd05799SMatthew G. Knepley 87317cd05799SMatthew G. Knepley Output Parameter: 87327cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 87337cd05799SMatthew G. Knepley 8734a1cb98faSBarry Smith Level: developer 8735966484cfSJed Brown 8736a1cb98faSBarry Smith Notes: 8737a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8738966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8739966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8740966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8741966484cfSJed Brown 8742966484cfSJed Brown The partitioned mesh is 8743966484cfSJed Brown ``` 8744966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8745966484cfSJed Brown ``` 8746966484cfSJed Brown and its global numbering is 8747966484cfSJed Brown ``` 8748966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8749966484cfSJed Brown ``` 8750966484cfSJed Brown Then the global numbering is provided as 8751966484cfSJed Brown ``` 8752966484cfSJed Brown [0] Number of indices in set 5 8753966484cfSJed Brown [0] 0 0 8754966484cfSJed Brown [0] 1 1 8755966484cfSJed Brown [0] 2 3 8756966484cfSJed Brown [0] 3 4 8757966484cfSJed Brown [0] 4 -6 8758966484cfSJed Brown [1] Number of indices in set 3 8759966484cfSJed Brown [1] 0 2 8760966484cfSJed Brown [1] 1 5 8761966484cfSJed Brown [1] 2 6 8762966484cfSJed Brown ``` 8763966484cfSJed Brown 87641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87657cd05799SMatthew G. Knepley @*/ 8766d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8767d71ae5a4SJacob Faibussowitsch { 8768ef48cebcSMatthew G. Knepley IS nums[4]; 8769862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8770ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 87710c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8772ef48cebcSMatthew G. Knepley 8773ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8774ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 87760c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 87779566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 87780c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8779862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8780862913ffSStefano Zampini PetscInt end; 8781862913ffSStefano Zampini 8782862913ffSStefano Zampini depths[d] = depth - d; 87839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 87840c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8785862913ffSStefano Zampini } 87860c15888dSMatthew G. Knepley if (empty) 87870c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 87880c15888dSMatthew G. Knepley depths[d] = -1; 87890c15888dSMatthew G. Knepley starts[d] = -1; 87900c15888dSMatthew G. Knepley } 87910c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 87921c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8793ad540459SPierre 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]); 87940c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8795ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8796ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8797ef48cebcSMatthew G. Knepley 87989566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 87999566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8800ef48cebcSMatthew G. Knepley shift += gsize; 8801ef48cebcSMatthew G. Knepley } 8802d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 88039566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 88043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8805ef48cebcSMatthew G. Knepley } 8806ef48cebcSMatthew G. Knepley 880708a22f4bSMatthew G. Knepley /*@ 880808a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 880908a22f4bSMatthew G. Knepley 881008a22f4bSMatthew G. Knepley Input Parameter: 8811a1cb98faSBarry Smith . dm - The `DMPLEX` object 881208a22f4bSMatthew G. Knepley 881308a22f4bSMatthew G. Knepley Output Parameter: 881408a22f4bSMatthew G. Knepley . ranks - The rank field 881508a22f4bSMatthew G. Knepley 8816a1cb98faSBarry Smith Options Database Key: 881720f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 881808a22f4bSMatthew G. Knepley 881908a22f4bSMatthew G. Knepley Level: intermediate 882008a22f4bSMatthew G. Knepley 88211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 882208a22f4bSMatthew G. Knepley @*/ 8823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8824d71ae5a4SJacob Faibussowitsch { 882508a22f4bSMatthew G. Knepley DM rdm; 882608a22f4bSMatthew G. Knepley PetscFE fe; 882708a22f4bSMatthew G. Knepley PetscScalar *r; 882808a22f4bSMatthew G. Knepley PetscMPIInt rank; 8829a55f9a55SMatthew G. Knepley DMPolytopeType ct; 883008a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8831a55f9a55SMatthew G. Knepley PetscBool simplex; 883208a22f4bSMatthew G. Knepley 883308a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8834f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88354f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 88369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 88379566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 88389566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 88399566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 88409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8841a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 88429566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 88439566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 88449566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 88459566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 88469566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 88479566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 88489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 88499566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 885008a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 885108a22f4bSMatthew G. Knepley PetscScalar *lr; 885208a22f4bSMatthew G. Knepley 88539566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 885471f09efeSPierre Jolivet if (lr) *lr = rank; 885508a22f4bSMatthew G. Knepley } 88569566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 88579566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 88583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 885908a22f4bSMatthew G. Knepley } 886008a22f4bSMatthew G. Knepley 8861ca8062c8SMatthew G. Knepley /*@ 8862acf3173eSStefano Zampini DMPlexCreateLabelField - Create a field whose value is the label value for that point 886318e14f0cSMatthew G. Knepley 886418e14f0cSMatthew G. Knepley Input Parameters: 886520f4b53cSBarry Smith + dm - The `DMPLEX` 886620f4b53cSBarry Smith - label - The `DMLabel` 886718e14f0cSMatthew G. Knepley 886818e14f0cSMatthew G. Knepley Output Parameter: 886918e14f0cSMatthew G. Knepley . val - The label value field 887018e14f0cSMatthew G. Knepley 887120f4b53cSBarry Smith Options Database Key: 887220f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 887318e14f0cSMatthew G. Knepley 887418e14f0cSMatthew G. Knepley Level: intermediate 887518e14f0cSMatthew G. Knepley 88761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 887718e14f0cSMatthew G. Knepley @*/ 8878d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8879d71ae5a4SJacob Faibussowitsch { 88801033741fSStefano Zampini DM rdm, plex; 8881acf3173eSStefano Zampini Vec lval; 8882acf3173eSStefano Zampini PetscSection section; 888318e14f0cSMatthew G. Knepley PetscFE fe; 888418e14f0cSMatthew G. Knepley PetscScalar *v; 8885acf3173eSStefano Zampini PetscInt dim, pStart, pEnd, p, cStart; 8886acf3173eSStefano Zampini DMPolytopeType ct; 8887acf3173eSStefano Zampini char name[PETSC_MAX_PATH_LEN]; 8888acf3173eSStefano Zampini const char *lname, *prefix; 888918e14f0cSMatthew G. Knepley 889018e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 889118e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88924f572ea9SToby Isaac PetscAssertPointer(label, 2); 88934f572ea9SToby Isaac PetscAssertPointer(val, 3); 88949566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 8895acf3173eSStefano Zampini PetscCall(DMConvert(rdm, DMPLEX, &plex)); 8896acf3173eSStefano Zampini PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL)); 8897acf3173eSStefano Zampini PetscCall(DMPlexGetCellType(plex, cStart, &ct)); 8898acf3173eSStefano Zampini PetscCall(DMDestroy(&plex)); 88999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 8900acf3173eSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 8901acf3173eSStefano Zampini PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 8902acf3173eSStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname)); 8903acf3173eSStefano Zampini PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe)); 8904acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)fe, "")); 89059566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 89069566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 89079566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 89089566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 8909acf3173eSStefano Zampini PetscCall(DMCreateLocalVector(rdm, &lval)); 8910acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*val, lname)); 8911acf3173eSStefano Zampini PetscCall(DMGetLocalSection(rdm, §ion)); 8912acf3173eSStefano Zampini PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 8913acf3173eSStefano Zampini PetscCall(VecGetArray(lval, &v)); 8914acf3173eSStefano Zampini for (p = pStart; p < pEnd; ++p) { 8915acf3173eSStefano Zampini PetscInt cval, dof, off; 891618e14f0cSMatthew G. Knepley 8917acf3173eSStefano Zampini PetscCall(PetscSectionGetDof(section, p, &dof)); 8918acf3173eSStefano Zampini if (!dof) continue; 8919acf3173eSStefano Zampini PetscCall(DMLabelGetValue(label, p, &cval)); 8920acf3173eSStefano Zampini PetscCall(PetscSectionGetOffset(section, p, &off)); 8921acf3173eSStefano Zampini for (PetscInt d = 0; d < dof; d++) v[off + d] = cval; 892218e14f0cSMatthew G. Knepley } 8923acf3173eSStefano Zampini PetscCall(VecRestoreArray(lval, &v)); 8924acf3173eSStefano Zampini PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val)); 8925acf3173eSStefano Zampini PetscCall(VecDestroy(&lval)); 89269566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 892818e14f0cSMatthew G. Knepley } 892918e14f0cSMatthew G. Knepley 893018e14f0cSMatthew G. Knepley /*@ 8931ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8932ca8062c8SMatthew G. Knepley 893369916449SMatthew G. Knepley Input Parameter: 8934a1cb98faSBarry Smith . dm - The `DMPLEX` object 8935a1cb98faSBarry Smith 8936a1cb98faSBarry Smith Level: developer 8937ca8062c8SMatthew G. Knepley 893895eb5ee5SVaclav Hapla Notes: 893995eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 894095eb5ee5SVaclav Hapla 894120f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 8942ca8062c8SMatthew G. Knepley 89431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8944ca8062c8SMatthew G. Knepley @*/ 8945d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 8946d71ae5a4SJacob Faibussowitsch { 8947ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8948ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8949ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 895057beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 895157beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8952ca8062c8SMatthew G. Knepley 8953ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8954ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89559566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 89569566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 89579566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8958ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 89599566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8960ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 89619566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 89629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8963ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 896442e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 896542e66dfaSMatthew G. Knepley PetscInt d; 896642e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 89679371c9d4SSatish Balay if (cone[c] == cone[d]) { 89689371c9d4SSatish Balay dup = PETSC_TRUE; 89699371c9d4SSatish Balay break; 89709371c9d4SSatish Balay } 897142e66dfaSMatthew G. Knepley } 89729566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 89739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8974ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8975ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8976ca8062c8SMatthew G. Knepley } 897742e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 897863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 897948a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 89809566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 898163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 898248a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 89839566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 898463a3b9bcSJacob 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]); 8985f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8986ca8062c8SMatthew G. Knepley } 898742e66dfaSMatthew G. Knepley } 89889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 89899371c9d4SSatish Balay if (p != pp) { 89909371c9d4SSatish Balay storagecheck = PETSC_FALSE; 89919371c9d4SSatish Balay continue; 89929371c9d4SSatish Balay } 89939566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 89949566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8995ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 89969566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 89979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8998ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 89999566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 90009371c9d4SSatish Balay if (cone[c] != pp) { 90019371c9d4SSatish Balay c = 0; 90029371c9d4SSatish Balay break; 90039371c9d4SSatish Balay } 9004ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 9005ca8062c8SMatthew G. Knepley } 9006ca8062c8SMatthew G. Knepley if (c >= coneSize) { 900763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 900848a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 90099566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 901063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 901148a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 90129566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 901363a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 9014ca8062c8SMatthew G. Knepley } 9015ca8062c8SMatthew G. Knepley } 9016ca8062c8SMatthew G. Knepley } 901757beb4faSStefano Zampini if (storagecheck) { 90189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 90199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 902063a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 902157beb4faSStefano Zampini } 90223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9023ca8062c8SMatthew G. Knepley } 9024ca8062c8SMatthew G. Knepley 9025412e9a14SMatthew G. Knepley /* 9026412e9a14SMatthew 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. 9027412e9a14SMatthew G. Knepley */ 9028d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9029d71ae5a4SJacob Faibussowitsch { 9030412e9a14SMatthew G. Knepley DMPolytopeType cct; 9031412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9032412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9033412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9034412e9a14SMatthew G. Knepley 9035412e9a14SMatthew G. Knepley PetscFunctionBegin; 9036412e9a14SMatthew G. Knepley *unsplit = 0; 9037412e9a14SMatthew G. Knepley switch (ct) { 9038d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9039d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9040d71ae5a4SJacob Faibussowitsch break; 9041412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 90429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 90439566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9044412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 90459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9046412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9047412e9a14SMatthew G. Knepley } 9048412e9a14SMatthew G. Knepley break; 9049412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9050412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 90519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 90529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9053412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 90549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 90559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9056412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 90579566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9058412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9059412e9a14SMatthew G. Knepley PetscInt p; 90609371c9d4SSatish Balay for (p = 0; p < npt; ++p) 90619371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9062412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9063412e9a14SMatthew G. Knepley } 9064412e9a14SMatthew G. Knepley } 9065412e9a14SMatthew G. Knepley } 9066412e9a14SMatthew G. Knepley break; 9067d71ae5a4SJacob Faibussowitsch default: 9068d71ae5a4SJacob Faibussowitsch break; 9069412e9a14SMatthew G. Knepley } 9070412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 90719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9072412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9073412e9a14SMatthew G. Knepley } 90743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9075412e9a14SMatthew G. Knepley } 9076412e9a14SMatthew G. Knepley 9077ca8062c8SMatthew G. Knepley /*@ 9078ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9079ca8062c8SMatthew G. Knepley 9080ca8062c8SMatthew G. Knepley Input Parameters: 9081a1cb98faSBarry Smith + dm - The `DMPLEX` object 908258723a97SMatthew G. Knepley - cellHeight - Normally 0 9083ca8062c8SMatthew G. Knepley 9084a1cb98faSBarry Smith Level: developer 9085a1cb98faSBarry Smith 908695eb5ee5SVaclav Hapla Notes: 908795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 908825c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9089ca8062c8SMatthew G. Knepley 909020f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 909195eb5ee5SVaclav Hapla 90921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9093ca8062c8SMatthew G. Knepley @*/ 9094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9095d71ae5a4SJacob Faibussowitsch { 9096412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9097412e9a14SMatthew G. Knepley DMPolytopeType ct; 9098412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9099ca8062c8SMatthew G. Knepley 9100ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9101ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91029566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 91039566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 91049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9105412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9106412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9107412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 910858723a97SMatthew G. Knepley 91099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 911063a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 9111412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9112412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 91139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 911463a3b9bcSJacob 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)); 9115412e9a14SMatthew G. Knepley } 91169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 911758723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 911858723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9119412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 912058723a97SMatthew G. Knepley } 91219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9122412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9123412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9124412e9a14SMatthew G. Knepley PetscInt unsplit; 912542363296SMatthew G. Knepley 91269566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9127412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 912842363296SMatthew G. Knepley } 912963a3b9bcSJacob 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)); 913042363296SMatthew G. Knepley } 91313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9132ca8062c8SMatthew G. Knepley } 91339bf0dad6SMatthew G. Knepley 91349bf0dad6SMatthew G. Knepley /*@ 91359bf0dad6SMatthew 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 91369bf0dad6SMatthew G. Knepley 913720f4b53cSBarry Smith Collective 9138899ea2b8SJacob Faibussowitsch 91399bf0dad6SMatthew G. Knepley Input Parameters: 9140a1cb98faSBarry Smith + dm - The `DMPLEX` object 91419bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 91429bf0dad6SMatthew G. Knepley 9143a1cb98faSBarry Smith Level: developer 9144a1cb98faSBarry Smith 914545da879fSVaclav Hapla Notes: 914645da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 914745da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 914845da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 914945da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 91509bf0dad6SMatthew G. Knepley 9151a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 915295eb5ee5SVaclav Hapla 91531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 91549bf0dad6SMatthew G. Knepley @*/ 9155d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9156d71ae5a4SJacob Faibussowitsch { 9157ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9158899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 91599bf0dad6SMatthew G. Knepley 91609bf0dad6SMatthew G. Knepley PetscFunctionBegin; 91619bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91628f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 91633ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 91648f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 91653ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 91663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9167899ea2b8SJacob Faibussowitsch } 9168899ea2b8SJacob Faibussowitsch 91699566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 91709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 91719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9172ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 91739566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 91743554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9175412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9176412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9177ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9178412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9179412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 91809bf0dad6SMatthew G. Knepley 91819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 91829566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9183412e9a14SMatthew G. Knepley if (unsplit) continue; 91849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 91859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91869566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 91879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 91889bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 91899bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 91909bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 91919bf0dad6SMatthew G. Knepley } 91929566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 919363a3b9bcSJacob 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); 91949bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9195d4961f80SStefano Zampini DMPolytopeType fct; 91969bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 91979bf0dad6SMatthew G. Knepley 91989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 91999566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 92009bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 92019bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 92029bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 92039bf0dad6SMatthew G. Knepley } 920463a3b9bcSJacob 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]); 92059bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9206b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9207b5a892a1SMatthew G. Knepley PetscInt v1; 9208b5a892a1SMatthew G. Knepley 92099566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 921063a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 92119566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 921263a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 92139566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 921463a3b9bcSJacob 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]); 9215b5a892a1SMatthew G. Knepley } 92169bf0dad6SMatthew G. Knepley } 92179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9218412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 92199bf0dad6SMatthew G. Knepley } 92209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 92219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92229bf0dad6SMatthew G. Knepley } 92233554e41dSMatthew G. Knepley } 92243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9225552f7358SJed Brown } 92263913d7c8SMatthew G. Knepley 9227bb6a34a8SMatthew G. Knepley /*@ 9228bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9229bb6a34a8SMatthew G. Knepley 9230bb6a34a8SMatthew G. Knepley Input Parameter: 9231a1cb98faSBarry Smith . dm - The `DMPLEX` object 9232a1cb98faSBarry Smith 9233a1cb98faSBarry Smith Level: developer 9234bb6a34a8SMatthew G. Knepley 923595eb5ee5SVaclav Hapla Notes: 923695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 923795eb5ee5SVaclav Hapla 923820f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9239bb6a34a8SMatthew G. Knepley 92401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9241bb6a34a8SMatthew G. Knepley @*/ 9242d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9243d71ae5a4SJacob Faibussowitsch { 9244a2a9e04cSMatthew G. Knepley Vec coordinates; 9245bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9246bb6a34a8SMatthew G. Knepley PetscReal vol; 924751a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9248bb6a34a8SMatthew G. Knepley 9249bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 92509566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 92519566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 92523ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 92539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9254bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 92559566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9256a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 92579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 92583ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9259412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9260412e9a14SMatthew G. Knepley DMPolytopeType ct; 9261412e9a14SMatthew G. Knepley PetscInt unsplit; 9262412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9263412e9a14SMatthew G. Knepley 92649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9265412e9a14SMatthew G. Knepley switch (ct) { 9266412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9267412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9268d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9269d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9270d71ae5a4SJacob Faibussowitsch break; 9271d71ae5a4SJacob Faibussowitsch default: 9272d71ae5a4SJacob Faibussowitsch break; 9273412e9a14SMatthew G. Knepley } 9274412e9a14SMatthew G. Knepley switch (ct) { 9275412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9276412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9277412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9278d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9279d71ae5a4SJacob Faibussowitsch continue; 9280d71ae5a4SJacob Faibussowitsch default: 9281d71ae5a4SJacob Faibussowitsch break; 9282412e9a14SMatthew G. Knepley } 92839566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9284412e9a14SMatthew G. Knepley if (unsplit) continue; 92859566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 92861dca8a05SBarry 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); 928763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 92886858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 92896858538eSMatthew G. Knepley if (depth > 1) { 92909566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 92911dca8a05SBarry 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); 929263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9293bb6a34a8SMatthew G. Knepley } 9294bb6a34a8SMatthew G. Knepley } 92953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9296bb6a34a8SMatthew G. Knepley } 9297bb6a34a8SMatthew G. Knepley 929803da9461SVaclav Hapla /*@ 929920f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 93007726db96SVaclav Hapla 930120f4b53cSBarry Smith Collective 930203da9461SVaclav Hapla 930303da9461SVaclav Hapla Input Parameters: 9304a1cb98faSBarry Smith + dm - The `DMPLEX` object 930520f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9306a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9307a1cb98faSBarry Smith 9308a1cb98faSBarry Smith Level: developer 930903da9461SVaclav Hapla 9310e83a0d2dSVaclav Hapla Notes: 9311e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 931203da9461SVaclav Hapla 9313a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 931495eb5ee5SVaclav Hapla 9315baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9316d7d32a9aSMatthew G. Knepley 93171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 931803da9461SVaclav Hapla @*/ 9319d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9320d71ae5a4SJacob Faibussowitsch { 93217726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 93227726db96SVaclav Hapla const PetscInt *locals; 93237726db96SVaclav Hapla const PetscSFNode *remotes; 9324f0cfc026SVaclav Hapla PetscBool distributed; 93257726db96SVaclav Hapla MPI_Comm comm; 93267726db96SVaclav Hapla PetscMPIInt rank; 932703da9461SVaclav Hapla 932803da9461SVaclav Hapla PetscFunctionBegin; 932903da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93307726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 93317726db96SVaclav Hapla else pointSF = dm->sf; 93327726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 93337726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 93347726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 93357726db96SVaclav Hapla { 93367726db96SVaclav Hapla PetscMPIInt mpiFlag; 93377726db96SVaclav Hapla 93387726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 93397726db96SVaclav 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); 93407726db96SVaclav Hapla } 93417726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 93429566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 93437726db96SVaclav Hapla if (!distributed) { 93447726db96SVaclav 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); 93453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 93468918e3e2SVaclav Hapla } 93477726db96SVaclav 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); 93487726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 934903da9461SVaclav Hapla 93507726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 93517726db96SVaclav Hapla { 93527726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 93537726db96SVaclav Hapla 93547726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 93557726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9356d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 93577726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 93587726db96SVaclav Hapla } 93597726db96SVaclav Hapla 93607726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 93617726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 93627726db96SVaclav 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); 93637726db96SVaclav Hapla } 93647726db96SVaclav Hapla 93657726db96SVaclav Hapla /* Check there are no cells in interface */ 93667726db96SVaclav Hapla if (!overlap) { 93677726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 93687726db96SVaclav Hapla 93699566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 93709566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9371f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 93727726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9373f5869d18SMatthew G. Knepley 93747726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 93757726db96SVaclav Hapla } 937603da9461SVaclav Hapla } 9377ece87651SVaclav Hapla 93787726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 93797726db96SVaclav Hapla { 93807726db96SVaclav Hapla const PetscInt *rootdegree; 93817726db96SVaclav Hapla 93827726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 93837726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9384f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 93857726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9386f5869d18SMatthew G. Knepley const PetscInt *cone; 9387f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9388f5869d18SMatthew G. Knepley 93899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 93909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9391f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9392f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 93937726db96SVaclav Hapla if (locals) { 93949566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 93957726db96SVaclav Hapla } else { 93967726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 93977726db96SVaclav Hapla } 939863a3b9bcSJacob 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]); 9399f5869d18SMatthew G. Knepley } 9400f5869d18SMatthew G. Knepley } 9401ece87651SVaclav Hapla } 94027726db96SVaclav Hapla } 94033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 940403da9461SVaclav Hapla } 940503da9461SVaclav Hapla 94067f9d8d6cSVaclav Hapla /*@ 940720f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 94087f9d8d6cSVaclav Hapla 94097f9d8d6cSVaclav Hapla Input Parameter: 9410a1cb98faSBarry Smith . dm - The `DMPLEX` object 9411a1cb98faSBarry Smith 9412a1cb98faSBarry Smith Level: developer 94137f9d8d6cSVaclav Hapla 94147f9d8d6cSVaclav Hapla Notes: 94157f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 94167f9d8d6cSVaclav Hapla 941720f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 94187f9d8d6cSVaclav Hapla 941920f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 94207f9d8d6cSVaclav Hapla 94211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 94227f9d8d6cSVaclav Hapla @*/ 9423d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9424d71ae5a4SJacob Faibussowitsch { 94257f9d8d6cSVaclav Hapla PetscInt cellHeight; 94267f9d8d6cSVaclav Hapla 9427b5a892a1SMatthew G. Knepley PetscFunctionBegin; 94287f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94299566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 94309566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 94319566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 94329566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9433d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 94349566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 94353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9436b5a892a1SMatthew G. Knepley } 9437b5a892a1SMatthew G. Knepley 94389371c9d4SSatish Balay typedef struct cell_stats { 9439068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9440068a5610SStefano Zampini PetscInt count; 9441068a5610SStefano Zampini } cell_stats_t; 9442068a5610SStefano Zampini 9443d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9444d71ae5a4SJacob Faibussowitsch { 9445068a5610SStefano Zampini PetscInt i, N = *len; 9446068a5610SStefano Zampini 9447068a5610SStefano Zampini for (i = 0; i < N; i++) { 9448068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9449068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9450068a5610SStefano Zampini 9451068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9452068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9453068a5610SStefano Zampini B->sum += A->sum; 9454068a5610SStefano Zampini B->squaresum += A->squaresum; 9455068a5610SStefano Zampini B->count += A->count; 9456068a5610SStefano Zampini } 9457068a5610SStefano Zampini } 9458068a5610SStefano Zampini 9459068a5610SStefano Zampini /*@ 946043fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9461068a5610SStefano Zampini 946220f4b53cSBarry Smith Collective 94638261a58bSMatthew G. Knepley 9464068a5610SStefano Zampini Input Parameters: 9465a1cb98faSBarry Smith + dm - The `DMPLEX` object 946620f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9467a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9468a1cb98faSBarry Smith 9469a1cb98faSBarry Smith Level: developer 9470068a5610SStefano Zampini 947195eb5ee5SVaclav Hapla Notes: 947295eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 947395eb5ee5SVaclav Hapla 9474a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9475068a5610SStefano Zampini 94761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9477068a5610SStefano Zampini @*/ 9478d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9479d71ae5a4SJacob Faibussowitsch { 9480068a5610SStefano Zampini DM dmCoarse; 948143fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 948243fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 948343fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 948443fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9485412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 948643fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9487068a5610SStefano Zampini 9488068a5610SStefano Zampini PetscFunctionBegin; 9489068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9490068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9491068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9492068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9493068a5610SStefano Zampini stats.count = 0; 9494068a5610SStefano Zampini 94959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 94969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 94979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 94989566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 94999566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 95009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9501412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9502068a5610SStefano Zampini PetscInt i; 9503068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9504068a5610SStefano Zampini 95059566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 950663a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 950743fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9508068a5610SStefano Zampini frobJ += J[i] * J[i]; 9509068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9510068a5610SStefano Zampini } 9511068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9512068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9513068a5610SStefano Zampini 9514068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9515068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9516068a5610SStefano Zampini stats.sum += cond; 9517068a5610SStefano Zampini stats.squaresum += cond2; 9518068a5610SStefano Zampini stats.count++; 95198261a58bSMatthew G. Knepley if (output && cond > limit) { 952043fa8764SMatthew G. Knepley PetscSection coordSection; 952143fa8764SMatthew G. Knepley Vec coordsLocal; 952243fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 952343fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 952443fa8764SMatthew G. Knepley 95259566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 95269566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 95279566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 952863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 952943fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 953063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 953143fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 95329566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 95339566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 953443fa8764SMatthew G. Knepley } 95359566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 953643fa8764SMatthew G. Knepley } 95379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 953843fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 953943fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 954043fa8764SMatthew G. Knepley 954143fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 954243fa8764SMatthew G. Knepley PetscReal len; 954343fa8764SMatthew G. Knepley 95449566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 954563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 954643fa8764SMatthew G. Knepley } 954743fa8764SMatthew G. Knepley } 95489566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 95499566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 955043fa8764SMatthew G. Knepley } 9551068a5610SStefano Zampini } 95529566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9553068a5610SStefano Zampini 9554068a5610SStefano Zampini if (size > 1) { 9555068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9556068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9557068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9558068a5610SStefano Zampini MPI_Op statReduce; 9559068a5610SStefano Zampini 95609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 95619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 95629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 95639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 95649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 95659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9566068a5610SStefano Zampini } else { 95679566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9568068a5610SStefano Zampini } 9569dd400576SPatrick Sanan if (rank == 0) { 9570068a5610SStefano Zampini count = globalStats.count; 9571068a5610SStefano Zampini min = globalStats.min; 9572068a5610SStefano Zampini max = globalStats.max; 9573068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9574068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9575068a5610SStefano Zampini } 9576068a5610SStefano Zampini 957748a46eb9SPierre 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)); 95789566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9579068a5610SStefano Zampini 95809566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9581068a5610SStefano Zampini if (dmCoarse) { 9582068a5610SStefano Zampini PetscBool isplex; 9583068a5610SStefano Zampini 95849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 95851baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9586068a5610SStefano Zampini } 95873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9588068a5610SStefano Zampini } 9589068a5610SStefano Zampini 9590f108dbd7SJacob Faibussowitsch /*@ 9591f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9592f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9593f108dbd7SJacob Faibussowitsch 959420f4b53cSBarry Smith Collective 9595f108dbd7SJacob Faibussowitsch 9596f108dbd7SJacob Faibussowitsch Input Parameters: 9597a1cb98faSBarry Smith + dm - The `DMPLEX` object 9598a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9599f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9600f108dbd7SJacob Faibussowitsch 9601f108dbd7SJacob Faibussowitsch Output Parameters: 960220f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9603a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9604f108dbd7SJacob Faibussowitsch 9605f108dbd7SJacob Faibussowitsch Options Database Keys: 9606a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9607f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9608f108dbd7SJacob Faibussowitsch 9609a1cb98faSBarry Smith Level: intermediate 9610a1cb98faSBarry Smith 9611f108dbd7SJacob Faibussowitsch Notes: 9612a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9613f108dbd7SJacob Faibussowitsch 9614a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9615f108dbd7SJacob Faibussowitsch 9616f108dbd7SJacob 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 9617f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9618f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9619f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9620f108dbd7SJacob Faibussowitsch 9621f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9622f108dbd7SJacob Faibussowitsch 9623a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9624f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9625f108dbd7SJacob Faibussowitsch 9626f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9627f108dbd7SJacob Faibussowitsch 96281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9629f108dbd7SJacob Faibussowitsch @*/ 9630d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9631d71ae5a4SJacob Faibussowitsch { 96326ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 96336ed19f2fSJacob Faibussowitsch PetscInt *idx; 96346ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9635f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 96366ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9637f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9638f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9639f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9640f108dbd7SJacob Faibussowitsch IS glob; 9641f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9642f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9643f108dbd7SJacob Faibussowitsch 9644f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9645f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9646ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 96474f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 96486bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 96499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 96509566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 965163a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 96526ed19f2fSJacob Faibussowitsch { 96536ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 96546ed19f2fSJacob Faibussowitsch 96559566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9656f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9657f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9658f108dbd7SJacob Faibussowitsch 96599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 966098921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9661f108dbd7SJacob Faibussowitsch } 96626ed19f2fSJacob Faibussowitsch } 9663f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 96644f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 96659566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 96669566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 96679371c9d4SSatish Balay } else { 96689371c9d4SSatish Balay *OrthQualLabel = NULL; 96699371c9d4SSatish Balay } 96709566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 96719566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 96729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 96739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 96749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 96759566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 96769566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 96779566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 96789566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 96799566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 96809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 96819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 96829566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 96839566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 96849566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 96859566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 96869566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 96879566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 96886ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 96896ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9690f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9691f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9692898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9693f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9694f108dbd7SJacob Faibussowitsch 96956ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9696f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9697f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 96989566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 96999566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9700f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 97019566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 97026ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 97036ed19f2fSJacob Faibussowitsch PetscInt i; 97046ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9705f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9706f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9707f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9708f108dbd7SJacob Faibussowitsch 9709f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9710f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 97119566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9712f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 97136ed19f2fSJacob Faibussowitsch { 97146ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 97156ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 97166ed19f2fSJacob Faibussowitsch 97179566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97189566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 97199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97206ed19f2fSJacob Faibussowitsch } 9721f108dbd7SJacob Faibussowitsch 9722f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9723f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9724f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9725f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9726f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9727addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9728addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9729addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9730f108dbd7SJacob Faibussowitsch } 9731addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9732addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9733addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9734f108dbd7SJacob Faibussowitsch 9735f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9736f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9737f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9738f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9739f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9740f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9741f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9742f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9743f108dbd7SJacob Faibussowitsch } 9744ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9745ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9746f108dbd7SJacob Faibussowitsch } 97479566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 97489566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9749f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 97506ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9751f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97529566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9753f108dbd7SJacob Faibussowitsch } 9754f108dbd7SJacob Faibussowitsch } 97559566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 97569566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 97579566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 97589566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 97599566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 97609566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9761f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97629566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9763f108dbd7SJacob Faibussowitsch } 97649566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 9765cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&vwr)); 97669566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 97673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9768f108dbd7SJacob Faibussowitsch } 9769f108dbd7SJacob Faibussowitsch 9770d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 97711eb70e55SToby Isaac * interpolator construction */ 9772d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9773d71ae5a4SJacob Faibussowitsch { 97741eb70e55SToby Isaac PetscSection section, newSection, gsection; 97751eb70e55SToby Isaac PetscSF sf; 97761eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 97771eb70e55SToby Isaac 97781eb70e55SToby Isaac PetscFunctionBegin; 97791eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97804f572ea9SToby Isaac PetscAssertPointer(odm, 2); 97819566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 97829566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9783712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 97841eb70e55SToby Isaac if (!ghasConstraints) { 97859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 97861eb70e55SToby Isaac *odm = dm; 97873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97881eb70e55SToby Isaac } 97899566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 97909566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 97919566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 97929566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 9793eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection)); 97949566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 97959566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 97963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97971eb70e55SToby Isaac } 97981eb70e55SToby Isaac 9799d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9800d71ae5a4SJacob Faibussowitsch { 98011eb70e55SToby Isaac DM dmco, dmfo; 98021eb70e55SToby Isaac Mat interpo; 98031eb70e55SToby Isaac Vec rscale; 98041eb70e55SToby Isaac Vec cglobalo, clocal; 98051eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 98061eb70e55SToby Isaac PetscBool regular; 98071eb70e55SToby Isaac 98081eb70e55SToby Isaac PetscFunctionBegin; 98099566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 98109566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 98119566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 98129566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 98139566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 98149566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 98159566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 98169566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 98179566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 98189566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 98199566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 98209566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 98219566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 98229566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 98239566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 98249566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 98259566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 98269566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 98279566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 98289566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 98299566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 98309566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 98319566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 98329566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 98331eb70e55SToby Isaac *shift = fglobal; 98349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 98359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 98369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 98379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 98389566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 98399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 98409566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 98419566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 98423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98431eb70e55SToby Isaac } 98441eb70e55SToby Isaac 9845d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9846d71ae5a4SJacob Faibussowitsch { 98471eb70e55SToby Isaac PetscObject shifto; 98481eb70e55SToby Isaac Vec shift; 98491eb70e55SToby Isaac 98501eb70e55SToby Isaac PetscFunctionBegin; 98511eb70e55SToby Isaac if (!interp) { 98521eb70e55SToby Isaac Vec rscale; 98531eb70e55SToby Isaac 98549566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 98559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 98561eb70e55SToby Isaac } else { 98579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 98581eb70e55SToby Isaac } 98599566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 98601eb70e55SToby Isaac if (!shifto) { 98619566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 98629566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 98631eb70e55SToby Isaac shifto = (PetscObject)shift; 98649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 98651eb70e55SToby Isaac } 98661eb70e55SToby Isaac shift = (Vec)shifto; 98679566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 98689566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 98699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 98703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98711eb70e55SToby Isaac } 98721eb70e55SToby Isaac 9873bceba477SMatthew G. Knepley /* Pointwise interpolation 9874bceba477SMatthew G. Knepley Just code FEM for now 9875bceba477SMatthew G. Knepley u^f = I u^c 98764ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 98774ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 98784ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9879bceba477SMatthew G. Knepley */ 9880d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9881d71ae5a4SJacob Faibussowitsch { 9882bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9883bceba477SMatthew G. Knepley PetscInt m, n; 9884a063dac3SMatthew G. Knepley void *ctx; 988568132eb9SMatthew G. Knepley DM cdm; 9886cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9887bceba477SMatthew G. Knepley 9888bceba477SMatthew G. Knepley PetscFunctionBegin; 98899566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 98909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 98919566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 98929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 989368132eb9SMatthew G. Knepley 98949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 98959566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 98969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 98979566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 98989566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 989968132eb9SMatthew G. Knepley 99009566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 99019566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 99029566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 99039566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 99049566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 99054db47ee9SStefano Zampini if (scaling) { 99065d1c2e58SMatthew G. Knepley /* Use naive scaling */ 99079566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 99084db47ee9SStefano Zampini } 99093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9910a063dac3SMatthew G. Knepley } 9911bceba477SMatthew G. Knepley 9912d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9913d71ae5a4SJacob Faibussowitsch { 99146dbf9973SLawrence Mitchell VecScatter ctx; 991590748bafSMatthew G. Knepley 9916a063dac3SMatthew G. Knepley PetscFunctionBegin; 99179566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 99189566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 99199566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 99203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9921bceba477SMatthew G. Knepley } 9922bceba477SMatthew G. Knepley 9923d71ae5a4SJacob 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[]) 9924d71ae5a4SJacob Faibussowitsch { 992500635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 992600635df3SMatthew G. Knepley PetscInt c; 992700635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 99283e9753d6SMatthew G. Knepley } 99293e9753d6SMatthew G. Knepley 9930d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9931d71ae5a4SJacob Faibussowitsch { 9932b4937a87SMatthew G. Knepley DM dmc; 9933b4937a87SMatthew G. Knepley PetscDS ds; 9934b4937a87SMatthew G. Knepley Vec ones, locmass; 9935b4937a87SMatthew G. Knepley IS cellIS; 9936b4937a87SMatthew G. Knepley PetscFormKey key; 9937b4937a87SMatthew G. Knepley PetscInt depth; 9938b4937a87SMatthew G. Knepley 9939b4937a87SMatthew G. Knepley PetscFunctionBegin; 99409566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 99419566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 99429566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 99439566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 99449566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 99459566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 99469566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 99479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 99489566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 99499566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 99509566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9951b4937a87SMatthew G. Knepley key.label = NULL; 9952b4937a87SMatthew G. Knepley key.value = 0; 9953b4937a87SMatthew G. Knepley key.field = 0; 9954b4937a87SMatthew G. Knepley key.part = 0; 99559566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 99569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 99579566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 99589566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 99599566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 99609566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 99619566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 99629566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 99633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9964b4937a87SMatthew G. Knepley } 9965b4937a87SMatthew G. Knepley 9966d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9967d71ae5a4SJacob Faibussowitsch { 9968bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9969bd041c0cSMatthew G. Knepley PetscInt m, n; 9970bd041c0cSMatthew G. Knepley void *ctx; 9971bd041c0cSMatthew G. Knepley DM cdm; 9972bd041c0cSMatthew G. Knepley PetscBool regular; 9973bd041c0cSMatthew G. Knepley 9974bd041c0cSMatthew G. Knepley PetscFunctionBegin; 99753e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 99763e9753d6SMatthew G. Knepley DM dmc; 99773e9753d6SMatthew G. Knepley PetscDS ds; 9978b4937a87SMatthew G. Knepley PetscWeakForm wf; 99793e9753d6SMatthew G. Knepley Vec u; 99803e9753d6SMatthew G. Knepley IS cellIS; 998106ad1575SMatthew G. Knepley PetscFormKey key; 99823e9753d6SMatthew G. Knepley PetscInt depth; 99833e9753d6SMatthew G. Knepley 99849566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 99859566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 99869566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 99879566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 99889566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 99899566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 99909566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 99918d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 99929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 99939566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 99949566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 99956528b96dSMatthew G. Knepley key.label = NULL; 99966528b96dSMatthew G. Knepley key.value = 0; 99976528b96dSMatthew G. Knepley key.field = 0; 999806ad1575SMatthew G. Knepley key.part = 0; 99999566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 100009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 100018d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 100029566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 100033e9753d6SMatthew G. Knepley } else { 100049566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 100059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 100069566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 100079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 10008bd041c0cSMatthew G. Knepley 100099566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 100109566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 100119566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 100129566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 10013bd041c0cSMatthew G. Knepley 100149566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 100159566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 100169566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 100179566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 100183e9753d6SMatthew G. Knepley } 100199566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 100203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10021bd041c0cSMatthew G. Knepley } 10022bd041c0cSMatthew G. Knepley 100230aef6b92SMatthew G. Knepley /*@ 100240aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100250aef6b92SMatthew G. Knepley 100260aef6b92SMatthew G. Knepley Input Parameter: 10027a1cb98faSBarry Smith . dm - The `DMPLEX` object 100280aef6b92SMatthew G. Knepley 100290aef6b92SMatthew G. Knepley Output Parameter: 100300aef6b92SMatthew G. Knepley . regular - The flag 100310aef6b92SMatthew G. Knepley 100320aef6b92SMatthew G. Knepley Level: intermediate 100330aef6b92SMatthew G. Knepley 100341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 100350aef6b92SMatthew G. Knepley @*/ 10036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10037d71ae5a4SJacob Faibussowitsch { 100380aef6b92SMatthew G. Knepley PetscFunctionBegin; 100390aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100404f572ea9SToby Isaac PetscAssertPointer(regular, 2); 100410aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 100423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100430aef6b92SMatthew G. Knepley } 100440aef6b92SMatthew G. Knepley 100450aef6b92SMatthew G. Knepley /*@ 100460aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100470aef6b92SMatthew G. Knepley 100480aef6b92SMatthew G. Knepley Input Parameters: 10049a1cb98faSBarry Smith + dm - The `DMPLEX` object 100500aef6b92SMatthew G. Knepley - regular - The flag 100510aef6b92SMatthew G. Knepley 100520aef6b92SMatthew G. Knepley Level: intermediate 100530aef6b92SMatthew G. Knepley 100541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 100550aef6b92SMatthew G. Knepley @*/ 10056d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10057d71ae5a4SJacob Faibussowitsch { 100580aef6b92SMatthew G. Knepley PetscFunctionBegin; 100590aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100600aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 100613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100620aef6b92SMatthew G. Knepley } 100630aef6b92SMatthew G. Knepley 10064a68b90caSToby Isaac /*@ 10065f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10066a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10067a68b90caSToby Isaac 10068a1cb98faSBarry Smith Not Collective 10069a68b90caSToby Isaac 10070f899ff85SJose E. Roman Input Parameter: 10071a1cb98faSBarry Smith . dm - The `DMPLEX` object 10072a68b90caSToby Isaac 10073a68b90caSToby Isaac Output Parameters: 1007420f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1007520f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10076a68b90caSToby Isaac 10077a68b90caSToby Isaac Level: intermediate 10078a68b90caSToby Isaac 100791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10080a68b90caSToby Isaac @*/ 10081d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 10082d71ae5a4SJacob Faibussowitsch { 10083a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10084a68b90caSToby Isaac 10085a68b90caSToby Isaac PetscFunctionBegin; 10086a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100879566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10088a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10089a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 100903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10091a68b90caSToby Isaac } 10092a68b90caSToby Isaac 10093a68b90caSToby Isaac /*@ 10094a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10095a68b90caSToby Isaac 1009620f4b53cSBarry Smith Collective 10097a68b90caSToby Isaac 10098a68b90caSToby Isaac Input Parameters: 10099a1cb98faSBarry Smith + dm - The `DMPLEX` object 10100a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10101a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10102a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10103a68b90caSToby Isaac 10104a68b90caSToby Isaac Level: intermediate 10105a68b90caSToby Isaac 10106a1cb98faSBarry Smith Notes: 10107a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10108a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10109a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10110a4e35b19SJacob Faibussowitsch 10111a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10112a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10113a1cb98faSBarry Smith 1011420f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10115a1cb98faSBarry Smith 101161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10117a68b90caSToby Isaac @*/ 10118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10119d71ae5a4SJacob Faibussowitsch { 10120a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10121e228b242SToby Isaac PetscMPIInt result; 10122a68b90caSToby Isaac 10123a68b90caSToby Isaac PetscFunctionBegin; 10124a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10125e228b242SToby Isaac if (anchorSection) { 10126e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 101279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 101281dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10129e228b242SToby Isaac } 10130e228b242SToby Isaac if (anchorIS) { 10131e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 101329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 101331dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10134e228b242SToby Isaac } 10135a68b90caSToby Isaac 101369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 101379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10138a68b90caSToby Isaac plex->anchorSection = anchorSection; 10139a68b90caSToby Isaac 101409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 101419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10142a68b90caSToby Isaac plex->anchorIS = anchorIS; 10143a68b90caSToby Isaac 10144cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10145a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10146a68b90caSToby Isaac const PetscInt *anchors; 10147a68b90caSToby Isaac 101489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 101499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 101509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10151a68b90caSToby Isaac for (a = 0; a < size; a++) { 10152a68b90caSToby Isaac PetscInt p; 10153a68b90caSToby Isaac 10154a68b90caSToby Isaac p = anchors[a]; 10155a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10156a68b90caSToby Isaac PetscInt dof; 10157a68b90caSToby Isaac 101589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10159a68b90caSToby Isaac if (dof) { 101609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1016163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10162a68b90caSToby Isaac } 10163a68b90caSToby Isaac } 10164a68b90caSToby Isaac } 101659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10166a68b90caSToby Isaac } 10167f7c74593SToby Isaac /* reset the generic constraints */ 101689566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 101693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10170a68b90caSToby Isaac } 10171a68b90caSToby Isaac 10172d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10173d71ae5a4SJacob Faibussowitsch { 10174f7c74593SToby Isaac PetscSection anchorSection; 101756995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10176a68b90caSToby Isaac 10177a68b90caSToby Isaac PetscFunctionBegin; 10178a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101799566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 101809566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 101819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 101826995de1eSToby Isaac if (numFields) { 10183719ab38cSToby Isaac PetscInt f; 101849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10185719ab38cSToby Isaac 10186719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10187719ab38cSToby Isaac PetscInt numComp; 10188719ab38cSToby Isaac 101899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 101909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10191719ab38cSToby Isaac } 101926995de1eSToby Isaac } 101939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 101949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 101956995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 101966995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 101976995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 101989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10199a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 102009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10201a68b90caSToby Isaac if (dof) { 102029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 102039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10204a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 102059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 102069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10207a68b90caSToby Isaac } 10208a68b90caSToby Isaac } 10209a68b90caSToby Isaac } 102109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 102119566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 102123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10213a68b90caSToby Isaac } 10214a68b90caSToby Isaac 10215d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10216d71ae5a4SJacob Faibussowitsch { 10217f7c74593SToby Isaac PetscSection aSec; 10218ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 102190ac89760SToby Isaac const PetscInt *anchors; 102200ac89760SToby Isaac PetscInt numFields, f; 1022166ad2231SToby Isaac IS aIS; 10222e19f7ee6SMark Adams MatType mtype; 10223e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 102240ac89760SToby Isaac 102250ac89760SToby Isaac PetscFunctionBegin; 102260ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 102289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 102299566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 102309566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 102319566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 102329566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 102339566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 102349566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10235e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10236e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10237e19f7ee6SMark Adams else mtype = MATSEQAIJ; 102389566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 102399566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 102409566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 102416995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 102429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 102439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 102449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 102450ac89760SToby Isaac i[0] = 0; 102469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 102470ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10248f19733c5SToby Isaac PetscInt rDof, rOff, r; 10249f19733c5SToby Isaac 102509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10251f19733c5SToby Isaac if (!rDof) continue; 102529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102530ac89760SToby Isaac if (numFields) { 102540ac89760SToby Isaac for (f = 0; f < numFields; f++) { 102550ac89760SToby Isaac annz = 0; 10256f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10257f19733c5SToby Isaac a = anchors[rOff + r]; 10258ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 102600ac89760SToby Isaac annz += aDof; 102610ac89760SToby Isaac } 102629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 102639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10264ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 102650ac89760SToby Isaac } 102662f7452b8SBarry Smith } else { 102670ac89760SToby Isaac annz = 0; 102689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102690ac89760SToby Isaac for (q = 0; q < dof; q++) { 10270ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10271ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 102730ac89760SToby Isaac annz += aDof; 102740ac89760SToby Isaac } 102759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10277ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 102780ac89760SToby Isaac } 102790ac89760SToby Isaac } 102800ac89760SToby Isaac nnz = i[m]; 102819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 102820ac89760SToby Isaac offset = 0; 102830ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 102840ac89760SToby Isaac if (numFields) { 102850ac89760SToby Isaac for (f = 0; f < numFields; f++) { 102869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 102870ac89760SToby Isaac for (q = 0; q < dof; q++) { 102880ac89760SToby Isaac PetscInt rDof, rOff, r; 102899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 102909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102910ac89760SToby Isaac for (r = 0; r < rDof; r++) { 102920ac89760SToby Isaac PetscInt s; 102930ac89760SToby Isaac 102940ac89760SToby Isaac a = anchors[rOff + r]; 10295ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 102979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10298ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 102990ac89760SToby Isaac } 103000ac89760SToby Isaac } 103010ac89760SToby Isaac } 103022f7452b8SBarry Smith } else { 103039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103040ac89760SToby Isaac for (q = 0; q < dof; q++) { 103050ac89760SToby Isaac PetscInt rDof, rOff, r; 103069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 103079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103080ac89760SToby Isaac for (r = 0; r < rDof; r++) { 103090ac89760SToby Isaac PetscInt s; 103100ac89760SToby Isaac 103110ac89760SToby Isaac a = anchors[rOff + r]; 10312ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 103149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10315ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 103160ac89760SToby Isaac } 103170ac89760SToby Isaac } 103180ac89760SToby Isaac } 103190ac89760SToby Isaac } 103209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 103219566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 103229566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 103239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 103243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103250ac89760SToby Isaac } 103260ac89760SToby Isaac 10327d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10328d71ae5a4SJacob Faibussowitsch { 10329f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10330f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1033166ad2231SToby Isaac Mat cMat; 1033266ad2231SToby Isaac 1033366ad2231SToby Isaac PetscFunctionBegin; 1033466ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 103359566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1033666ad2231SToby Isaac if (anchorSection) { 1033744a7f3ddSMatthew G. Knepley PetscInt Nf; 10338e228b242SToby Isaac 103399566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 103409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 103419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 103429566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 103439566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 103449566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 103459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 103469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1034766ad2231SToby Isaac } 103483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1034966ad2231SToby Isaac } 10350a93c429eSMatthew G. Knepley 10351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10352d71ae5a4SJacob Faibussowitsch { 10353a93c429eSMatthew G. Knepley IS subis; 10354a93c429eSMatthew G. Knepley PetscSection section, subsection; 10355a93c429eSMatthew G. Knepley 10356a93c429eSMatthew G. Knepley PetscFunctionBegin; 103579566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1035828b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1035928b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10360a93c429eSMatthew G. Knepley /* Create subdomain */ 1036130cbcd5dSksagiyam PetscCall(DMPlexFilter(dm, label, value, PETSC_FALSE, PETSC_FALSE, NULL, subdm)); 10362a93c429eSMatthew G. Knepley /* Create submodel */ 103639566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 103649566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 103659566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 103669566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 103679566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10368a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10369a93c429eSMatthew G. Knepley if (is) { 10370a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10371a93c429eSMatthew G. Knepley IS spIS; 10372a93c429eSMatthew G. Knepley const PetscInt *spmap; 10373a93c429eSMatthew G. Knepley PetscInt *subIndices; 10374a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10375a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10376a93c429eSMatthew G. Knepley 103779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 103789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 103799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 103809566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 103819566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 103829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10383a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10384a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10385a93c429eSMatthew G. Knepley 103869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10387a93c429eSMatthew G. Knepley if (gdof > 0) { 10388a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10389a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10390a93c429eSMatthew G. Knepley 103919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 103929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10393a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10394a93c429eSMatthew G. Knepley } 10395a93c429eSMatthew G. Knepley subSize += pSubSize; 10396a93c429eSMatthew G. Knepley if (pSubSize) { 10397a93c429eSMatthew G. Knepley if (bs < 0) { 10398a93c429eSMatthew G. Knepley bs = pSubSize; 10399a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10400a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10401a93c429eSMatthew G. Knepley bs = 1; 10402a93c429eSMatthew G. Knepley } 10403a93c429eSMatthew G. Knepley } 10404a93c429eSMatthew G. Knepley } 10405a93c429eSMatthew G. Knepley } 10406a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 104079371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 104089371c9d4SSatish Balay bsLocal[1] = bs; 104099566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 104109371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 104119371c9d4SSatish Balay bs = 1; 104129371c9d4SSatish Balay } else { 104139371c9d4SSatish Balay bs = bsMinMax[0]; 104149371c9d4SSatish Balay } 104159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10416a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10417a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10418a93c429eSMatthew G. Knepley 104199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10420a93c429eSMatthew G. Knepley if (gdof > 0) { 10421a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10422a93c429eSMatthew G. Knepley 104239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10424a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10425a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10426a93c429eSMatthew G. Knepley 10427a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10428a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 104299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 104309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10431a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10432a93c429eSMatthew G. Knepley } 104339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 104349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10435ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10436a93c429eSMatthew G. Knepley } 10437a93c429eSMatthew G. Knepley } 10438a93c429eSMatthew G. Knepley } 104399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 104409566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10441a93c429eSMatthew G. Knepley if (bs > 1) { 10442a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10443a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10444a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10445a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 104469371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 104479371c9d4SSatish Balay set = 0; 104489371c9d4SSatish Balay break; 104499371c9d4SSatish Balay } 10450a93c429eSMatthew G. Knepley } 10451a93c429eSMatthew G. Knepley } 104529566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10453a93c429eSMatthew G. Knepley } 10454a93c429eSMatthew G. Knepley /* Attach nullspace */ 10455a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10456a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10457a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10458a93c429eSMatthew G. Knepley } 10459a93c429eSMatthew G. Knepley if (f < Nf) { 10460a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 104619566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 104626823f3c5SBlaise Bourdin 104639566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 104649566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10465a93c429eSMatthew G. Knepley } 10466a93c429eSMatthew G. Knepley } 104673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10468a93c429eSMatthew G. Knepley } 10469c0f0dcc3SMatthew G. Knepley 10470c0f0dcc3SMatthew G. Knepley /*@ 10471c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10472c0f0dcc3SMatthew G. Knepley 10473a1cb98faSBarry Smith Input Parameters: 10474a1cb98faSBarry Smith + dm - The `DM` 10475a1cb98faSBarry Smith - dummy - unused argument 10476a1cb98faSBarry Smith 10477a1cb98faSBarry Smith Options Database Key: 10478a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10479c0f0dcc3SMatthew G. Knepley 10480c0f0dcc3SMatthew G. Knepley Level: developer 10481c0f0dcc3SMatthew G. Knepley 104821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10483c0f0dcc3SMatthew G. Knepley @*/ 10484d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10485d71ae5a4SJacob Faibussowitsch { 10486b665b14eSToby Isaac PetscLogHandler default_handler; 10487b665b14eSToby Isaac 104882611ad71SToby Isaac PetscFunctionBegin; 104892611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10490b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10491b665b14eSToby Isaac if (default_handler) { 10492c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10493c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10494c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10495c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10496c0f0dcc3SMatthew G. Knepley const char *name; 10497c0f0dcc3SMatthew G. Knepley 104989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 104999566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 105009566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 105019566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10502b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10503c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10504c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10505c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1050663a3b9bcSJacob 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))); 105072611ad71SToby Isaac } else { 10508b665b14eSToby 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."); 105092611ad71SToby Isaac } 105103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10511c0f0dcc3SMatthew G. Knepley } 10512