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"
228 std::string name = dlm->
sys->
name();
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;
void set_union(T &data, const unsigned int root_id) const
dof_id_type first_dof(const processor_id_type proc) const
dof_id_type end_dof(const processor_id_type proc) const
This class handles the numbering of degrees of freedom on a mesh.
unsigned int n_variables() const override
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
const Variable & variable(const unsigned int c) const override
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.
This is the base class from which all geometric element types are derived.
NumericVector< Number > * rhs
The system matrix.
SparseMatrix< Number > * matrix
The system matrix.
This is the MeshBase class.
std::string & subdomain_name(subdomain_id_type id)
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
The NonlinearSolver defines the default interface used to solve the nonlinear_implicit system.
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
const Parallel::Communicator & comm() const
This class provides a nice interface to the PETSc C-based data structures for parallel,...
void swap(PetscMatrixBase< T > &)
Swaps the internal data pointers of two PetscMatrices, no actual values are swapped.
static PetscMatrixBase< T > * get_context(Mat mat, const TIMPI::Communicator &comm)
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
This class provides a nice interface to PETSc's Vec object.
void attach_dof_map(const DofMap &dof_map)
Set a pointer to the DofMap to use.
virtual void zero()=0
Set all entries to 0.
const std::string & name() const
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
virtual void update()
Update the local values to reflect the solution on neighboring processors.
const DofMap & get_dof_map() const
const MeshBase & get_mesh() const
const std::string & name() const
The libMesh namespace provides an interface to certain functionality in the library.
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
dof_id_type numeric_index_type
LibmeshPetscCallQ(DMShellGetContext(dm, &ctx))
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...
PETSC_EXTERN PetscErrorCode DMlibMeshGetSystem(DM, libMesh::NonlinearImplicitSystem *&)
static PetscErrorCode DMlibMeshFunction(DM dm, Vec x, Vec r)
static PetscErrorCode DMCreateGlobalVector_libMesh(DM dm, Vec *x)
static PetscErrorCode SNESFunction_DMlibMesh(SNES, Vec x, Vec r, void *ctx)
static PetscErrorCode DMView_libMesh(DM dm, PetscViewer viewer)
static PetscErrorCode DMSetUp_libMesh(DM dm)
PetscErrorCode DMlibMeshGetBlocks(DM dm, PetscInt *n, char ***blocknames)
static PetscErrorCode DMlibMeshJacobian(DM dm, Vec x, Mat jac, Mat pc)
static PetscErrorCode DMCreateMatrix_libMesh(DM dm, Mat *A)
PetscErrorCode DMlibMeshSetUpName_Private(DM dm)
static PetscErrorCode SNESJacobian_DMlibMesh(SNES, Vec x, Mat jac, Mat pc, void *ctx)
PetscErrorCode DMlibMeshCreateFieldDecompositionDM(DM dm, PetscInt dnumber, PetscInt *dsizes, char ***dvarlists, DM *ddm)
PetscErrorCode DMlibMeshGetVec_Private(DM, const char *, Vec *)
PetscErrorCode DMCreate_libMesh(DM dm)
static PetscErrorCode DMDestroy_libMesh(DM dm)
static PetscErrorCode DMVariableBounds_libMesh(DM dm, Vec xl, Vec xu)
PetscErrorCode DMlibMeshGetVariables(DM dm, PetscInt *n, char ***varnames)
PetscErrorCode DMlibMeshGetSystem_libMesh(DM dm, NonlinearImplicitSystem *&sys)
PetscErrorCode DMlibMeshSetSystem_libMesh(DM dm, NonlinearImplicitSystem &sys)
static PetscErrorCode DMCreateFieldDecomposition_libMesh(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
static PetscErrorCode DMCreateDomainDecomposition_libMesh(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
PetscErrorCode DMlibMeshCreateDomainDecompositionDM(DM dm, PetscInt dnumber, PetscInt *dsizes, char ***dblocklists, DM *ddm)
unsigned int decomposition_type
std::vector< std::set< unsigned int > > * decomposition
std::map< std::string, unsigned int > * varids
unsigned int embedding_type
std::map< unsigned int, std::string > * blocknames
NonlinearImplicitSystem * sys
std::map< std::string, unsigned int > * blockids
std::map< unsigned int, std::string > * varnames
The definition of the const_element_iterator struct.