static PetscErrorCode SetupSection(DM dm) { PetscSection s; PetscInt vStart, vEnd, v; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &s);CHKERRQ(ierr); ierr = PetscSectionSetNumFields(s, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(s, 0, 1);CHKERRQ(ierr); ierr = PetscSectionSetChart(s, vStart, vEnd);CHKERRQ(ierr); for (v = vStart; v < vEnd; ++v) { ierr = PetscSectionSetDof(s, v, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(s, v, 0, 1);CHKERRQ(ierr); } ierr = PetscSectionSetUp(s);CHKERRQ(ierr); ierr = DMSetSection(dm, s);CHKERRQ(ierr); ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc, char **argv) { DM dm, dmDist = NULL; Vec u; PetscSection section; PetscViewer viewer; PetscInt dim = 2, numFields, numBC, i; PetscInt numComp[3]; PetscInt numDof[12]; PetscInt bcField[1]; IS bcPointIS[1]; PetscBool interpolate = PETSC_TRUE; PetscErrorCode ierr; ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; ierr = PetscOptionsGetInt(NULL,NULL, "-dim", &dim, NULL);CHKERRQ(ierr); /* Create a mesh */ ierr = DMPlexCreateBoxMesh(PETSC_COMM_WORLD, dim, PETSC_TRUE, NULL, NULL, NULL, NULL, interpolate, &dm);CHKERRQ(ierr); /* Distribute mesh over processes */ ierr = DMPlexDistribute(dm, 0, NULL, &dmDist);CHKERRQ(ierr); if (dmDist) {ierr = DMDestroy(&dm);CHKERRQ(ierr); dm = dmDist;} /* Create a scalar field u, a vector field v, and a surface vector field w */ numFields = 3; numComp[0] = 1; numComp[1] = dim; numComp[2] = dim-1; for (i = 0; i < numFields*(dim+1); ++i) numDof[i] = 0; /* Let u be defined on vertices */ numDof[0*(dim+1)+0] = 1; /* Let v be defined on cells */ numDof[1*(dim+1)+dim] = dim; /* Let v be defined on faces */ numDof[2*(dim+1)+dim-1] = dim-1; /* Setup boundary conditions */ numBC = 1; /* Prescribe a Dirichlet condition on u on the boundary Label "marker" is made by the mesh creation routine */ bcField[0] = 0; ierr = DMGetStratumIS(dm, "marker", 1, &bcPointIS[0]);CHKERRQ(ierr); /* Create a PetscSection with this data layout */ ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); ierr = DMPlexCreateSection(dm, NULL, numComp, numDof, numBC, bcField, NULL, bcPointIS, NULL, §ion);CHKERRQ(ierr); ierr = ISDestroy(&bcPointIS[0]);CHKERRQ(ierr); /* Name the Field variables */ ierr = PetscSectionSetFieldName(section, 0, "u");CHKERRQ(ierr); ierr = PetscSectionSetFieldName(section, 1, "v");CHKERRQ(ierr); ierr = PetscSectionSetFieldName(section, 2, "w");CHKERRQ(ierr); ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); /* Tell the DM to use this data layout */ ierr = DMSetSection(dm, section);CHKERRQ(ierr); /* Create a Vec with this layout and view it */ ierr = DMGetGlobalVector(dm, &u);CHKERRQ(ierr); ierr = PetscViewerCreate(PETSC_COMM_WORLD, &viewer);CHKERRQ(ierr); ierr = PetscViewerSetType(viewer, PETSCVIEWERVTK);CHKERRQ(ierr); ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_VTK);CHKERRQ(ierr); ierr = PetscViewerFileSetName(viewer, "sol.vtk");CHKERRQ(ierr); ierr = VecView(u, viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dm, &u);CHKERRQ(ierr); /* Cleanup */ ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
//! Help PETSc identify the coarser DM dmc given the fine DM dmf PetscErrorCode libmesh_petsc_DMCoarsen(DM dmf, MPI_Comm /*comm*/, DM * dmc) { libmesh_assert(dmc); libmesh_assert(dmf); PetscErrorCode ierr; // Extract our context from the incoming dmf void * ctx_f = nullptr; ierr = DMShellGetContext(dmf, &ctx_f);LIBMESH_CHKERR(ierr); libmesh_assert(ctx_f); PetscDMContext * p_ctx = static_cast<PetscDMContext*>(ctx_f); // First, ensure that there exists a coarse DM that we want to // set. There ought to be as we created it while walking the // hierarchy. libmesh_assert(p_ctx->coarser_dm); libmesh_assert(*(p_ctx->coarser_dm)); // In situations using fieldsplit we need to (potentially) // provide a coarser DM which only has the relevant subfields in // it. Since we create global DMs for each mesh level, we need // to extract the section from the DM, and check the number of // fields. When less than all the fields are used, we need to // create the proper subsections. // Get the number of fields and their names from the incomming // fine DM and the global reference DM PetscInt nfieldsf, nfieldsg; char ** fieldnamesf; char ** fieldnamesg; libmesh_assert(p_ctx->global_dm); DM * globaldm = p_ctx->global_dm; ierr = DMCreateFieldIS(dmf, &nfieldsf, &fieldnamesf, nullptr); LIBMESH_CHKERR(ierr); ierr = DMCreateFieldIS(*globaldm, &nfieldsg, &fieldnamesg, nullptr); LIBMESH_CHKERR(ierr); // If the probed number of fields is less than the number of // global fields, this amounts to PETSc 'indicating' to us we // are doing FS. So, we must create subsections for the coarser // DMs. if ( nfieldsf < nfieldsg ) { PetscSection section; PetscSection subsection; std::vector<PetscInt> subfields(nfieldsf); // extracted fields // First, get the section from the coarse DM #if PETSC_VERSION_LESS_THAN(3,10,0) ierr = DMGetDefaultSection(*(p_ctx->coarser_dm), §ion); #else ierr = DMGetSection(*(p_ctx->coarser_dm), §ion); #endif LIBMESH_CHKERR(ierr); // Now, match fine grid DM field names to their global DM // counterparts. Since PETSc can internally reassign field // numbering under a fieldsplit, we must extract // subsections via the field names. This is admittedly // gross, but c'est la vie. for (int i = 0; i < nfieldsf ; i++) { for (int j = 0; j < nfieldsg ;j++) if ( strcmp( fieldnamesg[j], fieldnamesf[i] ) == 0 ) subfields[i] = j; } // Next, for the found fields we now make a subsection and set it for the coarser DM ierr = PetscSectionCreateSubsection(section, nfieldsf, subfields.data(), &subsection); LIBMESH_CHKERR(ierr); #if PETSC_VERSION_LESS_THAN(3,10,0) ierr = DMSetDefaultSection(*(p_ctx->coarser_dm) , subsection); #else ierr = DMSetSection(*(p_ctx->coarser_dm) , subsection); #endif LIBMESH_CHKERR(ierr); ierr = PetscSectionDestroy(&subsection); LIBMESH_CHKERR(ierr); } // Finally, set the coarser DM *(dmc) = *(p_ctx->coarser_dm); return 0; }