19cbb8f0dSMatthew G. Knepley #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 29cbb8f0dSMatthew G. Knepley 39cbb8f0dSMatthew G. Knepley /* Set the number of dof on each point and separate by fields */ 4d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSectionFields(DM dm, const PetscInt numComp[], PetscSection *section) 5d71ae5a4SJacob Faibussowitsch { 6baef929fSMatthew G. Knepley DMLabel depthLabel; 7baef929fSMatthew G. Knepley PetscInt depth, Nf, f, pStart, pEnd; 89cbb8f0dSMatthew G. Knepley PetscBool *isFE; 99cbb8f0dSMatthew G. Knepley 109cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 139566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 149566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &isFE)); 15baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 169cbb8f0dSMatthew G. Knepley PetscObject obj; 179cbb8f0dSMatthew G. Knepley PetscClassId id; 189cbb8f0dSMatthew G. Knepley 199566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, &obj)); 209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 219371c9d4SSatish Balay if (id == PETSCFE_CLASSID) { 229371c9d4SSatish Balay isFE[f] = PETSC_TRUE; 239371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) { 249371c9d4SSatish Balay isFE[f] = PETSC_FALSE; 259371c9d4SSatish Balay } 269cbb8f0dSMatthew G. Knepley } 27baef929fSMatthew G. Knepley 289566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), section)); 29baef929fSMatthew G. Knepley if (Nf > 0) { 309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*section, Nf)); 319cbb8f0dSMatthew G. Knepley if (numComp) { 32baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*section, f, numComp[f])); 349cbb8f0dSMatthew G. Knepley if (isFE[f]) { 359cbb8f0dSMatthew G. Knepley PetscFE fe; 369cbb8f0dSMatthew G. Knepley PetscDualSpace dspace; 379cbb8f0dSMatthew G. Knepley const PetscInt ***perms; 389cbb8f0dSMatthew G. Knepley const PetscScalar ***flips; 399cbb8f0dSMatthew G. Knepley const PetscInt *numDof; 409cbb8f0dSMatthew G. Knepley 419566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe)); 429566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dspace)); 439566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dspace, &perms, &flips)); 449566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dspace, &numDof)); 459cbb8f0dSMatthew G. Knepley if (perms || flips) { 469cbb8f0dSMatthew G. Knepley DM K; 474dff28b8SMatthew G. Knepley PetscInt sph, spdepth; 489cbb8f0dSMatthew G. Knepley PetscSectionSym sym; 499cbb8f0dSMatthew G. Knepley 509566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(dspace, &K)); 519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(K, &spdepth)); 529566063dSJacob Faibussowitsch PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)*section), depthLabel, &sym)); 534dff28b8SMatthew G. Knepley for (sph = 0; sph <= spdepth; sph++) { 549cbb8f0dSMatthew G. Knepley PetscDualSpace hspace; 559cbb8f0dSMatthew G. Knepley PetscInt kStart, kEnd; 564dff28b8SMatthew G. Knepley PetscInt kConeSize, h = sph + (depth - spdepth); 579cbb8f0dSMatthew G. Knepley const PetscInt **perms0 = NULL; 589cbb8f0dSMatthew G. Knepley const PetscScalar **flips0 = NULL; 599cbb8f0dSMatthew G. Knepley 609566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dspace, sph, &hspace)); 619566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, h, &kStart, &kEnd)); 629cbb8f0dSMatthew G. Knepley if (!hspace) continue; 639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(hspace, &perms, &flips)); 649cbb8f0dSMatthew G. Knepley if (perms) perms0 = perms[0]; 659cbb8f0dSMatthew G. Knepley if (flips) flips0 = flips[0]; 669cbb8f0dSMatthew G. Knepley if (!(perms0 || flips0)) continue; 67b5a892a1SMatthew G. Knepley { 68b5a892a1SMatthew G. Knepley DMPolytopeType ct; 69b5a892a1SMatthew G. Knepley /* The number of arrangements is no longer based on the number of faces */ 709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, kStart, &ct)); 71b5a892a1SMatthew G. Knepley kConeSize = DMPolytopeTypeGetNumArrangments(ct) / 2; 72b5a892a1SMatthew G. Knepley } 739566063dSJacob Faibussowitsch PetscCall(PetscSectionSymLabelSetStratum(sym, depth - h, numDof[depth - h], -kConeSize, kConeSize, PETSC_USE_POINTER, perms0 ? &perms0[-kConeSize] : NULL, flips0 ? &flips0[-kConeSize] : NULL)); 749cbb8f0dSMatthew G. Knepley } 759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldSym(*section, f, sym)); 769566063dSJacob Faibussowitsch PetscCall(PetscSectionSymDestroy(&sym)); 779cbb8f0dSMatthew G. Knepley } 789cbb8f0dSMatthew G. Knepley } 799cbb8f0dSMatthew G. Knepley } 809cbb8f0dSMatthew G. Knepley } 819cbb8f0dSMatthew G. Knepley } 829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*section, pStart, pEnd)); 849566063dSJacob Faibussowitsch PetscCall(PetscFree(isFE)); 853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86baef929fSMatthew G. Knepley } 87baef929fSMatthew G. Knepley 88baef929fSMatthew G. Knepley /* Set the number of dof on each point and separate by fields */ 89d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSectionDof(DM dm, DMLabel label[], const PetscInt numDof[], PetscSection section) 90d71ae5a4SJacob Faibussowitsch { 91baef929fSMatthew G. Knepley DMLabel depthLabel; 92412e9a14SMatthew G. Knepley DMPolytopeType ct; 93baef929fSMatthew G. Knepley PetscInt depth, cellHeight, pStart = 0, pEnd = 0; 94a55f9a55SMatthew G. Knepley PetscInt Nf, f, Nds, n, dim, d, dep, p; 955fedec97SMatthew G. Knepley PetscBool *isFE, hasCohesive = PETSC_FALSE; 96baef929fSMatthew G. Knepley 97baef929fSMatthew G. Knepley PetscFunctionBegin; 989566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 999566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 1009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 1019566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 1029566063dSJacob Faibussowitsch PetscCall(DMGetNumDS(dm, &Nds)); 103a55f9a55SMatthew G. Knepley for (n = 0; n < Nds; ++n) { 104a55f9a55SMatthew G. Knepley PetscDS ds; 1055fedec97SMatthew G. Knepley PetscBool isCohesive; 106a55f9a55SMatthew G. Knepley 10707218a29SMatthew G. Knepley PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds, NULL)); 1089566063dSJacob Faibussowitsch PetscCall(PetscDSIsCohesive(ds, &isCohesive)); 1099371c9d4SSatish Balay if (isCohesive) { 1109371c9d4SSatish Balay hasCohesive = PETSC_TRUE; 1119371c9d4SSatish Balay break; 1129371c9d4SSatish Balay } 113a55f9a55SMatthew G. Knepley } 1149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nf, &isFE)); 115baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 116baef929fSMatthew G. Knepley PetscObject obj; 117baef929fSMatthew G. Knepley PetscClassId id; 118baef929fSMatthew G. Knepley 1199566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, &obj)); 1209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 1211274e1a1SLawrence Mitchell /* User is allowed to put a "placeholder" field in (c.f. DMCreateDS) */ 1221274e1a1SLawrence Mitchell isFE[f] = id == PETSCFE_CLASSID ? PETSC_TRUE : PETSC_FALSE; 123baef929fSMatthew G. Knepley } 124baef929fSMatthew G. Knepley 1259566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 126baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 127e0b68406SMatthew Knepley PetscBool avoidTensor; 128e0b68406SMatthew Knepley 1299566063dSJacob Faibussowitsch PetscCall(DMGetFieldAvoidTensor(dm, f, &avoidTensor)); 1305fedec97SMatthew G. Knepley avoidTensor = (avoidTensor || hasCohesive) ? PETSC_TRUE : PETSC_FALSE; 131baef929fSMatthew G. Knepley if (label && label[f]) { 132baef929fSMatthew G. Knepley IS pointIS; 133baef929fSMatthew G. Knepley const PetscInt *points; 134baef929fSMatthew G. Knepley PetscInt n; 135baef929fSMatthew G. Knepley 1369566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label[f], 1, &pointIS)); 137baef929fSMatthew G. Knepley if (!pointIS) continue; 1389566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &n)); 1399566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 140baef929fSMatthew G. Knepley for (p = 0; p < n; ++p) { 141baef929fSMatthew G. Knepley const PetscInt point = points[p]; 142baef929fSMatthew G. Knepley PetscInt dof, d; 143baef929fSMatthew G. Knepley 1449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, point, &ct)); 1459566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &d)); 146412e9a14SMatthew G. Knepley /* If this is a tensor prism point, use dof for one dimension lower */ 147412e9a14SMatthew G. Knepley switch (ct) { 148412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 149412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 150412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 151412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 152ad540459SPierre Jolivet if (hasCohesive) --d; 1539371c9d4SSatish Balay break; 154d71ae5a4SJacob Faibussowitsch default: 155d71ae5a4SJacob Faibussowitsch break; 156412e9a14SMatthew G. Knepley } 157baef929fSMatthew G. Knepley dof = d < 0 ? 0 : numDof[f * (dim + 1) + d]; 1589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(section, point, f, dof)); 1599566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, point, dof)); 160baef929fSMatthew G. Knepley } 1619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 1629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 163baef929fSMatthew G. Knepley } else { 1649cbb8f0dSMatthew G. Knepley for (dep = 0; dep <= depth - cellHeight; ++dep) { 1653fd2e703SMatthew G. Knepley /* Cases: dim > depth (cell-vertex mesh), dim == depth (fully interpolated), dim < depth (interpolated submesh) */ 1663fd2e703SMatthew G. Knepley d = dim <= depth ? dep : (!dep ? 0 : dim); 1679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd)); 1689cbb8f0dSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 169baef929fSMatthew G. Knepley const PetscInt dof = numDof[f * (dim + 1) + d]; 1709cbb8f0dSMatthew G. Knepley 1719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 172412e9a14SMatthew G. Knepley switch (ct) { 173412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 174412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 175412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 176412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 177e0b68406SMatthew Knepley if (avoidTensor && isFE[f]) continue; 178d71ae5a4SJacob Faibussowitsch default: 179d71ae5a4SJacob Faibussowitsch break; 180412e9a14SMatthew G. Knepley } 1819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(section, p, f, dof)); 1829566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, dof)); 1839cbb8f0dSMatthew G. Knepley } 184baef929fSMatthew G. Knepley } 1859cbb8f0dSMatthew G. Knepley } 1869cbb8f0dSMatthew G. Knepley } 1879566063dSJacob Faibussowitsch PetscCall(PetscFree(isFE)); 1883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1899cbb8f0dSMatthew G. Knepley } 1909cbb8f0dSMatthew G. Knepley 1919cbb8f0dSMatthew G. Knepley /* Set the number of dof on each point and separate by fields 1929cbb8f0dSMatthew G. Knepley If bcComps is NULL or the IS is NULL, constrain every dof on the point 1939cbb8f0dSMatthew G. Knepley */ 194d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 195d71ae5a4SJacob Faibussowitsch { 196baef929fSMatthew G. Knepley PetscInt Nf; 1979cbb8f0dSMatthew G. Knepley PetscInt bc; 1989cbb8f0dSMatthew G. Knepley PetscSection aSec; 1999cbb8f0dSMatthew G. Knepley 2009cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 2019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 2029cbb8f0dSMatthew G. Knepley for (bc = 0; bc < numBC; ++bc) { 2039cbb8f0dSMatthew G. Knepley PetscInt field = 0; 2049cbb8f0dSMatthew G. Knepley const PetscInt *comp; 2059cbb8f0dSMatthew G. Knepley const PetscInt *idx; 206ce093827SMatthew G. Knepley PetscInt Nc = 0, cNc = -1, n, i; 2079cbb8f0dSMatthew G. Knepley 208ce093827SMatthew G. Knepley if (Nf) { 209ce093827SMatthew G. Knepley field = bcField[bc]; 2109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, &Nc)); 211ce093827SMatthew G. Knepley } 2129566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISGetLocalSize(bcComps[bc], &cNc)); 2139566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISGetIndices(bcComps[bc], &comp)); 21424cfc5f6SToby Isaac if (bcPoints[bc]) { 2159566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bcPoints[bc], &n)); 2169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(bcPoints[bc], &idx)); 2179cbb8f0dSMatthew G. Knepley for (i = 0; i < n; ++i) { 2189cbb8f0dSMatthew G. Knepley const PetscInt p = idx[i]; 2199cbb8f0dSMatthew G. Knepley PetscInt numConst; 2209cbb8f0dSMatthew G. Knepley 221baef929fSMatthew G. Knepley if (Nf) { 2229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, field, &numConst)); 2239cbb8f0dSMatthew G. Knepley } else { 2249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numConst)); 2259cbb8f0dSMatthew G. Knepley } 226ce093827SMatthew G. Knepley /* If Nc <= 0, constrain every dof on the point */ 227ce093827SMatthew G. Knepley if (cNc > 0) { 228ce093827SMatthew G. Knepley /* We assume that a point may have multiple "nodes", which are collections of Nc dofs, 229ce093827SMatthew G. Knepley and that those dofs are numbered n*Nc+c */ 230ce093827SMatthew G. Knepley if (Nf) { 23163a3b9bcSJacob Faibussowitsch PetscCheck(numConst % Nc == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " has %" PetscInt_FMT " dof which is not divisible by %" PetscInt_FMT " field components", p, numConst, Nc); 232ce093827SMatthew G. Knepley numConst = (numConst / Nc) * cNc; 233ce093827SMatthew G. Knepley } else { 234ce093827SMatthew G. Knepley numConst = PetscMin(numConst, cNc); 235ce093827SMatthew G. Knepley } 236ce093827SMatthew G. Knepley } 2379566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionAddFieldConstraintDof(section, p, field, numConst)); 2389566063dSJacob Faibussowitsch PetscCall(PetscSectionAddConstraintDof(section, p, numConst)); 2399cbb8f0dSMatthew G. Knepley } 2409566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(bcPoints[bc], &idx)); 24124cfc5f6SToby Isaac } 2429566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISRestoreIndices(bcComps[bc], &comp)); 2439cbb8f0dSMatthew G. Knepley } 2449566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, NULL)); 2459cbb8f0dSMatthew G. Knepley if (aSec) { 2469cbb8f0dSMatthew G. Knepley PetscInt aStart, aEnd, a; 2479cbb8f0dSMatthew G. Knepley 2489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 2499cbb8f0dSMatthew G. Knepley for (a = aStart; a < aEnd; a++) { 2509cbb8f0dSMatthew G. Knepley PetscInt dof, f; 2519cbb8f0dSMatthew G. Knepley 2529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, a, &dof)); 2539cbb8f0dSMatthew G. Knepley if (dof) { 2549cbb8f0dSMatthew G. Knepley /* if there are point-to-point constraints, then all dofs are constrained */ 2559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &dof)); 2569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, a, dof)); 257baef929fSMatthew G. Knepley for (f = 0; f < Nf; f++) { 2589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &dof)); 2599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldConstraintDof(section, a, f, dof)); 2609cbb8f0dSMatthew G. Knepley } 2619cbb8f0dSMatthew G. Knepley } 2629cbb8f0dSMatthew G. Knepley } 2639cbb8f0dSMatthew G. Knepley } 2643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2659cbb8f0dSMatthew G. Knepley } 2669cbb8f0dSMatthew G. Knepley 2679cbb8f0dSMatthew G. Knepley /* Set the constrained field indices on each point 2689cbb8f0dSMatthew G. Knepley If bcComps is NULL or the IS is NULL, constrain every dof on the point 2699cbb8f0dSMatthew G. Knepley */ 270d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 271d71ae5a4SJacob Faibussowitsch { 2729cbb8f0dSMatthew G. Knepley PetscSection aSec; 2739cbb8f0dSMatthew G. Knepley PetscInt *indices; 274baef929fSMatthew G. Knepley PetscInt Nf, cdof, maxDof = 0, pStart, pEnd, p, bc, f, d; 2759cbb8f0dSMatthew G. Knepley 2769cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 2779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 2783ba16761SJacob Faibussowitsch if (!Nf) PetscFunctionReturn(PETSC_SUCCESS); 2799cbb8f0dSMatthew G. Knepley /* Initialize all field indices to -1 */ 2809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2819371c9d4SSatish Balay for (p = pStart; p < pEnd; ++p) { 2829371c9d4SSatish Balay PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 2839371c9d4SSatish Balay maxDof = PetscMax(maxDof, cdof); 2849371c9d4SSatish Balay } 2859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &indices)); 2869cbb8f0dSMatthew G. Knepley for (d = 0; d < maxDof; ++d) indices[d] = -1; 2879371c9d4SSatish Balay for (p = pStart; p < pEnd; ++p) 2889371c9d4SSatish Balay for (f = 0; f < Nf; ++f) PetscCall(PetscSectionSetFieldConstraintIndices(section, p, f, indices)); 2899cbb8f0dSMatthew G. Knepley /* Handle BC constraints */ 2909cbb8f0dSMatthew G. Knepley for (bc = 0; bc < numBC; ++bc) { 2919cbb8f0dSMatthew G. Knepley const PetscInt field = bcField[bc]; 2929cbb8f0dSMatthew G. Knepley const PetscInt *comp, *idx; 293ce093827SMatthew G. Knepley PetscInt Nc, cNc = -1, n, i; 2949cbb8f0dSMatthew G. Knepley 2959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, &Nc)); 2969566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISGetLocalSize(bcComps[bc], &cNc)); 2979566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISGetIndices(bcComps[bc], &comp)); 29824cfc5f6SToby Isaac if (bcPoints[bc]) { 2999566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bcPoints[bc], &n)); 3009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(bcPoints[bc], &idx)); 3019cbb8f0dSMatthew G. Knepley for (i = 0; i < n; ++i) { 3029cbb8f0dSMatthew G. Knepley const PetscInt p = idx[i]; 3039cbb8f0dSMatthew G. Knepley const PetscInt *find; 304ce093827SMatthew G. Knepley PetscInt fdof, fcdof, c, j; 3059cbb8f0dSMatthew G. Knepley 3069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, field, &fdof)); 3079cbb8f0dSMatthew G. Knepley if (!fdof) continue; 308ce093827SMatthew G. Knepley if (cNc < 0) { 3099cbb8f0dSMatthew G. Knepley for (d = 0; d < fdof; ++d) indices[d] = d; 3109cbb8f0dSMatthew G. Knepley fcdof = fdof; 3119cbb8f0dSMatthew G. Knepley } else { 312ce093827SMatthew G. Knepley /* We assume that a point may have multiple "nodes", which are collections of Nc dofs, 313ce093827SMatthew G. Knepley and that those dofs are numbered n*Nc+c */ 3149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, field, &fcdof)); 3159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, p, field, &find)); 316ce093827SMatthew G. Knepley /* Get indices constrained by previous bcs */ 3179371c9d4SSatish Balay for (d = 0; d < fcdof; ++d) { 3189371c9d4SSatish Balay if (find[d] < 0) break; 3199371c9d4SSatish Balay indices[d] = find[d]; 3209371c9d4SSatish Balay } 3219371c9d4SSatish Balay for (j = 0; j < fdof / Nc; ++j) 3229371c9d4SSatish Balay for (c = 0; c < cNc; ++c) indices[d++] = j * Nc + comp[c]; 3239566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&d, indices)); 3249cbb8f0dSMatthew G. Knepley for (c = d; c < fcdof; ++c) indices[c] = -1; 3259cbb8f0dSMatthew G. Knepley fcdof = d; 3269cbb8f0dSMatthew G. Knepley } 3279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldConstraintDof(section, p, field, fcdof)); 3289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldConstraintIndices(section, p, field, indices)); 3299cbb8f0dSMatthew G. Knepley } 3309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(bcPoints[bc], &idx)); 3319cbb8f0dSMatthew G. Knepley } 33224cfc5f6SToby Isaac if (bcComps && bcComps[bc]) PetscCall(ISRestoreIndices(bcComps[bc], &comp)); 33324cfc5f6SToby Isaac } 3349cbb8f0dSMatthew G. Knepley /* Handle anchors */ 3359566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, NULL)); 3369cbb8f0dSMatthew G. Knepley if (aSec) { 3379cbb8f0dSMatthew G. Knepley PetscInt aStart, aEnd, a; 3389cbb8f0dSMatthew G. Knepley 3399cbb8f0dSMatthew G. Knepley for (d = 0; d < maxDof; ++d) indices[d] = d; 3409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 3419cbb8f0dSMatthew G. Knepley for (a = aStart; a < aEnd; a++) { 3429cbb8f0dSMatthew G. Knepley PetscInt dof, f; 3439cbb8f0dSMatthew G. Knepley 3449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, a, &dof)); 3459cbb8f0dSMatthew G. Knepley if (dof) { 3469cbb8f0dSMatthew G. Knepley /* if there are point-to-point constraints, then all dofs are constrained */ 34748a46eb9SPierre Jolivet for (f = 0; f < Nf; f++) PetscCall(PetscSectionSetFieldConstraintIndices(section, a, f, indices)); 3489cbb8f0dSMatthew G. Knepley } 3499cbb8f0dSMatthew G. Knepley } 3509cbb8f0dSMatthew G. Knepley } 3519566063dSJacob Faibussowitsch PetscCall(PetscFree(indices)); 3523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3539cbb8f0dSMatthew G. Knepley } 3549cbb8f0dSMatthew G. Knepley 3559cbb8f0dSMatthew G. Knepley /* Set the constrained indices on each point */ 356d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 357d71ae5a4SJacob Faibussowitsch { 3589cbb8f0dSMatthew G. Knepley PetscInt *indices; 359baef929fSMatthew G. Knepley PetscInt Nf, maxDof, pStart, pEnd, p, f, d; 3609cbb8f0dSMatthew G. Knepley 3619cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 3629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 3639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 3649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 3659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &indices)); 3669cbb8f0dSMatthew G. Knepley for (d = 0; d < maxDof; ++d) indices[d] = -1; 3679cbb8f0dSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3689cbb8f0dSMatthew G. Knepley PetscInt cdof, d; 3699cbb8f0dSMatthew G. Knepley 3709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 3719cbb8f0dSMatthew G. Knepley if (cdof) { 372baef929fSMatthew G. Knepley if (Nf) { 3739cbb8f0dSMatthew G. Knepley PetscInt numConst = 0, foff = 0; 3749cbb8f0dSMatthew G. Knepley 375baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 3769cbb8f0dSMatthew G. Knepley const PetscInt *find; 3779cbb8f0dSMatthew G. Knepley PetscInt fcdof, fdof; 3789cbb8f0dSMatthew G. Knepley 3799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 3809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 3819cbb8f0dSMatthew G. Knepley /* Change constraint numbering from field component to local dof number */ 3829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, p, f, &find)); 3839cbb8f0dSMatthew G. Knepley for (d = 0; d < fcdof; ++d) indices[numConst + d] = find[d] + foff; 3849cbb8f0dSMatthew G. Knepley numConst += fcdof; 3859cbb8f0dSMatthew G. Knepley foff += fdof; 3869cbb8f0dSMatthew G. Knepley } 3879566063dSJacob Faibussowitsch if (cdof != numConst) PetscCall(PetscSectionSetConstraintDof(section, p, numConst)); 3889cbb8f0dSMatthew G. Knepley } else { 3899cbb8f0dSMatthew G. Knepley for (d = 0; d < cdof; ++d) indices[d] = d; 3909cbb8f0dSMatthew G. Knepley } 3919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintIndices(section, p, indices)); 3929cbb8f0dSMatthew G. Knepley } 3939cbb8f0dSMatthew G. Knepley } 3949566063dSJacob Faibussowitsch PetscCall(PetscFree(indices)); 3953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3969cbb8f0dSMatthew G. Knepley } 3979cbb8f0dSMatthew G. Knepley 3989cbb8f0dSMatthew G. Knepley /*@C 399a1cb98faSBarry Smith DMPlexCreateSection - Create a `PetscSection` based upon the dof layout specification provided. 4009cbb8f0dSMatthew G. Knepley 4019cbb8f0dSMatthew G. Knepley Not Collective 4029cbb8f0dSMatthew G. Knepley 4039cbb8f0dSMatthew G. Knepley Input Parameters: 404a1cb98faSBarry Smith + dm - The `DMPLEX` object 40592cfd99aSMartin Diehl . label - The label indicating the mesh support of each field, or NULL for the whole mesh 4069cbb8f0dSMatthew G. Knepley . numComp - An array of size numFields that holds the number of components for each field 4079cbb8f0dSMatthew G. Knepley . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 4089cbb8f0dSMatthew G. Knepley . numBC - The number of boundary conditions 409da81f932SPierre Jolivet . bcField - An array of size numBC giving the field number for each boundary condition 410a1cb98faSBarry Smith . bcComps - [Optional] An array of size numBC giving an `IS` holding the field components to which each boundary condition applies 411a1cb98faSBarry Smith . bcPoints - An array of size numBC giving an `IS` holding the `DMPLEX` points to which each boundary condition applies 4129cbb8f0dSMatthew G. Knepley - perm - Optional permutation of the chart, or NULL 4139cbb8f0dSMatthew G. Knepley 4149cbb8f0dSMatthew G. Knepley Output Parameter: 415a1cb98faSBarry Smith . section - The `PetscSection` object 416a1cb98faSBarry Smith 417a1cb98faSBarry Smith Level: developer 4189cbb8f0dSMatthew G. Knepley 4199cbb8f0dSMatthew G. Knepley Notes: 4209cbb8f0dSMatthew G. Knepley numDof[f*(dim+1)+d] gives the number of dof for field f on points of dimension d. For instance, numDof[1] is the 4219cbb8f0dSMatthew G. Knepley number of dof for field 0 on each edge. 4229cbb8f0dSMatthew G. Knepley 423a1cb98faSBarry Smith The chart permutation is the same one set using `PetscSectionSetPermutation()` 4249cbb8f0dSMatthew G. Knepley 425a1cb98faSBarry Smith Developer Note: 426a1cb98faSBarry Smith This is used by `DMCreateLocalSection()`? 4279cbb8f0dSMatthew G. Knepley 428*1cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `PetscSectionCreate()`, `PetscSectionSetPermutation()` 4299cbb8f0dSMatthew G. Knepley @*/ 430d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSection(DM dm, DMLabel label[], const PetscInt numComp[], const PetscInt numDof[], PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], IS perm, PetscSection *section) 431d71ae5a4SJacob Faibussowitsch { 4329cbb8f0dSMatthew G. Knepley PetscSection aSec; 4339cbb8f0dSMatthew G. Knepley 4349cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 4359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionFields(dm, numComp, section)); 4369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionDof(dm, label, numDof, *section)); 4379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section)); 4389566063dSJacob Faibussowitsch if (perm) PetscCall(PetscSectionSetPermutation(*section, perm)); 4399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFromOptions(*section)); 4409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*section)); 4419566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, NULL)); 4429cbb8f0dSMatthew G. Knepley if (numBC || aSec) { 4439566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section)); 4449566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionBCIndices(dm, *section)); 4459cbb8f0dSMatthew G. Knepley } 4469566063dSJacob Faibussowitsch PetscCall(PetscSectionViewFromOptions(*section, NULL, "-section_view")); 4473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4489cbb8f0dSMatthew G. Knepley } 4499cbb8f0dSMatthew G. Knepley 450d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalSection_Plex(DM dm) 451d71ae5a4SJacob Faibussowitsch { 4529cbb8f0dSMatthew G. Knepley PetscSection section; 453baef929fSMatthew G. Knepley DMLabel *labels; 4549cbb8f0dSMatthew G. Knepley IS *bcPoints, *bcComps; 4559cbb8f0dSMatthew G. Knepley PetscBool *isFE; 4569cbb8f0dSMatthew G. Knepley PetscInt *bcFields, *numComp, *numDof; 4579310035eSMatthew G. Knepley PetscInt depth, dim, numBC = 0, Nf, Nds, s, bc = 0, f; 4589cbb8f0dSMatthew G. Knepley PetscInt cStart, cEnd, cEndInterior; 4599cbb8f0dSMatthew G. Knepley 4609cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 4619566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 4629566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 4639566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 4649cbb8f0dSMatthew G. Knepley /* FE and FV boundary conditions are handled slightly differently */ 4659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nf, &isFE)); 466baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 4679cbb8f0dSMatthew G. Knepley PetscObject obj; 4689cbb8f0dSMatthew G. Knepley PetscClassId id; 4699cbb8f0dSMatthew G. Knepley 4709566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, &obj)); 4719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 4729371c9d4SSatish Balay if (id == PETSCFE_CLASSID) { 4739371c9d4SSatish Balay isFE[f] = PETSC_TRUE; 4749371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) { 4759371c9d4SSatish Balay isFE[f] = PETSC_FALSE; 4769371c9d4SSatish Balay } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f); 4779cbb8f0dSMatthew G. Knepley } 4789cbb8f0dSMatthew G. Knepley /* Allocate boundary point storage for FEM boundaries */ 4799566063dSJacob Faibussowitsch PetscCall(DMGetNumDS(dm, &Nds)); 4809310035eSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 4819310035eSMatthew G. Knepley PetscDS dsBC; 4829310035eSMatthew G. Knepley PetscInt numBd, bd; 4839310035eSMatthew G. Knepley 48407218a29SMatthew G. Knepley PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL)); 4859566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumBoundary(dsBC, &numBd)); 48608401ef6SPierre Jolivet PetscCheck(Nf || !numBd, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "number of fields is zero and number of boundary conditions is nonzero (this should never happen)"); 4879cbb8f0dSMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 4889cbb8f0dSMatthew G. Knepley PetscInt field; 4899cbb8f0dSMatthew G. Knepley DMBoundaryConditionType type; 4909cbb8f0dSMatthew G. Knepley DMLabel label; 4919cbb8f0dSMatthew G. Knepley 4929566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, &type, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL)); 4939cbb8f0dSMatthew G. Knepley if (label && isFE[field] && (type & DM_BC_ESSENTIAL)) ++numBC; 4949cbb8f0dSMatthew G. Knepley } 4959310035eSMatthew G. Knepley } 4969cbb8f0dSMatthew G. Knepley /* Add ghost cell boundaries for FVM */ 4979566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(dm, &cEndInterior, NULL)); 4989371c9d4SSatish Balay for (f = 0; f < Nf; ++f) 4999371c9d4SSatish Balay if (!isFE[f] && cEndInterior >= 0) ++numBC; 5009566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numBC, &bcFields, numBC, &bcPoints, numBC, &bcComps)); 5019cbb8f0dSMatthew G. Knepley /* Constrain ghost cells for FV */ 502baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5039cbb8f0dSMatthew G. Knepley PetscInt *newidx, c; 5049cbb8f0dSMatthew G. Knepley 5059cbb8f0dSMatthew G. Knepley if (isFE[f] || cEndInterior < 0) continue; 5069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cEndInterior, &newidx)); 5079cbb8f0dSMatthew G. Knepley for (c = cEndInterior; c < cEnd; ++c) newidx[c - cEndInterior] = c; 5089cbb8f0dSMatthew G. Knepley bcFields[bc] = f; 5099566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cEnd - cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++])); 5109cbb8f0dSMatthew G. Knepley } 511f985c9a8SMatthew G. Knepley /* Complete labels for boundary conditions */ 512799db056SMatthew G. Knepley PetscCall(DMCompleteBCLabels_Internal(dm)); 5139cbb8f0dSMatthew G. Knepley /* Handle FEM Dirichlet boundaries */ 5149566063dSJacob Faibussowitsch PetscCall(DMGetNumDS(dm, &Nds)); 5159310035eSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 5169310035eSMatthew G. Knepley PetscDS dsBC; 5179310035eSMatthew G. Knepley PetscInt numBd, bd; 5189310035eSMatthew G. Knepley 51907218a29SMatthew G. Knepley PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL)); 5209566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumBoundary(dsBC, &numBd)); 5219cbb8f0dSMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 5229cbb8f0dSMatthew G. Knepley DMLabel label; 5239cbb8f0dSMatthew G. Knepley const PetscInt *comps; 5249cbb8f0dSMatthew G. Knepley const PetscInt *values; 5259310035eSMatthew G. Knepley PetscInt bd2, field, numComps, numValues; 5269cbb8f0dSMatthew G. Knepley DMBoundaryConditionType type; 5279310035eSMatthew G. Knepley PetscBool duplicate = PETSC_FALSE; 5289cbb8f0dSMatthew G. Knepley 5299566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, &type, NULL, &label, &numValues, &values, &field, &numComps, &comps, NULL, NULL, NULL)); 5309cbb8f0dSMatthew G. Knepley if (!isFE[field] || !label) continue; 5319310035eSMatthew G. Knepley /* Only want to modify label once */ 5329310035eSMatthew G. Knepley for (bd2 = 0; bd2 < bd; ++bd2) { 53345480ffeSMatthew G. Knepley DMLabel l; 53445480ffeSMatthew G. Knepley 5359566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(dsBC, bd2, NULL, NULL, NULL, &l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); 53645480ffeSMatthew G. Knepley duplicate = l == label ? PETSC_TRUE : PETSC_FALSE; 5379310035eSMatthew G. Knepley if (duplicate) break; 5389310035eSMatthew G. Knepley } 5399cbb8f0dSMatthew G. Knepley /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 5409cbb8f0dSMatthew G. Knepley if (type & DM_BC_ESSENTIAL) { 5419cbb8f0dSMatthew G. Knepley PetscInt *newidx; 5429cbb8f0dSMatthew G. Knepley PetscInt n, newn = 0, p, v; 5439cbb8f0dSMatthew G. Knepley 5449cbb8f0dSMatthew G. Knepley bcFields[bc] = field; 54540cbb1a0SMatthew G. Knepley if (numComps) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numComps, comps, PETSC_COPY_VALUES, &bcComps[bc])); 5469cbb8f0dSMatthew G. Knepley for (v = 0; v < numValues; ++v) { 5479cbb8f0dSMatthew G. Knepley IS tmp; 5489cbb8f0dSMatthew G. Knepley const PetscInt *idx; 5499cbb8f0dSMatthew G. Knepley 5509566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &tmp)); 5519cbb8f0dSMatthew G. Knepley if (!tmp) continue; 5529566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &n)); 5539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(tmp, &idx)); 5549cbb8f0dSMatthew G. Knepley if (isFE[field]) { 5559371c9d4SSatish Balay for (p = 0; p < n; ++p) 5569371c9d4SSatish Balay if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 5579cbb8f0dSMatthew G. Knepley } else { 5589371c9d4SSatish Balay for (p = 0; p < n; ++p) 5599371c9d4SSatish Balay if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 5609cbb8f0dSMatthew G. Knepley } 5619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(tmp, &idx)); 5629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 5639cbb8f0dSMatthew G. Knepley } 5649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newidx)); 5659cbb8f0dSMatthew G. Knepley newn = 0; 5669cbb8f0dSMatthew G. Knepley for (v = 0; v < numValues; ++v) { 5679cbb8f0dSMatthew G. Knepley IS tmp; 5689cbb8f0dSMatthew G. Knepley const PetscInt *idx; 5699cbb8f0dSMatthew G. Knepley 5709566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &tmp)); 5719cbb8f0dSMatthew G. Knepley if (!tmp) continue; 5729566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &n)); 5739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(tmp, &idx)); 5749cbb8f0dSMatthew G. Knepley if (isFE[field]) { 5759371c9d4SSatish Balay for (p = 0; p < n; ++p) 5769371c9d4SSatish Balay if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 5779cbb8f0dSMatthew G. Knepley } else { 5789371c9d4SSatish Balay for (p = 0; p < n; ++p) 5799371c9d4SSatish Balay if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 5809cbb8f0dSMatthew G. Knepley } 5819566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(tmp, &idx)); 5829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 5839cbb8f0dSMatthew G. Knepley } 5849566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++])); 5859310035eSMatthew G. Knepley } 5869cbb8f0dSMatthew G. Knepley } 5879cbb8f0dSMatthew G. Knepley } 5889cbb8f0dSMatthew G. Knepley /* Handle discretization */ 5899566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(Nf, &labels, Nf, &numComp, Nf * (dim + 1), &numDof)); 590baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 59144a7f3ddSMatthew G. Knepley labels[f] = dm->fields[f].label; 5929cbb8f0dSMatthew G. Knepley if (isFE[f]) { 59344a7f3ddSMatthew G. Knepley PetscFE fe = (PetscFE)dm->fields[f].disc; 5949cbb8f0dSMatthew G. Knepley const PetscInt *numFieldDof; 595a3254110SMatthew Knepley PetscInt fedim, d; 5969cbb8f0dSMatthew G. Knepley 5979566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &numComp[f])); 5989566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumDof(fe, &numFieldDof)); 5999566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(fe, &fedim)); 600a3254110SMatthew Knepley for (d = 0; d < PetscMin(dim, fedim) + 1; ++d) numDof[f * (dim + 1) + d] = numFieldDof[d]; 6019cbb8f0dSMatthew G. Knepley } else { 60244a7f3ddSMatthew G. Knepley PetscFV fv = (PetscFV)dm->fields[f].disc; 6039cbb8f0dSMatthew G. Knepley 6049566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numComp[f])); 6059cbb8f0dSMatthew G. Knepley numDof[f * (dim + 1) + dim] = numComp[f]; 6069cbb8f0dSMatthew G. Knepley } 6079cbb8f0dSMatthew G. Knepley } 6089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 609baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 6109cbb8f0dSMatthew G. Knepley PetscInt d; 611ad540459SPierre Jolivet for (d = 1; d < dim; ++d) PetscCheck(numDof[f * (dim + 1) + d] <= 0 || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated when unknowns are specified on edges or faces."); 6129cbb8f0dSMatthew G. Knepley } 6139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSection(dm, labels, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion)); 614baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 6159cbb8f0dSMatthew G. Knepley PetscFE fe; 6169cbb8f0dSMatthew G. Knepley const char *name; 6179cbb8f0dSMatthew G. Knepley 6189566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe)); 619cdfe53dfSMatthew G. Knepley if (!((PetscObject)fe)->name) continue; 6209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)fe, &name)); 6219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldName(section, f, name)); 6229cbb8f0dSMatthew G. Knepley } 6239566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm, section)); 6249566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 6259371c9d4SSatish Balay for (bc = 0; bc < numBC; ++bc) { 6269371c9d4SSatish Balay PetscCall(ISDestroy(&bcPoints[bc])); 6279371c9d4SSatish Balay PetscCall(ISDestroy(&bcComps[bc])); 6289371c9d4SSatish Balay } 6299566063dSJacob Faibussowitsch PetscCall(PetscFree3(bcFields, bcPoints, bcComps)); 6309566063dSJacob Faibussowitsch PetscCall(PetscFree3(labels, numComp, numDof)); 6319566063dSJacob Faibussowitsch PetscCall(PetscFree(isFE)); 6323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6339cbb8f0dSMatthew G. Knepley } 634