20 #include "libmesh/libmesh_common.h" 22 #ifdef LIBMESH_HAVE_EIGEN 26 #include "libmesh/eigen_sparse_linear_solver.h" 27 #include "libmesh/libmesh_logging.h" 28 #include "libmesh/enum_to_string.h" 29 #include "libmesh/solver_configuration.h" 30 #include "libmesh/enum_preconditioner_type.h" 31 #include "libmesh/enum_solver_type.h" 34 #include "libmesh/ignore_warnings.h" 35 #include <unsupported/Eigen/IterativeSolvers> 36 #include "libmesh/restore_warnings.h" 45 _comp_info(
Eigen::Success)
82 std::pair<unsigned int, Real>
86 const std::optional<double> tol,
87 const std::optional<unsigned int> m_its)
89 LOG_SCOPE(
"solve()",
"EigenSparseLinearSolver");
102 std::pair<unsigned int, Real> retval(0,0.);
106 auto do_solve = [
this, &rhs, &solution, tol, m_its]
107 (
auto & e_solver, std::string_view msg) {
108 const int max_its = this->get_int_solver_setting(
"max_its", m_its);
109 const double abs_tol = this->get_real_solver_setting(
"abs_tol", tol);
111 e_solver.setMaxIterations(max_its);
112 e_solver.setTolerance(abs_tol);
115 solution._vec = e_solver.solveWithGuess(rhs._vec,solution._vec);
117 libMesh::out <<
"#iterations: " << e_solver.iterations() <<
" / " << max_its << std::endl;
118 libMesh::out <<
"estimated error: " << e_solver.error() <<
" / " << abs_tol << std::endl;
119 _comp_info = e_solver.info();
120 return std::make_pair(e_solver.iterations(), e_solver.error());
123 using Eigen::DiagonalPreconditioner;
124 using Eigen::IdentityPreconditioner;
125 using Eigen::IncompleteCholesky;
126 using Eigen::IncompleteLUT;
129 switch (this->_solver_type)
134 const int UPLO = Eigen::Lower|Eigen::Upper;
136 switch (this->_preconditioner_type)
140 Eigen::ConjugateGradient<EigenSM,UPLO,IdentityPreconditioner> solver (matrix.
_mat);
141 retval = do_solve(solver,
"Eigen CG solver without preconditioning");
146 Eigen::ConjugateGradient<EigenSM,UPLO,IncompleteLUT<Number,eigen_idx_type>>
147 solver (matrix.
_mat);
148 retval = do_solve(solver,
"Eigen CG solver with Incomplete Cholesky preconditioning");
153 Eigen::ConjugateGradient<
EigenSM,UPLO,
154 IncompleteCholesky<Number,Eigen::Lower,Eigen::AMDOrdering<eigen_idx_type>>>
155 solver (matrix.
_mat);
156 retval = do_solve(solver,
"Eigen CG solver with Incomplete Cholesky preconditioning");
160 libmesh_warning(
"No EigenSparseLinearSolver support for " <<
161 Utility::enum_to_string<PreconditionerType>(this->_preconditioner_type)
162 <<
" preconditioning.");
163 libmesh_fallthrough();
166 Eigen::ConjugateGradient<EigenSM,UPLO,DiagonalPreconditioner<Number>> solver (matrix.
_mat);
167 retval = do_solve(solver,
"Eigen CG solver with Jacobi preconditioning");
177 switch (this->_preconditioner_type)
181 Eigen::BiCGSTAB<EigenSM, IdentityPreconditioner> solver (matrix.
_mat);
182 retval = do_solve(solver,
"Eigen BiCGStab solver");
188 Eigen::BiCGSTAB<EigenSM,IncompleteLUT<Number, eigen_idx_type>>
189 solver (matrix.
_mat);
190 retval = do_solve(solver,
"Eigen BiCGSTAB solver with ILU preconditioning");
194 libmesh_warning(
"No EigenSparseLinearSolver support for " <<
195 Utility::enum_to_string<PreconditionerType>(this->_preconditioner_type)
196 <<
" preconditioning.");
197 libmesh_fallthrough();
200 Eigen::BiCGSTAB<EigenSM,DiagonalPreconditioner<Number>> solver (matrix.
_mat);
201 retval = do_solve(solver,
"Eigen BiCGSTAB solver with Jacobi preconditioning");
211 auto set_restart_and_solve = [
this, &do_solve]
212 (
auto & gm_solver, std::string_view msg)
217 if (this->_solver_configuration)
218 if (
const auto it = this->_solver_configuration->int_valued_data.find(
"gmres_restart");
219 it != this->_solver_configuration->int_valued_data.end())
220 gm_solver.set_restart(it->second);
222 std::ostringstream full_msg;
223 full_msg << msg <<
", restart = " << gm_solver.get_restart();
224 return do_solve(gm_solver, full_msg.str());
227 switch (this->_preconditioner_type)
231 Eigen::GMRES<EigenSM,IdentityPreconditioner> solver (matrix.
_mat);
232 retval = set_restart_and_solve(solver,
"Eigen GMRES solver without preconditioning");
238 Eigen::GMRES<EigenSM,IncompleteLUT<Number, eigen_idx_type>>
239 solver (matrix.
_mat);
240 retval = set_restart_and_solve(solver,
"Eigen GMRES solver with ILU preconditioning");
244 libmesh_warning(
"No EigenSparseLinearSolver support for " <<
245 Utility::enum_to_string<PreconditionerType>(this->_preconditioner_type)
246 <<
" preconditioning.");
247 libmesh_fallthrough();
250 Eigen::GMRES<EigenSM,DiagonalPreconditioner<Number>> solver (matrix.
_mat);
251 retval = set_restart_and_solve(solver,
"Eigen CG solver with Jacobi preconditioning");
273 matrix.
_mat.makeCompressed();
284 Eigen::SparseLU<EigenSM> solver;
289 solver.analyzePattern(matrix.
_mat);
292 solver.factorize(matrix.
_mat);
295 solution._vec = solver.solve(rhs._vec);
300 retval = std::make_pair(1, 0);
303 _comp_info = solver.info();
312 <<
"Continuing with BICGSTAB" << std::endl;
316 return this->solve (matrix,
329 template <
typename T>
330 std::pair<unsigned int, Real>
334 const std::optional<double> tol,
335 const std::optional<unsigned int> m_its)
337 LOG_SCOPE(
"adjoint_solve()",
"EigenSparseLinearSolver");
339 libmesh_experimental();
343 std::pair<unsigned int, Real> retval = this->solve (mat_trans,
355 template <
typename T>
356 std::pair<unsigned int, Real>
360 const std::optional<double> ,
361 const std::optional<unsigned int> )
363 libmesh_not_implemented();
364 return std::make_pair(0,0.0);
369 template <
typename T>
370 std::pair<unsigned int, Real>
375 const std::optional<double> ,
376 const std::optional<unsigned int> )
378 libmesh_not_implemented();
379 return std::make_pair(0,0.0);
384 template <
typename T>
387 libmesh_not_implemented();
415 template <
typename T>
420 if (
auto it = _convergence_reasons.find(_comp_info);
421 it == _convergence_reasons.end())
423 libmesh_warning(
"Warning: unknown Eigen::ComputationInfo: " \
425 <<
" returning CONVERGED_ITS." \
442 #endif // #ifdef LIBMESH_HAVE_EIGEN
SolverType _solver_type
Enum stating which type of iterative solver to use.
The EigenSparseMatrix class wraps a sparse matrix object from the Eigen library.
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
EigenSparseLinearSolver(const libMesh::Parallel::Communicator &comm_in)
Constructor.
This class provides an interface to Eigen iterative solvers that is compatible with the libMesh Linea...
LinearConvergenceReason
Linear solver convergence flags (taken from the PETSc flags).
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
virtual void init(const char *name=nullptr) override
Initialize data structures if not done so already.
The libMesh namespace provides an interface to certain functionality in the library.
DataType _mat
Actual Eigen::SparseMatrix<> we are wrapping.
This base class can be inherited from to provide interfaces to linear solvers from different packages...
bool _is_initialized
Flag that tells if init() has been called.
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
Eigen::SparseMatrix< Number, Eigen::RowMajor, eigen_idx_type > EigenSM
virtual LinearConvergenceReason get_converged_reason() const override
virtual std::pair< unsigned int, Real > solve(SparseMatrix< T > &matrix, NumericVector< T > &solution, NumericVector< T > &rhs, const std::optional< double > tol=std::nullopt, const std::optional< unsigned int > m_its=std::nullopt) override
Call the Eigen solver.
std::string enum_to_string(const T e)
virtual void clear() override
Release all memory and clear data structures.
void set_eigen_preconditioner_type()
Tells Eigen to use the user-specified preconditioner stored in _preconditioner_type.
virtual void get_transpose(SparseMatrix< T > &dest) const =0
Copies the transpose of the matrix into dest, which may be *this.
virtual std::pair< unsigned int, Real > adjoint_solve(SparseMatrix< T > &matrix, NumericVector< T > &solution, NumericVector< T > &rhs, const std::optional< double > tol=std::nullopt, const std::optional< unsigned int > m_its=std::nullopt) override
Call the Eigen solver to solve A^T x = b.
bool initialized()
Checks that library initialization has been done.
Generic shell matrix, i.e.
This class provides a nice interface to the Eigen C++-based data structures for serial vectors...