16#include "./InternalHeaderCheck.h"
60template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
61bool gmres(
const MatrixType& mat,
const Rhs& rhs, Dest& x,
const Preconditioner& precond, Index& iters,
62 const Index& restart_,
typename Dest::RealScalar& tol_error) {
66 using RealScalar =
typename Dest::RealScalar;
67 using Scalar =
typename Dest::Scalar;
68 using VectorType = Matrix<Scalar, Dynamic, 1>;
69 using FMatrixType = Matrix<Scalar, Dynamic, Dynamic, ColMajor>;
71 const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
73 if (rhs.norm() <= considerAsZero) {
79 RealScalar tol = tol_error;
80 const Index maxIters = iters;
83 const Index m = mat.rows();
86 const Index restart = numext::mini(numext::maxi(restart_, Index(1)), m);
89 VectorType p0 = rhs - mat * x;
90 VectorType r0 = precond.solve(p0);
92 const RealScalar r0Norm = r0.norm();
95 const RealScalar rhsNorm = numext::maxi((x.squaredNorm() == 0) ? r0Norm : precond.solve(rhs).norm(), considerAsZero);
96 const RealScalar threshold = numext::maxi(tol * rhsNorm, considerAsZero);
99 if (r0Norm < threshold) {
100 tol_error = r0Norm / rhsNorm;
105 FMatrixType H = FMatrixType::Zero(m, restart + 1);
106 VectorType w = VectorType::Zero(restart + 1);
107 VectorType tau = VectorType::Zero(restart + 1);
110 std::vector<JacobiRotation<Scalar> > G(restart);
113 VectorType t(m), v(m), workspace(m), x_new(m);
116 Ref<VectorType> H0_tail = H.col(0).tail(m - 1);
118 r0.makeHouseholder(H0_tail, tau.coeffRef(0), beta);
121 for (Index k = 1; k <= restart; ++k) {
124 v = VectorType::Unit(m, k - 1);
128 for (Index i = k - 1; i >= 0; --i) {
129 v.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data());
133 t.noalias() = mat * v;
134 v = precond.solve(t);
138 for (Index i = 0; i < k; ++i) {
139 v.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data());
142 if (v.tail(m - k).norm() != 0.0 && k <= restart) {
144 Ref<VectorType> Hk_tail = H.col(k).tail(m - k - 1);
145 v.tail(m - k).makeHouseholder(Hk_tail, tau.coeffRef(k), beta);
148 v.tail(m - k).applyHouseholderOnTheLeft(Hk_tail, tau.coeffRef(k), workspace.data());
152 for (Index i = 0; i < k - 1; ++i) {
153 v.applyOnTheLeft(i, i + 1, G[i].adjoint());
156 if (k < m && v(k) != (Scalar)0) {
158 G[k - 1].makeGivens(v(k - 1), v(k));
161 v.applyOnTheLeft(k - 1, k, G[k - 1].adjoint());
162 w.applyOnTheLeft(k - 1, k, G[k - 1].adjoint());
166 H.col(k - 1).head(k) = v.head(k);
168 tol_error = abs(w(k)) / rhsNorm;
169 bool stop = (k == m || tol_error < tol || iters == maxIters);
171 if (stop || k == restart) {
173 Ref<VectorType> y = w.head(k);
174 H.topLeftCorner(k, k).template triangularView<Upper>().solveInPlace(y);
178 for (Index i = k - 1; i >= 0; --i) {
181 x_new.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data());
192 p0.noalias() = rhs - mat * x;
193 r0 = precond.solve(p0);
201 r0.makeHouseholder(H0_tail, tau.coeffRef(0), beta);
212template <
typename MatrixType_,
typename Preconditioner_ = DiagonalPreconditioner<
typename MatrixType_::Scalar> >
217template <
typename MatrixType_,
typename Preconditioner_>
218struct traits<GMRES<MatrixType_, Preconditioner_> > {
219 using MatrixType = MatrixType_;
220 using Preconditioner = Preconditioner_;
263template <
typename MatrixType_,
typename Preconditioner_>
269 using Base::m_isInitialized;
270 using Base::m_iterations;
274 Index m_restart = 30;
277 using Base::_solve_impl;
278 using MatrixType = MatrixType_;
279 using Scalar =
typename MatrixType::Scalar;
280 using RealScalar =
typename MatrixType::RealScalar;
281 using Preconditioner = Preconditioner_;
297 template <
typename MatrixDerived>
310 template <
typename Rhs,
typename Dest>
311 void _solve_vector_with_guess_impl(
const Rhs& b, Dest& x)
const {
313 m_error = Base::m_tolerance;
314 bool ret = internal::gmres(matrix(), b, x, Base::m_preconditioner, m_iterations, m_restart, m_error);
A GMRES solver for sparse square problems.
Definition GMRES.h:264
GMRES(const EigenBase< MatrixDerived > &A)
Definition GMRES.h:298
Index get_restart() const
Definition GMRES.h:302
GMRES()
Definition GMRES.h:285
void set_restart(const Index restart)
Definition GMRES.h:307
IterativeSolverBase()
Definition IterativeSolverBase.h:136
Index maxIterations() const
Definition IterativeSolverBase.h:245
@ NumericalIssue
Definition Constants.h:459
@ Success
Definition Constants.h:457
@ NoConvergence
Definition Constants.h:461
Definition EigenBase.h:34