Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 :
19 :
20 : #ifndef LIBMESH_EIGEN_SPARSE_LINEAR_SOLVER_H
21 : #define LIBMESH_EIGEN_SPARSE_LINEAR_SOLVER_H
22 :
23 : #include "libmesh/libmesh_common.h"
24 :
25 : #ifdef LIBMESH_HAVE_EIGEN
26 :
27 : // Eigen includes
28 :
29 : // Local includes
30 : #include "libmesh/linear_solver.h"
31 : #include "libmesh/eigen_sparse_vector.h"
32 : #include "libmesh/eigen_sparse_matrix.h"
33 : #include "libmesh/enum_convergence_flags.h" // The build_map() function uses these.
34 :
35 :
36 : namespace libMesh
37 : {
38 :
39 : /**
40 : * This class provides an interface to Eigen
41 : * iterative solvers that is compatible with the \p libMesh
42 : * \p LinearSolver<>
43 : *
44 : * \author Benjamin Kirk
45 : * \date 2013
46 : */
47 : template <typename T>
48 : class EigenSparseLinearSolver : public LinearSolver<T>
49 : {
50 : public:
51 : /**
52 : * Constructor. Initializes Eigen data structures
53 : */
54 : EigenSparseLinearSolver (const libMesh::Parallel::Communicator & comm_in);
55 :
56 : /**
57 : * Destructor.
58 : */
59 : ~EigenSparseLinearSolver ();
60 :
61 : /**
62 : * Release all memory and clear data structures.
63 : */
64 : virtual void clear () override;
65 :
66 : /**
67 : * Initialize data structures if not done so already.
68 : */
69 : virtual void init (const char * name=nullptr) override;
70 :
71 : /**
72 : * Call the Eigen solver
73 : */
74 : virtual std::pair<unsigned int, Real>
75 : solve (SparseMatrix<T> & matrix,
76 : NumericVector<T> & solution,
77 : NumericVector<T> & rhs,
78 : const std::optional<double> tol = std::nullopt,
79 : const std::optional<unsigned int> m_its = std::nullopt) override;
80 :
81 : /**
82 : * Call the Eigen solver to solve A^T x = b
83 : */
84 : virtual std::pair<unsigned int, Real>
85 : adjoint_solve (SparseMatrix<T> & matrix,
86 : NumericVector<T> & solution,
87 : NumericVector<T> & rhs,
88 : const std::optional<double> tol = std::nullopt,
89 : const std::optional<unsigned int> m_its = std::nullopt) override;
90 :
91 : /**
92 : * Call the Eigen solver
93 : */
94 : virtual std::pair<unsigned int, Real>
95 : solve (SparseMatrix<T> & matrix,
96 : SparseMatrix<T> & pc,
97 : NumericVector<T> & solution,
98 : NumericVector<T> & rhs,
99 : const std::optional<double> tol = std::nullopt,
100 : const std::optional<unsigned int> m_its = std::nullopt) override;
101 :
102 : /**
103 : * This function solves a system whose matrix is a shell matrix.
104 : */
105 : virtual std::pair<unsigned int, Real>
106 : solve (const ShellMatrix<T> & shell_matrix,
107 : NumericVector<T> & solution_in,
108 : NumericVector<T> & rhs_in,
109 : const std::optional<double> tol = std::nullopt,
110 : const std::optional<unsigned int> m_its = std::nullopt) override;
111 :
112 : /**
113 : * This function solves a system whose matrix is a shell matrix, but
114 : * a sparse matrix is used as preconditioning matrix, this allowing
115 : * other preconditioners than JACOBI.
116 : */
117 : virtual std::pair<unsigned int, Real>
118 : solve (const ShellMatrix<T> & shell_matrix,
119 : const SparseMatrix<T> & precond_matrix,
120 : NumericVector<T> & solution_in,
121 : NumericVector<T> & rhs_in,
122 : const std::optional<double> tol = std::nullopt,
123 : const std::optional<unsigned int> m_its = std::nullopt) override;
124 :
125 : /**
126 : * \returns The solver's convergence flag
127 : */
128 : virtual LinearConvergenceReason get_converged_reason() const override;
129 :
130 : private:
131 :
132 : /**
133 : * Tells Eigen to use the user-specified preconditioner stored in
134 : * \p _preconditioner_type
135 : */
136 : void set_eigen_preconditioner_type ();
137 :
138 : /**
139 : * Store the result of the last solve.
140 : */
141 : Eigen::ComputationInfo _comp_info;
142 :
143 : /**
144 : * Static map between Eigen ComputationInfo enumerations and libMesh
145 : * LinearConvergenceReason enumerations.
146 : */
147 : static std::map<Eigen::ComputationInfo, LinearConvergenceReason> _convergence_reasons;
148 :
149 : /**
150 : * Static function used to initialize _convergence_reasons map
151 : */
152 16389 : static std::map<Eigen::ComputationInfo, LinearConvergenceReason> build_map()
153 : {
154 462 : std::map<Eigen::ComputationInfo, LinearConvergenceReason> ret;
155 16389 : ret[Eigen::Success] = CONVERGED_ITS;
156 16389 : ret[Eigen::NumericalIssue] = DIVERGED_BREAKDOWN;
157 16389 : ret[Eigen::NoConvergence] = DIVERGED_ITS;
158 16389 : ret[Eigen::InvalidInput] = DIVERGED_NULL;
159 16389 : return ret;
160 : }
161 : };
162 :
163 :
164 :
165 : // Call the class-static function to define the class-static member.
166 : // Since it's a template class, you actually do this in the header,
167 : // not the source file.
168 : template <typename T>
169 : std::map<Eigen::ComputationInfo, LinearConvergenceReason>
170 : EigenSparseLinearSolver<T>::_convergence_reasons = EigenSparseLinearSolver<T>::build_map();
171 :
172 :
173 :
174 : template <typename T>
175 : inline
176 552 : EigenSparseLinearSolver<T>::~EigenSparseLinearSolver ()
177 : {
178 0 : this->clear ();
179 552 : }
180 :
181 :
182 :
183 : template <typename T>
184 : inline
185 : std::pair<unsigned int, Real>
186 0 : EigenSparseLinearSolver<T>::solve (SparseMatrix<T> &,
187 : SparseMatrix<T> &,
188 : NumericVector<T> &,
189 : NumericVector<T> &,
190 : const std::optional<double>,
191 : const std::optional<unsigned int>)
192 : {
193 0 : libmesh_error_msg("ERROR: Eigen does not support a user-supplied preconditioner!");
194 :
195 : return std::pair<unsigned int, Real>();
196 : }
197 :
198 : } // namespace libMesh
199 :
200 : #endif // #ifdef LIBMESH_HAVE_EIGEN
201 : #endif // LIBMESH_EIGEN_SPARSE_LINEAR_SOLVER_H
|