static char help[] = "Test FEM layout with constraints\n\n"; #include int main(int argc,char **argv) { DM dm,pdm; PetscSection section; const PetscInt field = 0; char ifilename[PETSC_MAX_PATH_LEN]; PetscInt sdim,s,pStart,pEnd,p,numVS,numPoints; PetscInt constraints[1]; IS setIS,pointIS; const PetscInt *setID,*pointID; PetscFunctionBeginUser; PetscCall(PetscInitialize(&argc,&argv,NULL,help)); PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"FEM Layout Options","ex98"); PetscCall(PetscOptionsString("-i","Filename to read","ex98",ifilename,ifilename,sizeof(ifilename),NULL)); PetscOptionsEnd(); PetscCall(DMPlexCreateFromFile(PETSC_COMM_WORLD,ifilename,NULL,PETSC_TRUE,&dm)); PetscCall(DMPlexDistributeSetDefault(dm,PETSC_FALSE)); PetscCall(DMSetFromOptions(dm)); PetscCall(DMPlexDistribute(dm,0,NULL,&pdm)); if (pdm) { PetscCall(DMDestroy(&dm)); dm = pdm; } PetscCall(DMViewFromOptions(dm,NULL,"-dm_view")); /* create a section */ PetscCall(DMGetDimension(dm,&sdim)); PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) dm),§ion)); PetscCall(PetscSectionSetNumFields(section,1)); PetscCall(PetscSectionSetFieldName(section,field,"U")); PetscCall(PetscSectionSetFieldComponents(section,field,sdim)); PetscCall(DMPlexGetChart(dm,&pStart,&pEnd)); PetscCall(PetscSectionSetChart(section,pStart,pEnd)); /* initialize the section storage for a P1 field */ PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd)); for (p = pStart; p < pEnd; ++p) { PetscCall(PetscSectionSetDof(section,p,sdim)); PetscCall(PetscSectionSetFieldDof(section,p,0,sdim)); } /* add constraints at all vertices belonging to a vertex set */ /* first pass is to reserve space */ PetscCall(DMGetLabelSize(dm,"Vertex Sets",&numVS)); PetscCall(PetscPrintf(PETSC_COMM_WORLD,"# Vertex set: %" PetscInt_FMT "\n",numVS)); PetscCall(DMGetLabelIdIS(dm,"Vertex Sets",&setIS)); PetscCall(ISGetIndices(setIS,&setID)); for (s = 0; s < numVS; ++s){ PetscCall(DMGetStratumIS(dm,"Vertex Sets",setID[s],&pointIS)); PetscCall(DMGetStratumSize(dm,"Vertex Sets",setID[s],&numPoints)); PetscCall(PetscPrintf(PETSC_COMM_WORLD,"set %" PetscInt_FMT " size: %" PetscInt_FMT "\n",s,numPoints)); PetscCall(ISGetIndices(pointIS,&pointID)); for (p = 0; p < numPoints; ++p){ PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\t point %" PetscInt_FMT "\n",pointID[p])); PetscCall(PetscSectionSetConstraintDof(section,pointID[p],1)); PetscCall(PetscSectionSetFieldConstraintDof(section,pointID[p],field,1)); } PetscCall(ISRestoreIndices(pointIS,&pointID)); PetscCall(ISDestroy(&pointIS)); } PetscCall(PetscSectionSetUp(section)); /* add constraints at all vertices belonging to a vertex set */ /* second pass is to assign constraints to a specific component / dof */ for (s = 0; s < numVS; ++s){ PetscCall(DMGetStratumIS(dm,"Vertex Sets",setID[s],&pointIS)); PetscCall(DMGetStratumSize(dm,"Vertex Sets",setID[s],&numPoints)); PetscCall(ISGetIndices(pointIS,&pointID)); for (p = 0; p < numPoints; ++p){ constraints[0] = setID[s]%sdim; PetscCall(PetscSectionSetConstraintIndices(section,pointID[p],constraints)); PetscCall(PetscSectionSetFieldConstraintIndices(section,pointID[p],field,constraints)); } PetscCall(ISRestoreIndices(pointIS,&pointID)); PetscCall(ISDestroy(&pointIS)); } PetscCall(ISRestoreIndices(setIS,&setID)); PetscCall(ISDestroy(&setIS)); PetscCall(PetscObjectViewFromOptions((PetscObject) section,NULL,"-dm_section_view")); PetscCall(PetscSectionDestroy(§ion)); PetscCall(DMDestroy(&dm)); PetscCall(PetscFinalize()); return 0; } /*TEST build: requires: exodusii pnetcdf !complex testset: args: -i ${wPETSC_DIR}/share/petsc/datafiles/meshes/SquareFaceSet.exo -dm_view -dm_section_view nsize: 1 test: suffix: 0 args: TEST*/