Eigen  5.0.1
 
Loading...
Searching...
No Matches
BiCGSTAB.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_BICGSTAB_H
13#define EIGEN_BICGSTAB_H
14
15// IWYU pragma: private
16#include "./InternalHeaderCheck.h"
17
18namespace Eigen {
19
20namespace internal {
21
32template <typename MatrixType, typename Rhs, typename Dest, typename Preconditioner>
33bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x, const Preconditioner& precond, Index& iters,
34 typename Dest::RealScalar& tol_error) {
35 using RealScalar = typename Dest::RealScalar;
36 using Scalar = typename Dest::Scalar;
37 using VectorType = Matrix<Scalar, Dynamic, 1>;
38 Index maxIters = iters;
39
40 Index n = mat.cols();
41 VectorType r = rhs - mat * x;
42 VectorType r0 = r;
43
44 RealScalar r0_norm = r0.stableNorm();
45 RealScalar r_norm = r0_norm;
46 RealScalar rhs_norm = rhs.stableNorm();
47 if (rhs_norm == 0) {
48 x.setZero();
49 return true;
50 }
51
52 RealScalar tol = tol_error * rhs_norm;
53
54 Scalar rho(1);
55 Scalar alpha(0);
56 Scalar w(1);
57
58 VectorType v = VectorType::Zero(n), p = VectorType::Zero(n);
59 VectorType y(n), z(n);
60
61 VectorType s(n), t(n);
62
63 RealScalar eps = NumTraits<Scalar>::epsilon();
64 Index i = 0;
65 Index restarts = 0;
66
67 while (r_norm > tol && i < maxIters) {
68 Scalar rho_old = rho;
69 rho = r0.dot(r);
70 if (Eigen::numext::abs(rho) / Eigen::numext::maxi(r0_norm, r_norm) < eps * Eigen::numext::mini(r0_norm, r_norm)) {
71 // The new residual vector became too orthogonal to the arbitrarily chosen direction r0
72 // Let's restart with a new r0:
73 r.noalias() = rhs - mat * x;
74 r0 = r;
75 rho = r.squaredNorm();
76 r0_norm = r.stableNorm();
77 alpha = Scalar(0);
78 w = Scalar(1);
79 if (restarts++ == 0) i = 0;
80 }
81 Scalar beta = (rho / rho_old) * (alpha / w);
82 p = r + beta * (p - w * v);
83
84 y = precond.solve(p);
85
86 v.noalias() = mat * y;
87 Scalar theta = r0.dot(v);
88 // For small angles ∠(r0, v) < eps, random restart.
89 RealScalar v_norm = v.stableNorm();
90 if (Eigen::numext::abs(theta) / Eigen::numext::maxi(r0_norm, v_norm) < eps * Eigen::numext::mini(r0_norm, v_norm)) {
91 r.noalias() = rhs - mat * x;
92 r0.setRandom();
93 r0_norm = r0.stableNorm();
94 rho = Scalar(1);
95 alpha = Scalar(0);
96 w = Scalar(1);
97 if (restarts++ == 0) i = 0;
98 continue;
99 }
100 alpha = rho / theta;
101 s = r - alpha * v;
102
103 z = precond.solve(s);
104 t.noalias() = mat * z;
105
106 RealScalar tmp = t.squaredNorm();
107 if (tmp > RealScalar(0)) {
108 w = t.dot(s) / tmp;
109 } else {
110 w = Scalar(0);
111 }
112 x += alpha * y + w * z;
113 r = s - w * t;
114 r_norm = r.stableNorm();
115 ++i;
116 }
117
118 tol_error = r_norm / rhs_norm;
119 iters = i;
120 return true;
121}
122
123} // namespace internal
124
125template <typename MatrixType_, typename Preconditioner_ = DiagonalPreconditioner<typename MatrixType_::Scalar> >
126class BiCGSTAB;
127
128namespace internal {
129
130template <typename MatrixType_, typename Preconditioner_>
131struct traits<BiCGSTAB<MatrixType_, Preconditioner_> > {
132 using MatrixType = MatrixType_;
133 using Preconditioner = Preconditioner_;
134};
135
136} // namespace internal
137
169template <typename MatrixType_, typename Preconditioner_>
170class BiCGSTAB : public IterativeSolverBase<BiCGSTAB<MatrixType_, Preconditioner_> > {
171 protected:
173 using Base::m_error;
174 using Base::m_info;
175 using Base::m_isInitialized;
176 using Base::m_iterations;
177 using Base::matrix;
178
179 public:
180 using MatrixType = MatrixType_;
181 using Scalar = typename MatrixType::Scalar;
182 using RealScalar = typename MatrixType::RealScalar;
183 using Preconditioner = Preconditioner_;
184
185 public:
187 BiCGSTAB() : Base() {}
188
199 template <typename MatrixDerived>
200 explicit BiCGSTAB(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {}
201
203 template <typename Rhs, typename Dest>
204 void _solve_vector_with_guess_impl(const Rhs& b, Dest& x) const {
205 m_iterations = Base::maxIterations();
206 m_error = Base::m_tolerance;
207
208 bool ret = internal::bicgstab(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error);
209
210 m_info = (!ret) ? NumericalIssue : m_error <= Base::m_tolerance ? Success : NoConvergence;
211 }
212};
213
214} // end namespace Eigen
215
216#endif // EIGEN_BICGSTAB_H
A bi conjugate gradient stabilized solver for sparse square problems.
Definition BiCGSTAB.h:170
BiCGSTAB(const EigenBase< MatrixDerived > &A)
Definition BiCGSTAB.h:200
BiCGSTAB()
Definition BiCGSTAB.h:187
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