20 #include "libmesh/petsc_macro.h" 22 #ifdef LIBMESH_HAVE_PETSC 24 #include "libmesh/ignore_warnings.h" 27 #if !PETSC_VERSION_LESS_THAN(3,6,0) 28 # include <petsc/private/dmimpl.h> 30 # include <petsc-private/dmimpl.h> 33 #include "libmesh/restore_warnings.h" 36 #include "libmesh/libmesh_common.h" 37 #include "libmesh/nonlinear_implicit_system.h" 38 #include "libmesh/petsc_nonlinear_solver.h" 39 #include "libmesh/petsc_linear_solver.h" 40 #include "libmesh/petsc_vector.h" 41 #include "libmesh/petsc_matrix_base.h" 42 #include "libmesh/petscdmlibmesh.h" 43 #include "libmesh/dof_map.h" 44 #include "libmesh/preconditioner.h" 45 #include "libmesh/elem.h" 46 #include "libmesh/parallel.h" 52 #define DMLIBMESH_NO_DECOMPOSITION 0 53 #define DMLIBMESH_FIELD_DECOMPOSITION 1 54 #define DMLIBMESH_DOMAIN_DECOMPOSITION 2 56 #define DMLIBMESH_NO_EMBEDDING 0 57 #define DMLIBMESH_FIELD_EMBEDDING 1 58 #define DMLIBMESH_DOMAIN_EMBEDDING 2 63 std::map<std::string, unsigned int> *
varids;
64 std::map<unsigned int, std::string> *
varnames;
65 std::map<std::string, unsigned int> *
blockids;
79 #define __FUNCT__ "DMlibMeshGetVec_Private" 92 #define __FUNCT__ "DMlibMeshSetSystem_libMesh" 98 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
100 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
101 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
103 if (dm->setupcalled) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE,
"Cannot reset the libMesh system after DM has been set up.");
113 dlm->
varids->insert(std::pair<std::string,unsigned int>(vname,v));
114 dlm->
varnames->insert(std::pair<unsigned int,std::string>(v,vname));
119 std::set<subdomain_id_type> blocks;
123 for (
const auto & elem :
mesh.active_element_ptr_range())
124 blocks.insert(elem->subdomain_id());
128 std::set<subdomain_id_type>::iterator bit = blocks.begin();
129 std::set<subdomain_id_type>::iterator bend = blocks.end();
130 if (bit == bend) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_PLIB,
"No mesh blocks found.");
132 for (; bit != bend; ++bit) {
135 if (!bname.length()) {
140 std::ostringstream ss;
144 dlm->
blockids->insert(std::pair<std::string,unsigned int>(bname,bid));
145 dlm->
blocknames->insert(std::pair<unsigned int,std::string>(bid,bname));
152 #define __FUNCT__ "DMlibMeshGetSystem_libMesh" 156 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
158 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
159 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
167 #define __FUNCT__ "DMlibMeshGetBlocks" 172 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
174 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
175 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
177 #if PETSC_RELEASE_GREATER_EQUALS(3,20,0) 178 PetscAssertPointer(n,2);
180 PetscValidPointer(n,2);
182 *n = cast_int<unsigned int>(dlm->
blockids->size());
186 for (
const auto & pr : *(dlm->
blockids))
195 #define __FUNCT__ "DMlibMeshGetVariables" 199 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
202 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
203 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
205 #if PETSC_RELEASE_GREATER_EQUALS(3,20,0) 206 PetscAssertPointer(n,2);
208 PetscValidPointer(n,2);
210 *n = cast_int<unsigned int>(dlm->
varids->size());
214 for (
const auto & pr : *(dlm->
varids))
223 #define __FUNCT__ "DMlibMeshSetUpName_Private" 229 std::map<unsigned int, std::string> * dnames = LIBMESH_PETSC_NULLPTR,
230 * enames = LIBMESH_PETSC_NULLPTR;
236 name +=
":dec:block:";
241 for (std::set<unsigned int>::iterator dit_begin = decomp.begin(),
243 dit_end = decomp.end();
244 dit != dit_end; ++dit) {
245 unsigned int id = *dit;
246 if (dit != dit_begin)
248 name += (*dnames)[id];
258 name +=
":emb:block:";
262 for (
auto eit = enames->begin(),
263 eit_end = enames->end(); eit != eit_end; ++eit) {
264 std::string & ename = eit->second;
265 if (eit != enames->begin())
277 #define __FUNCT__ "DMCreateFieldDecomposition_libMesh" 292 std::set<numeric_index_type> dindices;
294 std::map<std::string, unsigned int> dvarids;
295 std::map<unsigned int, std::string> dvarnames;
296 unsigned int dvcount = 0;
298 std::string vname = (*dlm->
varnames)[v];
299 dvarids.insert(std::pair<std::string, unsigned int>(vname,v));
300 dvarnames.insert(std::pair<unsigned int,std::string>(v,vname));
301 if (!dvcount) dname = vname;
302 else dname +=
"_" + vname;
304 if (!islist)
continue;
306 for (
const auto & pr : *(dlm->
blockids)) {
308 for (
const auto & elem :
310 sys->
get_mesh().active_local_subdomain_elements_end(sbd_id))) {
312 std::vector<numeric_index_type> evindices;
317 dindices.insert(dof);
330 for (
const auto &
id : dindices) {
335 cast_int<PetscInt>(dindices.size()),
336 darray, PETSC_OWN_POINTER, &dis));
343 if (elen != dlen) LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB,
"Failed to embed subdomain %zu", d);
377 #define __FUNCT__ "DMCreateDomainDecomposition_libMesh" 388 if (outerislist) *outerislist = LIBMESH_PETSC_NULLPTR;
391 std::set<numeric_index_type> dindices;
393 std::map<std::string, unsigned int> dblockids;
394 std::map<unsigned int,std::string> dblocknames;
395 unsigned int dbcount = 0;
398 dblockids.insert(std::pair<std::string, unsigned int>(bname,b));
399 dblocknames.insert(std::pair<unsigned int,std::string>(b,bname));
400 if (!dbcount) dname = bname;
401 else dname +=
"_" + bname;
403 if (!innerislist)
continue;
407 for ( ; el != end_el; ++el) {
408 const Elem * elem = *el;
409 std::vector<numeric_index_type> evindices;
411 for (
const auto & pr : *(dlm->
varids)) {
414 for (
const auto & dof : evindices) {
416 dindices.insert(dof);
429 for (
const auto &
id : dindices) {
434 cast_int<PetscInt>(dindices.size()),
435 darray, PETSC_OWN_POINTER, &dis));
442 if (elen != dlen) LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB,
"Failed to embed field %zu" , d);
451 (*innerislist)[d] = dis;
481 #define __FUNCT__ "DMlibMeshCreateFieldDecompositionDM" 486 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
487 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
488 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
489 if (dnumber < 0) LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Negative number %" LIBMESH_PETSCINT_FMT
" of decomposition parts", dnumber);
490 #if PETSC_RELEASE_GREATER_EQUALS(3,20,0) 491 PetscAssertPointer(ddm,5);
493 PetscValidPointer(ddm,5);
504 ddlm->
decomposition =
new(std::vector<std::set<unsigned int>>);
507 for (PetscInt d = 0; d < dnumber; ++d) {
508 if (dsizes[d] < 0) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Negative size %" LIBMESH_PETSCINT_FMT
" of decomposition part %" LIBMESH_PETSCINT_FMT, dsizes[d],d);
510 for (PetscInt v = 0; v < dsizes[d]; ++v) {
511 std::string vname(dvarlists[d][v]);
512 std::map<std::string, unsigned int>::const_iterator vit = dlm->
varids->find(vname);
513 if (vit == dlm->
varids->end())
514 LIBMESH_SETERRQ3(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Variable %" LIBMESH_PETSCINT_FMT
" on the %" LIBMESH_PETSCINT_FMT
"-th list with name %s is not owned by this DM", v, d, dvarlists[d][v]);
515 unsigned int vid = vit->second;
522 for (
const auto & pr : (*ddlm->
varids)) {
524 unsigned int vid = pr.second;
536 #define __FUNCT__ "DMlibMeshCreateDomainDecompositionDM" 541 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
542 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
543 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
544 if (dnumber < 0) LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Negative number %" LIBMESH_PETSCINT_FMT
" of decomposition parts", dnumber);
545 #if PETSC_RELEASE_GREATER_EQUALS(3,20,0) 546 PetscAssertPointer(ddm,5);
548 PetscValidPointer(ddm,5);
559 ddlm->
decomposition =
new(std::vector<std::set<unsigned int>>);
562 for (PetscInt d = 0; d < dnumber; ++d) {
563 if (dsizes[d] < 0) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Negative size %" LIBMESH_PETSCINT_FMT
" of decomposition part %" LIBMESH_PETSCINT_FMT, dsizes[d],d);
565 for (PetscInt b = 0; b < dsizes[d]; ++b) {
566 std::string bname(dblocklists[d][b]);
567 std::map<std::string, unsigned int>::const_iterator bit = dlm->
blockids->find(bname);
569 LIBMESH_SETERRQ3(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"Block %" LIBMESH_PETSCINT_FMT
" on the %" LIBMESH_PETSCINT_FMT
"-th list with name %s is not owned by this DM", b, d, dblocklists[d][b]);
570 unsigned int bid = bit->second;
577 for (
const auto & pr : (*ddlm->
blockids)) {
579 unsigned int bid = pr.second;
598 #define __FUNCT__ "DMlibMeshFunction" 613 X_global.
swap(X_sys);
620 X_global.swap(X_sys);
627 "ERROR: cannot specify both a function and object to compute the Residual!");
630 "ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
645 libmesh_error_msg(
"Error! Unable to compute residual and/or Jacobian!");
653 #define __FUNCT__ "SNESFunction_DMlibMesh" 664 #define __FUNCT__ "DMlibMeshJacobian" 685 X_global.swap(X_sys);
691 X_global.swap(X_sys);
699 "ERROR: cannot specify both a function and object to compute the Jacobian!");
702 "ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
717 libmesh_error_msg(
"Error! Unable to compute residual and/or Jacobian!");
726 #define __FUNCT__ "SNESJacobian_DMlibMesh" 736 #define __FUNCT__ "DMVariableBounds_libMesh" 746 const PetscReal petsc_inf = std::numeric_limits<PetscReal>::max() / 4;
754 SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"No bounds calculation in this libMesh object");
761 #define __FUNCT__ "DMCreateGlobalVector_libMesh" 771 LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
774 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"No libMesh system set for DM_libMesh");
794 #if PETSC_VERSION_LESS_THAN(3,13,0) 807 #define __FUNCT__ "DMCreateMatrix_libMesh" 817 LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
820 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"No libMesh system set for DM_libMesh");
829 #define __FUNCT__ "DMView_libMesh" 833 const char *
name, * prefix;
836 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
840 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"DM libMesh with name %s and prefix %s\n",
name, prefix));
842 std::map<std::string,unsigned int>::iterator bit = dlm->
blockids->begin();
843 std::map<std::string,unsigned int>::const_iterator bend = dlm->
blockids->end();
844 for (; bit != bend; ++bit) {
845 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"(%s,%d) ", bit->first.c_str(), bit->second));
849 std::map<std::string,unsigned int>::iterator vit = dlm->
varids->begin();
850 std::map<std::string,unsigned int>::const_iterator vend = dlm->
varids->end();
851 for (; vit != vend; ++vit) {
852 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"(%s,%d) ", vit->first.c_str(), vit->second));
860 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"Field decomposition by variable: "));
863 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"Domain decomposition by block: "));
865 else LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB,
"Unexpected decomposition type: %d", dlm->
decomposition_type);
868 std::set<unsigned int>::iterator dbegin = (*dlm->
decomposition)[d].begin();
869 std::set<unsigned int>::iterator dit = (*dlm->
decomposition)[d].begin();
870 std::set<unsigned int>::iterator dend = (*dlm->
decomposition)[d].end();
871 for (; dit != dend; ++dit) {
887 #define __FUNCT__ "DMSetUp_libMesh" 897 LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG,
"DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
900 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"No libMesh system set for DM_libMesh");
915 dm->ops->createglobalvector = 0;
916 dm->ops->creatematrix = 0;
925 #define __FUNCT__ "DMDestroy_libMesh" 943 #define __FUNCT__ "DMCreate_libMesh" 949 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
954 dlm->
varids =
new(std::map<std::string, unsigned int>);
955 dlm->
blockids =
new(std::map<std::string, unsigned int>);
956 dlm->
varnames =
new(std::map<unsigned int, std::string>);
957 dlm->
blocknames =
new(std::map<unsigned int, std::string>);
963 dm->ops->createlocalvector = 0;
964 dm->ops->getcoloring = 0;
966 dm->ops->createinterpolation= 0;
969 dm->ops->coarsen = 0;
974 #if PETSC_VERSION_LESS_THAN(3,12,0) 975 dm->ops->getinjection = 0;
976 dm->ops->getaggregates = 0;
978 dm->ops->createinjection = 0;
987 dm->ops->setfromoptions = 0;
998 #endif // LIBMESH_HAVE_PETSC static PetscErrorCode SNESFunction_DMlibMesh(SNES, Vec x, Vec r, void *ctx)
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
static PetscErrorCode SNESJacobian_DMlibMesh(SNES, Vec x, Mat jac, Mat pc, void *ctx)
static PetscErrorCode DMVariableBounds_libMesh(DM dm, Vec xl, Vec xu)
static PetscErrorCode DMCreateDomainDecomposition_libMesh(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
dof_id_type end_dof(const processor_id_type proc) const
NonlinearImplicitSystem * sys
This class provides a nice interface to PETSc's Vec object.
static PetscErrorCode DMCreateGlobalVector_libMesh(DM dm, Vec *x)
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
The NonlinearSolver defines the default interface used to solve the nonlinear_implicit system...
void swap(PetscMatrixBase< T > &)
Swaps the internal data pointers of two PetscMatrices, no actual values are swapped.
PetscErrorCode DMlibMeshSetUpName_Private(DM dm)
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
The definition of the const_element_iterator struct.
unsigned int embedding_type
std::map< std::string, unsigned int > * blockids
PetscErrorCode DMlibMeshSetSystem_libMesh(DM dm, NonlinearImplicitSystem &sys)
std::map< std::string, unsigned int > * varids
This is the base class from which all geometric element types are derived.
static PetscErrorCode DMCreateMatrix_libMesh(DM dm, Mat *A)
static PetscErrorCode DMCreateFieldDecomposition_libMesh(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
NumericVector< Number > * rhs
The system matrix.
const Parallel::Communicator & comm() const
static PetscMatrixBase< T > * get_context(Mat mat, const TIMPI::Communicator &comm)
PETSC_EXTERN PetscErrorCode DMlibMeshGetSystem(DM, libMesh::NonlinearImplicitSystem *&)
The libMesh namespace provides an interface to certain functionality in the library.
PetscErrorCode DMlibMeshGetBlocks(DM dm, PetscInt *n, char ***blocknames)
const MeshBase & get_mesh() const
This is the MeshBase class.
const Variable & variable(const unsigned int c) const override
virtual void swap(NumericVector< T > &v) override
Swaps the contents of this with v.
This class handles the numbering of degrees of freedom on a mesh.
std::vector< std::set< unsigned int > > * decomposition
PetscErrorCode DMCreate_libMesh(DM dm)
static PetscErrorCode DMSetUp_libMesh(DM dm)
PetscErrorCode DMlibMeshCreateFieldDecompositionDM(DM dm, PetscInt dnumber, PetscInt *dsizes, char ***dvarlists, DM *ddm)
virtual void zero()=0
Set all entries to 0.
dof_id_type numeric_index_type
static PetscErrorCode DMlibMeshFunction(DM dm, Vec x, Vec r)
PetscErrorCode DMlibMeshGetSystem_libMesh(DM dm, NonlinearImplicitSystem *&sys)
unsigned int n_variables() const override
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
std::map< unsigned int, std::string > * varnames
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
std::map< unsigned int, std::string > * blocknames
std::string & subdomain_name(subdomain_id_type id)
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
PetscErrorCode DMlibMeshGetVec_Private(DM, const char *, Vec *)
void attach_dof_map(const DofMap &dof_map)
Set a pointer to the DofMap to use.
LibmeshPetscCallQ(DMShellGetContext(dm, &ctx))
virtual void update()
Update the local values to reflect the solution on neighboring processors.
static PetscErrorCode DMlibMeshJacobian(DM dm, Vec x, Mat jac, Mat pc)
SparseMatrix< Number > * matrix
The system matrix.
PetscErrorCode DMlibMeshGetVariables(DM dm, PetscInt *n, char ***varnames)
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
PetscErrorCode DMlibMeshCreateDomainDecompositionDM(DM dm, PetscInt dnumber, PetscInt *dsizes, char ***dblocklists, DM *ddm)
const std::string & name() const
const std::string & name() const
dof_id_type first_dof(const processor_id_type proc) const
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
const DofMap & get_dof_map() const
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
static PetscErrorCode DMView_libMesh(DM dm, PetscViewer viewer)
unsigned int decomposition_type
static PetscErrorCode DMDestroy_libMesh(DM dm)
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
Constrains the numeric vector v, which represents a solution defined on the mesh. ...
void set_union(T &data, const unsigned int root_id) const