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 */ 4baef929fSMatthew G. Knepley static PetscErrorCode DMPlexCreateSectionFields(DM dm, const PetscInt numComp[], PetscSection *section) 59cbb8f0dSMatthew G. Knepley { 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; 11*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 12*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm,&depthLabel)); 13*9566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 14*9566063dSJacob 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 19*9566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, &obj)); 20*9566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 219cbb8f0dSMatthew G. Knepley if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 229cbb8f0dSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 239cbb8f0dSMatthew G. Knepley } 24baef929fSMatthew G. Knepley 25*9566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), section)); 26baef929fSMatthew G. Knepley if (Nf > 0) { 27*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*section, Nf)); 289cbb8f0dSMatthew G. Knepley if (numComp) { 29baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 30*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*section, f, numComp[f])); 319cbb8f0dSMatthew G. Knepley if (isFE[f]) { 329cbb8f0dSMatthew G. Knepley PetscFE fe; 339cbb8f0dSMatthew G. Knepley PetscDualSpace dspace; 349cbb8f0dSMatthew G. Knepley const PetscInt ***perms; 359cbb8f0dSMatthew G. Knepley const PetscScalar ***flips; 369cbb8f0dSMatthew G. Knepley const PetscInt *numDof; 379cbb8f0dSMatthew G. Knepley 38*9566063dSJacob Faibussowitsch PetscCall(DMGetField(dm,f,NULL,(PetscObject *) &fe)); 39*9566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe,&dspace)); 40*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dspace,&perms,&flips)); 41*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dspace,&numDof)); 429cbb8f0dSMatthew G. Knepley if (perms || flips) { 439cbb8f0dSMatthew G. Knepley DM K; 444dff28b8SMatthew G. Knepley PetscInt sph, spdepth; 459cbb8f0dSMatthew G. Knepley PetscSectionSym sym; 469cbb8f0dSMatthew G. Knepley 47*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(dspace,&K)); 48*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(K, &spdepth)); 49*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)*section),depthLabel,&sym)); 504dff28b8SMatthew G. Knepley for (sph = 0; sph <= spdepth; sph++) { 519cbb8f0dSMatthew G. Knepley PetscDualSpace hspace; 529cbb8f0dSMatthew G. Knepley PetscInt kStart, kEnd; 534dff28b8SMatthew G. Knepley PetscInt kConeSize, h = sph + (depth - spdepth); 549cbb8f0dSMatthew G. Knepley const PetscInt **perms0 = NULL; 559cbb8f0dSMatthew G. Knepley const PetscScalar **flips0 = NULL; 569cbb8f0dSMatthew G. Knepley 57*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dspace, sph, &hspace)); 58*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, h, &kStart, &kEnd)); 599cbb8f0dSMatthew G. Knepley if (!hspace) continue; 60*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(hspace,&perms,&flips)); 619cbb8f0dSMatthew G. Knepley if (perms) perms0 = perms[0]; 629cbb8f0dSMatthew G. Knepley if (flips) flips0 = flips[0]; 639cbb8f0dSMatthew G. Knepley if (!(perms0 || flips0)) continue; 64b5a892a1SMatthew G. Knepley { 65b5a892a1SMatthew G. Knepley DMPolytopeType ct; 66b5a892a1SMatthew G. Knepley /* The number of arrangements is no longer based on the number of faces */ 67*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, kStart, &ct)); 68b5a892a1SMatthew G. Knepley kConeSize = DMPolytopeTypeGetNumArrangments(ct) / 2; 69b5a892a1SMatthew G. Knepley } 70*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSymLabelSetStratum(sym,depth - h,numDof[depth - h],-kConeSize,kConeSize,PETSC_USE_POINTER,perms0 ? &perms0[-kConeSize] : NULL,flips0 ? &flips0[-kConeSize] : NULL)); 719cbb8f0dSMatthew G. Knepley } 72*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldSym(*section,f,sym)); 73*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSymDestroy(&sym)); 749cbb8f0dSMatthew G. Knepley } 759cbb8f0dSMatthew G. Knepley } 769cbb8f0dSMatthew G. Knepley } 779cbb8f0dSMatthew G. Knepley } 789cbb8f0dSMatthew G. Knepley } 79*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 80*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*section, pStart, pEnd)); 81*9566063dSJacob Faibussowitsch PetscCall(PetscFree(isFE)); 82baef929fSMatthew G. Knepley PetscFunctionReturn(0); 83baef929fSMatthew G. Knepley } 84baef929fSMatthew G. Knepley 85baef929fSMatthew G. Knepley /* Set the number of dof on each point and separate by fields */ 86baef929fSMatthew G. Knepley static PetscErrorCode DMPlexCreateSectionDof(DM dm, DMLabel label[],const PetscInt numDof[], PetscSection section) 87baef929fSMatthew G. Knepley { 88baef929fSMatthew G. Knepley DMLabel depthLabel; 89412e9a14SMatthew G. Knepley DMPolytopeType ct; 90baef929fSMatthew G. Knepley PetscInt depth, cellHeight, pStart = 0, pEnd = 0; 91a55f9a55SMatthew G. Knepley PetscInt Nf, f, Nds, n, dim, d, dep, p; 925fedec97SMatthew G. Knepley PetscBool *isFE, hasCohesive = PETSC_FALSE; 93baef929fSMatthew G. Knepley 94baef929fSMatthew G. Knepley PetscFunctionBegin; 95*9566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 96*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 97*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm,&depthLabel)); 98*9566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 99*9566063dSJacob Faibussowitsch PetscCall(DMGetNumDS(dm, &Nds)); 100a55f9a55SMatthew G. Knepley for (n = 0; n < Nds; ++n) { 101a55f9a55SMatthew G. Knepley PetscDS ds; 1025fedec97SMatthew G. Knepley PetscBool isCohesive; 103a55f9a55SMatthew G. Knepley 104*9566063dSJacob Faibussowitsch PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds)); 105*9566063dSJacob Faibussowitsch PetscCall(PetscDSIsCohesive(ds, &isCohesive)); 1065fedec97SMatthew G. Knepley if (isCohesive) {hasCohesive = PETSC_TRUE; break;} 107a55f9a55SMatthew G. Knepley } 108*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nf, &isFE)); 109baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 110baef929fSMatthew G. Knepley PetscObject obj; 111baef929fSMatthew G. Knepley PetscClassId id; 112baef929fSMatthew G. Knepley 113*9566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, &obj)); 114*9566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 1151274e1a1SLawrence Mitchell /* User is allowed to put a "placeholder" field in (c.f. DMCreateDS) */ 1161274e1a1SLawrence Mitchell isFE[f] = id == PETSCFE_CLASSID ? PETSC_TRUE : PETSC_FALSE; 117baef929fSMatthew G. Knepley } 118baef929fSMatthew G. Knepley 119*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 120baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 121e0b68406SMatthew Knepley PetscBool avoidTensor; 122e0b68406SMatthew Knepley 123*9566063dSJacob Faibussowitsch PetscCall(DMGetFieldAvoidTensor(dm, f, &avoidTensor)); 1245fedec97SMatthew G. Knepley avoidTensor = (avoidTensor || hasCohesive) ? PETSC_TRUE : PETSC_FALSE; 125baef929fSMatthew G. Knepley if (label && label[f]) { 126baef929fSMatthew G. Knepley IS pointIS; 127baef929fSMatthew G. Knepley const PetscInt *points; 128baef929fSMatthew G. Knepley PetscInt n; 129baef929fSMatthew G. Knepley 130*9566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label[f], 1, &pointIS)); 131baef929fSMatthew G. Knepley if (!pointIS) continue; 132*9566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &n)); 133*9566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 134baef929fSMatthew G. Knepley for (p = 0; p < n; ++p) { 135baef929fSMatthew G. Knepley const PetscInt point = points[p]; 136baef929fSMatthew G. Knepley PetscInt dof, d; 137baef929fSMatthew G. Knepley 138*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, point, &ct)); 139*9566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &d)); 140412e9a14SMatthew G. Knepley /* If this is a tensor prism point, use dof for one dimension lower */ 141412e9a14SMatthew G. Knepley switch (ct) { 142412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 143412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 144412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 145412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 1465fedec97SMatthew G. Knepley if (hasCohesive) {--d;} break; 147412e9a14SMatthew G. Knepley default: break; 148412e9a14SMatthew G. Knepley } 149baef929fSMatthew G. Knepley dof = d < 0 ? 0 : numDof[f*(dim+1)+d]; 150*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(section, point, f, dof)); 151*9566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, point, dof)); 152baef929fSMatthew G. Knepley } 153*9566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 154*9566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 155baef929fSMatthew G. Knepley } else { 1569cbb8f0dSMatthew G. Knepley for (dep = 0; dep <= depth - cellHeight; ++dep) { 1573fd2e703SMatthew G. Knepley /* Cases: dim > depth (cell-vertex mesh), dim == depth (fully interpolated), dim < depth (interpolated submesh) */ 1583fd2e703SMatthew G. Knepley d = dim <= depth ? dep : (!dep ? 0 : dim); 159*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd)); 1609cbb8f0dSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 161baef929fSMatthew G. Knepley const PetscInt dof = numDof[f*(dim+1)+d]; 1629cbb8f0dSMatthew G. Knepley 163*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 164412e9a14SMatthew G. Knepley switch (ct) { 165412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 166412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 167412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 168412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 169e0b68406SMatthew Knepley if (avoidTensor && isFE[f]) continue; 170412e9a14SMatthew G. Knepley default: break; 171412e9a14SMatthew G. Knepley } 172*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(section, p, f, dof)); 173*9566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, dof)); 1749cbb8f0dSMatthew G. Knepley } 175baef929fSMatthew G. Knepley } 1769cbb8f0dSMatthew G. Knepley } 1779cbb8f0dSMatthew G. Knepley } 178*9566063dSJacob Faibussowitsch PetscCall(PetscFree(isFE)); 1799cbb8f0dSMatthew G. Knepley PetscFunctionReturn(0); 1809cbb8f0dSMatthew G. Knepley } 1819cbb8f0dSMatthew G. Knepley 1829cbb8f0dSMatthew G. Knepley /* Set the number of dof on each point and separate by fields 1839cbb8f0dSMatthew G. Knepley If bcComps is NULL or the IS is NULL, constrain every dof on the point 1849cbb8f0dSMatthew G. Knepley */ 1859cbb8f0dSMatthew G. Knepley static PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 1869cbb8f0dSMatthew G. Knepley { 187baef929fSMatthew G. Knepley PetscInt Nf; 1889cbb8f0dSMatthew G. Knepley PetscInt bc; 1899cbb8f0dSMatthew G. Knepley PetscSection aSec; 1909cbb8f0dSMatthew G. Knepley 1919cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 192*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 1939cbb8f0dSMatthew G. Knepley for (bc = 0; bc < numBC; ++bc) { 1949cbb8f0dSMatthew G. Knepley PetscInt field = 0; 1959cbb8f0dSMatthew G. Knepley const PetscInt *comp; 1969cbb8f0dSMatthew G. Knepley const PetscInt *idx; 197ce093827SMatthew G. Knepley PetscInt Nc = 0, cNc = -1, n, i; 1989cbb8f0dSMatthew G. Knepley 199ce093827SMatthew G. Knepley if (Nf) { 200ce093827SMatthew G. Knepley field = bcField[bc]; 201*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, &Nc)); 202ce093827SMatthew G. Knepley } 203*9566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISGetLocalSize(bcComps[bc], &cNc)); 204*9566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISGetIndices(bcComps[bc], &comp)); 205*9566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bcPoints[bc], &n)); 206*9566063dSJacob Faibussowitsch PetscCall(ISGetIndices(bcPoints[bc], &idx)); 2079cbb8f0dSMatthew G. Knepley for (i = 0; i < n; ++i) { 2089cbb8f0dSMatthew G. Knepley const PetscInt p = idx[i]; 2099cbb8f0dSMatthew G. Knepley PetscInt numConst; 2109cbb8f0dSMatthew G. Knepley 211baef929fSMatthew G. Knepley if (Nf) { 212*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, field, &numConst)); 2139cbb8f0dSMatthew G. Knepley } else { 214*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numConst)); 2159cbb8f0dSMatthew G. Knepley } 216ce093827SMatthew G. Knepley /* If Nc <= 0, constrain every dof on the point */ 217ce093827SMatthew G. Knepley if (cNc > 0) { 218ce093827SMatthew G. Knepley /* We assume that a point may have multiple "nodes", which are collections of Nc dofs, 219ce093827SMatthew G. Knepley and that those dofs are numbered n*Nc+c */ 220ce093827SMatthew G. Knepley if (Nf) { 2212c71b3e2SJacob Faibussowitsch PetscCheckFalse(numConst % Nc,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D has %D dof which is not divisible by %D field components", p, numConst, Nc); 222ce093827SMatthew G. Knepley numConst = (numConst/Nc) * cNc; 223ce093827SMatthew G. Knepley } else { 224ce093827SMatthew G. Knepley numConst = PetscMin(numConst, cNc); 225ce093827SMatthew G. Knepley } 226ce093827SMatthew G. Knepley } 227*9566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionAddFieldConstraintDof(section, p, field, numConst)); 228*9566063dSJacob Faibussowitsch PetscCall(PetscSectionAddConstraintDof(section, p, numConst)); 2299cbb8f0dSMatthew G. Knepley } 230*9566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(bcPoints[bc], &idx)); 231*9566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISRestoreIndices(bcComps[bc], &comp)); 2329cbb8f0dSMatthew G. Knepley } 233*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, NULL)); 2349cbb8f0dSMatthew G. Knepley if (aSec) { 2359cbb8f0dSMatthew G. Knepley PetscInt aStart, aEnd, a; 2369cbb8f0dSMatthew G. Knepley 237*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 2389cbb8f0dSMatthew G. Knepley for (a = aStart; a < aEnd; a++) { 2399cbb8f0dSMatthew G. Knepley PetscInt dof, f; 2409cbb8f0dSMatthew G. Knepley 241*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, a, &dof)); 2429cbb8f0dSMatthew G. Knepley if (dof) { 2439cbb8f0dSMatthew G. Knepley /* if there are point-to-point constraints, then all dofs are constrained */ 244*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &dof)); 245*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, a, dof)); 246baef929fSMatthew G. Knepley for (f = 0; f < Nf; f++) { 247*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &dof)); 248*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldConstraintDof(section, a, f, dof)); 2499cbb8f0dSMatthew G. Knepley } 2509cbb8f0dSMatthew G. Knepley } 2519cbb8f0dSMatthew G. Knepley } 2529cbb8f0dSMatthew G. Knepley } 2539cbb8f0dSMatthew G. Knepley PetscFunctionReturn(0); 2549cbb8f0dSMatthew G. Knepley } 2559cbb8f0dSMatthew G. Knepley 2569cbb8f0dSMatthew G. Knepley /* Set the constrained field indices on each point 2579cbb8f0dSMatthew G. Knepley If bcComps is NULL or the IS is NULL, constrain every dof on the point 2589cbb8f0dSMatthew G. Knepley */ 2599cbb8f0dSMatthew G. Knepley static PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2609cbb8f0dSMatthew G. Knepley { 2619cbb8f0dSMatthew G. Knepley PetscSection aSec; 2629cbb8f0dSMatthew G. Knepley PetscInt *indices; 263baef929fSMatthew G. Knepley PetscInt Nf, cdof, maxDof = 0, pStart, pEnd, p, bc, f, d; 2649cbb8f0dSMatthew G. Knepley 2659cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 266*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 267baef929fSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 2689cbb8f0dSMatthew G. Knepley /* Initialize all field indices to -1 */ 269*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 270*9566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) {PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); maxDof = PetscMax(maxDof, cdof);} 271*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &indices)); 2729cbb8f0dSMatthew G. Knepley for (d = 0; d < maxDof; ++d) indices[d] = -1; 273*9566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) for (f = 0; f < Nf; ++f) PetscCall(PetscSectionSetFieldConstraintIndices(section, p, f, indices)); 2749cbb8f0dSMatthew G. Knepley /* Handle BC constraints */ 2759cbb8f0dSMatthew G. Knepley for (bc = 0; bc < numBC; ++bc) { 2769cbb8f0dSMatthew G. Knepley const PetscInt field = bcField[bc]; 2779cbb8f0dSMatthew G. Knepley const PetscInt *comp, *idx; 278ce093827SMatthew G. Knepley PetscInt Nc, cNc = -1, n, i; 2799cbb8f0dSMatthew G. Knepley 280*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, &Nc)); 281*9566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISGetLocalSize(bcComps[bc], &cNc)); 282*9566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISGetIndices(bcComps[bc], &comp)); 283*9566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bcPoints[bc], &n)); 284*9566063dSJacob Faibussowitsch PetscCall(ISGetIndices(bcPoints[bc], &idx)); 2859cbb8f0dSMatthew G. Knepley for (i = 0; i < n; ++i) { 2869cbb8f0dSMatthew G. Knepley const PetscInt p = idx[i]; 2879cbb8f0dSMatthew G. Knepley const PetscInt *find; 288ce093827SMatthew G. Knepley PetscInt fdof, fcdof, c, j; 2899cbb8f0dSMatthew G. Knepley 290*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, field, &fdof)); 2919cbb8f0dSMatthew G. Knepley if (!fdof) continue; 292ce093827SMatthew G. Knepley if (cNc < 0) { 2939cbb8f0dSMatthew G. Knepley for (d = 0; d < fdof; ++d) indices[d] = d; 2949cbb8f0dSMatthew G. Knepley fcdof = fdof; 2959cbb8f0dSMatthew G. Knepley } else { 296ce093827SMatthew G. Knepley /* We assume that a point may have multiple "nodes", which are collections of Nc dofs, 297ce093827SMatthew G. Knepley and that those dofs are numbered n*Nc+c */ 298*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, field, &fcdof)); 299*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, p, field, &find)); 300ce093827SMatthew G. Knepley /* Get indices constrained by previous bcs */ 3019cbb8f0dSMatthew G. Knepley for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 302ce093827SMatthew G. Knepley for (j = 0; j < fdof/Nc; ++j) for (c = 0; c < cNc; ++c) indices[d++] = j*Nc + comp[c]; 303*9566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&d, indices)); 3049cbb8f0dSMatthew G. Knepley for (c = d; c < fcdof; ++c) indices[c] = -1; 3059cbb8f0dSMatthew G. Knepley fcdof = d; 3069cbb8f0dSMatthew G. Knepley } 307*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldConstraintDof(section, p, field, fcdof)); 308*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldConstraintIndices(section, p, field, indices)); 3099cbb8f0dSMatthew G. Knepley } 310*9566063dSJacob Faibussowitsch if (bcComps && bcComps[bc]) PetscCall(ISRestoreIndices(bcComps[bc], &comp)); 311*9566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(bcPoints[bc], &idx)); 3129cbb8f0dSMatthew G. Knepley } 3139cbb8f0dSMatthew G. Knepley /* Handle anchors */ 314*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, NULL)); 3159cbb8f0dSMatthew G. Knepley if (aSec) { 3169cbb8f0dSMatthew G. Knepley PetscInt aStart, aEnd, a; 3179cbb8f0dSMatthew G. Knepley 3189cbb8f0dSMatthew G. Knepley for (d = 0; d < maxDof; ++d) indices[d] = d; 319*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 3209cbb8f0dSMatthew G. Knepley for (a = aStart; a < aEnd; a++) { 3219cbb8f0dSMatthew G. Knepley PetscInt dof, f; 3229cbb8f0dSMatthew G. Knepley 323*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, a, &dof)); 3249cbb8f0dSMatthew G. Knepley if (dof) { 3259cbb8f0dSMatthew G. Knepley /* if there are point-to-point constraints, then all dofs are constrained */ 326baef929fSMatthew G. Knepley for (f = 0; f < Nf; f++) { 327*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldConstraintIndices(section, a, f, indices)); 3289cbb8f0dSMatthew G. Knepley } 3299cbb8f0dSMatthew G. Knepley } 3309cbb8f0dSMatthew G. Knepley } 3319cbb8f0dSMatthew G. Knepley } 332*9566063dSJacob Faibussowitsch PetscCall(PetscFree(indices)); 3339cbb8f0dSMatthew G. Knepley PetscFunctionReturn(0); 3349cbb8f0dSMatthew G. Knepley } 3359cbb8f0dSMatthew G. Knepley 3369cbb8f0dSMatthew G. Knepley /* Set the constrained indices on each point */ 3379cbb8f0dSMatthew G. Knepley static PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 3389cbb8f0dSMatthew G. Knepley { 3399cbb8f0dSMatthew G. Knepley PetscInt *indices; 340baef929fSMatthew G. Knepley PetscInt Nf, maxDof, pStart, pEnd, p, f, d; 3419cbb8f0dSMatthew G. Knepley 3429cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 343*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 344*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 345*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 346*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &indices)); 3479cbb8f0dSMatthew G. Knepley for (d = 0; d < maxDof; ++d) indices[d] = -1; 3489cbb8f0dSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3499cbb8f0dSMatthew G. Knepley PetscInt cdof, d; 3509cbb8f0dSMatthew G. Knepley 351*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 3529cbb8f0dSMatthew G. Knepley if (cdof) { 353baef929fSMatthew G. Knepley if (Nf) { 3549cbb8f0dSMatthew G. Knepley PetscInt numConst = 0, foff = 0; 3559cbb8f0dSMatthew G. Knepley 356baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 3579cbb8f0dSMatthew G. Knepley const PetscInt *find; 3589cbb8f0dSMatthew G. Knepley PetscInt fcdof, fdof; 3599cbb8f0dSMatthew G. Knepley 360*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 361*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 3629cbb8f0dSMatthew G. Knepley /* Change constraint numbering from field component to local dof number */ 363*9566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, p, f, &find)); 3649cbb8f0dSMatthew G. Knepley for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 3659cbb8f0dSMatthew G. Knepley numConst += fcdof; 3669cbb8f0dSMatthew G. Knepley foff += fdof; 3679cbb8f0dSMatthew G. Knepley } 368*9566063dSJacob Faibussowitsch if (cdof != numConst) PetscCall(PetscSectionSetConstraintDof(section, p, numConst)); 3699cbb8f0dSMatthew G. Knepley } else { 3709cbb8f0dSMatthew G. Knepley for (d = 0; d < cdof; ++d) indices[d] = d; 3719cbb8f0dSMatthew G. Knepley } 372*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintIndices(section, p, indices)); 3739cbb8f0dSMatthew G. Knepley } 3749cbb8f0dSMatthew G. Knepley } 375*9566063dSJacob Faibussowitsch PetscCall(PetscFree(indices)); 3769cbb8f0dSMatthew G. Knepley PetscFunctionReturn(0); 3779cbb8f0dSMatthew G. Knepley } 3789cbb8f0dSMatthew G. Knepley 3799cbb8f0dSMatthew G. Knepley /*@C 3809cbb8f0dSMatthew G. Knepley DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 3819cbb8f0dSMatthew G. Knepley 3829cbb8f0dSMatthew G. Knepley Not Collective 3839cbb8f0dSMatthew G. Knepley 3849cbb8f0dSMatthew G. Knepley Input Parameters: 3859cbb8f0dSMatthew G. Knepley + dm - The DMPlex object 38692cfd99aSMartin Diehl . label - The label indicating the mesh support of each field, or NULL for the whole mesh 3879cbb8f0dSMatthew G. Knepley . numComp - An array of size numFields that holds the number of components for each field 3889cbb8f0dSMatthew 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 3899cbb8f0dSMatthew G. Knepley . numBC - The number of boundary conditions 3909cbb8f0dSMatthew G. Knepley . bcField - An array of size numBC giving the field number for each boundry condition 3919cbb8f0dSMatthew G. Knepley . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 3929cbb8f0dSMatthew G. Knepley . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 3939cbb8f0dSMatthew G. Knepley - perm - Optional permutation of the chart, or NULL 3949cbb8f0dSMatthew G. Knepley 3959cbb8f0dSMatthew G. Knepley Output Parameter: 3969cbb8f0dSMatthew G. Knepley . section - The PetscSection object 3979cbb8f0dSMatthew G. Knepley 3989cbb8f0dSMatthew G. Knepley Notes: 3999cbb8f0dSMatthew 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 4009cbb8f0dSMatthew G. Knepley number of dof for field 0 on each edge. 4019cbb8f0dSMatthew G. Knepley 4029cbb8f0dSMatthew G. Knepley The chart permutation is the same one set using PetscSectionSetPermutation() 4039cbb8f0dSMatthew G. Knepley 4049cbb8f0dSMatthew G. Knepley Level: developer 4059cbb8f0dSMatthew G. Knepley 4061bb6d2a8SBarry Smith TODO: How is this related to DMCreateLocalSection() 4071bb6d2a8SBarry Smith 4089cbb8f0dSMatthew G. Knepley .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 4099cbb8f0dSMatthew G. Knepley @*/ 410baef929fSMatthew G. Knepley 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) 4119cbb8f0dSMatthew G. Knepley { 4129cbb8f0dSMatthew G. Knepley PetscSection aSec; 4139cbb8f0dSMatthew G. Knepley 4149cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 415*9566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionFields(dm, numComp, section)); 416*9566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionDof(dm, label, numDof, *section)); 417*9566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section)); 418*9566063dSJacob Faibussowitsch if (perm) PetscCall(PetscSectionSetPermutation(*section, perm)); 419*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFromOptions(*section)); 420*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*section)); 421*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,NULL)); 4229cbb8f0dSMatthew G. Knepley if (numBC || aSec) { 423*9566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section)); 424*9566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSectionBCIndices(dm, *section)); 4259cbb8f0dSMatthew G. Knepley } 426*9566063dSJacob Faibussowitsch PetscCall(PetscSectionViewFromOptions(*section,NULL,"-section_view")); 4279cbb8f0dSMatthew G. Knepley PetscFunctionReturn(0); 4289cbb8f0dSMatthew G. Knepley } 4299cbb8f0dSMatthew G. Knepley 4301bb6d2a8SBarry Smith PetscErrorCode DMCreateLocalSection_Plex(DM dm) 4319cbb8f0dSMatthew G. Knepley { 4329cbb8f0dSMatthew G. Knepley PetscSection section; 433baef929fSMatthew G. Knepley DMLabel *labels; 4349cbb8f0dSMatthew G. Knepley IS *bcPoints, *bcComps; 4359cbb8f0dSMatthew G. Knepley PetscBool *isFE; 4369cbb8f0dSMatthew G. Knepley PetscInt *bcFields, *numComp, *numDof; 4379310035eSMatthew G. Knepley PetscInt depth, dim, numBC = 0, Nf, Nds, s, bc = 0, f; 4389cbb8f0dSMatthew G. Knepley PetscInt cStart, cEnd, cEndInterior; 4399cbb8f0dSMatthew G. Knepley 4409cbb8f0dSMatthew G. Knepley PetscFunctionBegin; 441*9566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 442*9566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 443*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 4449cbb8f0dSMatthew G. Knepley /* FE and FV boundary conditions are handled slightly differently */ 445*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nf, &isFE)); 446baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 4479cbb8f0dSMatthew G. Knepley PetscObject obj; 4489cbb8f0dSMatthew G. Knepley PetscClassId id; 4499cbb8f0dSMatthew G. Knepley 450*9566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, &obj)); 451*9566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 4529cbb8f0dSMatthew G. Knepley if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 4539cbb8f0dSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 45498921bdaSJacob Faibussowitsch else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f); 4559cbb8f0dSMatthew G. Knepley } 4569cbb8f0dSMatthew G. Knepley /* Allocate boundary point storage for FEM boundaries */ 457*9566063dSJacob Faibussowitsch PetscCall(DMGetNumDS(dm, &Nds)); 4589310035eSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 4599310035eSMatthew G. Knepley PetscDS dsBC; 4609310035eSMatthew G. Knepley PetscInt numBd, bd; 4619310035eSMatthew G. Knepley 462*9566063dSJacob Faibussowitsch PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC)); 463*9566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumBoundary(dsBC, &numBd)); 4642c71b3e2SJacob Faibussowitsch PetscCheckFalse(!Nf && numBd,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "number of fields is zero and number of boundary conditions is nonzero (this should never happen)"); 4659cbb8f0dSMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 4669cbb8f0dSMatthew G. Knepley PetscInt field; 4679cbb8f0dSMatthew G. Knepley DMBoundaryConditionType type; 4689cbb8f0dSMatthew G. Knepley DMLabel label; 4699cbb8f0dSMatthew G. Knepley 470*9566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, &type, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL)); 4719cbb8f0dSMatthew G. Knepley if (label && isFE[field] && (type & DM_BC_ESSENTIAL)) ++numBC; 4729cbb8f0dSMatthew G. Knepley } 4739310035eSMatthew G. Knepley } 4749cbb8f0dSMatthew G. Knepley /* Add ghost cell boundaries for FVM */ 475*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(dm, &cEndInterior, NULL)); 476baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 477*9566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numBC, &bcFields, numBC, &bcPoints, numBC, &bcComps)); 4789cbb8f0dSMatthew G. Knepley /* Constrain ghost cells for FV */ 479baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 4809cbb8f0dSMatthew G. Knepley PetscInt *newidx, c; 4819cbb8f0dSMatthew G. Knepley 4829cbb8f0dSMatthew G. Knepley if (isFE[f] || cEndInterior < 0) continue; 483*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd-cEndInterior,&newidx)); 4849cbb8f0dSMatthew G. Knepley for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 4859cbb8f0dSMatthew G. Knepley bcFields[bc] = f; 486*9566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++])); 4879cbb8f0dSMatthew G. Knepley } 4889cbb8f0dSMatthew G. Knepley /* Handle FEM Dirichlet boundaries */ 489*9566063dSJacob Faibussowitsch PetscCall(DMGetNumDS(dm, &Nds)); 4909310035eSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 4919310035eSMatthew G. Knepley PetscDS dsBC; 4929310035eSMatthew G. Knepley PetscInt numBd, bd; 4939310035eSMatthew G. Knepley 494*9566063dSJacob Faibussowitsch PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC)); 495*9566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumBoundary(dsBC, &numBd)); 4969cbb8f0dSMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 4979cbb8f0dSMatthew G. Knepley DMLabel label; 4989cbb8f0dSMatthew G. Knepley const PetscInt *comps; 4999cbb8f0dSMatthew G. Knepley const PetscInt *values; 5009310035eSMatthew G. Knepley PetscInt bd2, field, numComps, numValues; 5019cbb8f0dSMatthew G. Knepley DMBoundaryConditionType type; 5029310035eSMatthew G. Knepley PetscBool duplicate = PETSC_FALSE; 5039cbb8f0dSMatthew G. Knepley 504*9566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, &type, NULL, &label, &numValues, &values, &field, &numComps, &comps, NULL, NULL, NULL)); 5059cbb8f0dSMatthew G. Knepley if (!isFE[field] || !label) continue; 5069310035eSMatthew G. Knepley /* Only want to modify label once */ 5079310035eSMatthew G. Knepley for (bd2 = 0; bd2 < bd; ++bd2) { 50845480ffeSMatthew G. Knepley DMLabel l; 50945480ffeSMatthew G. Knepley 510*9566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(dsBC, bd2, NULL, NULL, NULL, &l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); 51145480ffeSMatthew G. Knepley duplicate = l == label ? PETSC_TRUE : PETSC_FALSE; 5129310035eSMatthew G. Knepley if (duplicate) break; 5139310035eSMatthew G. Knepley } 5149310035eSMatthew G. Knepley if (!duplicate && (isFE[field])) { 5159310035eSMatthew G. Knepley /* don't complete cells, which are just present to give orientation to the boundary */ 516*9566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 5179310035eSMatthew G. Knepley } 5189cbb8f0dSMatthew G. Knepley /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 5199cbb8f0dSMatthew G. Knepley if (type & DM_BC_ESSENTIAL) { 5209cbb8f0dSMatthew G. Knepley PetscInt *newidx; 5219cbb8f0dSMatthew G. Knepley PetscInt n, newn = 0, p, v; 5229cbb8f0dSMatthew G. Knepley 5239cbb8f0dSMatthew G. Knepley bcFields[bc] = field; 524*9566063dSJacob Faibussowitsch if (numComps) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc])); 5259cbb8f0dSMatthew G. Knepley for (v = 0; v < numValues; ++v) { 5269cbb8f0dSMatthew G. Knepley IS tmp; 5279cbb8f0dSMatthew G. Knepley const PetscInt *idx; 5289cbb8f0dSMatthew G. Knepley 529*9566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &tmp)); 5309cbb8f0dSMatthew G. Knepley if (!tmp) continue; 531*9566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &n)); 532*9566063dSJacob Faibussowitsch PetscCall(ISGetIndices(tmp, &idx)); 5339cbb8f0dSMatthew G. Knepley if (isFE[field]) { 5349cbb8f0dSMatthew G. Knepley for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 5359cbb8f0dSMatthew G. Knepley } else { 5369cbb8f0dSMatthew G. Knepley for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 5379cbb8f0dSMatthew G. Knepley } 538*9566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(tmp, &idx)); 539*9566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 5409cbb8f0dSMatthew G. Knepley } 541*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newidx)); 5429cbb8f0dSMatthew G. Knepley newn = 0; 5439cbb8f0dSMatthew G. Knepley for (v = 0; v < numValues; ++v) { 5449cbb8f0dSMatthew G. Knepley IS tmp; 5459cbb8f0dSMatthew G. Knepley const PetscInt *idx; 5469cbb8f0dSMatthew G. Knepley 547*9566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &tmp)); 5489cbb8f0dSMatthew G. Knepley if (!tmp) continue; 549*9566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &n)); 550*9566063dSJacob Faibussowitsch PetscCall(ISGetIndices(tmp, &idx)); 5519cbb8f0dSMatthew G. Knepley if (isFE[field]) { 5529cbb8f0dSMatthew G. Knepley for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 5539cbb8f0dSMatthew G. Knepley } else { 5549cbb8f0dSMatthew G. Knepley for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 5559cbb8f0dSMatthew G. Knepley } 556*9566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(tmp, &idx)); 557*9566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 5589cbb8f0dSMatthew G. Knepley } 559*9566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++])); 5609310035eSMatthew G. Knepley } 5619cbb8f0dSMatthew G. Knepley } 5629cbb8f0dSMatthew G. Knepley } 5639cbb8f0dSMatthew G. Knepley /* Handle discretization */ 564*9566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(Nf,&labels,Nf,&numComp,Nf*(dim+1),&numDof)); 565baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 56644a7f3ddSMatthew G. Knepley labels[f] = dm->fields[f].label; 5679cbb8f0dSMatthew G. Knepley if (isFE[f]) { 56844a7f3ddSMatthew G. Knepley PetscFE fe = (PetscFE) dm->fields[f].disc; 5699cbb8f0dSMatthew G. Knepley const PetscInt *numFieldDof; 570a3254110SMatthew Knepley PetscInt fedim, d; 5719cbb8f0dSMatthew G. Knepley 572*9566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &numComp[f])); 573*9566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumDof(fe, &numFieldDof)); 574*9566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(fe, &fedim)); 575a3254110SMatthew Knepley for (d = 0; d < PetscMin(dim, fedim)+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 5769cbb8f0dSMatthew G. Knepley } else { 57744a7f3ddSMatthew G. Knepley PetscFV fv = (PetscFV) dm->fields[f].disc; 5789cbb8f0dSMatthew G. Knepley 579*9566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numComp[f])); 5809cbb8f0dSMatthew G. Knepley numDof[f*(dim+1)+dim] = numComp[f]; 5819cbb8f0dSMatthew G. Knepley } 5829cbb8f0dSMatthew G. Knepley } 583*9566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 584baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5859cbb8f0dSMatthew G. Knepley PetscInt d; 5869cbb8f0dSMatthew G. Knepley for (d = 1; d < dim; ++d) { 5872c71b3e2SJacob Faibussowitsch PetscCheckFalse((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."); 5889cbb8f0dSMatthew G. Knepley } 5899cbb8f0dSMatthew G. Knepley } 590*9566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSection(dm, labels, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion)); 591baef929fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5929cbb8f0dSMatthew G. Knepley PetscFE fe; 5939cbb8f0dSMatthew G. Knepley const char *name; 5949cbb8f0dSMatthew G. Knepley 595*9566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, (PetscObject *) &fe)); 596cdfe53dfSMatthew G. Knepley if (!((PetscObject) fe)->name) continue; 597*9566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) fe, &name)); 598*9566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldName(section, f, name)); 5999cbb8f0dSMatthew G. Knepley } 600*9566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm, section)); 601*9566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 602*9566063dSJacob Faibussowitsch for (bc = 0; bc < numBC; ++bc) {PetscCall(ISDestroy(&bcPoints[bc]));PetscCall(ISDestroy(&bcComps[bc]));} 603*9566063dSJacob Faibussowitsch PetscCall(PetscFree3(bcFields,bcPoints,bcComps)); 604*9566063dSJacob Faibussowitsch PetscCall(PetscFree3(labels,numComp,numDof)); 605*9566063dSJacob Faibussowitsch PetscCall(PetscFree(isFE)); 6069cbb8f0dSMatthew G. Knepley PetscFunctionReturn(0); 6079cbb8f0dSMatthew G. Knepley } 608