30#ifndef EIGEN_BICGSTABL_H
31#define EIGEN_BICGSTABL_H
34#include "./InternalHeaderCheck.h"
50template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
51bool bicgstabl(
const MatrixType &mat,
const Rhs &rhs, Dest &x,
const Preconditioner &precond, Index &iters,
52 typename Dest::RealScalar &tol_error, Index L) {
53 using RealScalar =
typename Dest::RealScalar;
54 using Scalar =
typename Dest::Scalar;
55 const Index N = rhs.size();
56 L = numext::mini(L, x.rows());
60 const RealScalar tol = tol_error;
61 const Index maxIters = iters;
63 using VectorType = Matrix<Scalar, Dynamic, 1>;
64 using DenseMatrixType = Matrix<Scalar, Dynamic, Dynamic, ColMajor>;
66 DenseMatrixType rHat(N, L + 1);
67 DenseMatrixType uHat(N, L + 1);
72 rHat.col(0).noalias() = rhs - mat * x0;
76 VectorType rShadow = VectorType::Random(N);
78 VectorType x_prime = x;
80 VectorType b_prime = rHat.col(0);
87 uHat.col(0).setZero();
89 bool bicg_convergence =
false;
91 const RealScalar normb = rhs.stableNorm();
92 if (normb == RealScalar(0)) {
97 RealScalar normr = rHat.col(0).stableNorm();
98 RealScalar Mx = normr;
99 RealScalar Mr = normr;
102 RealScalar normr_min = normr;
103 VectorType x_min = x_prime + x;
106 const RealScalar delta = 0.01;
108 bool compute_res =
false;
109 bool update_app =
false;
111 while (normr > tol * normb && k < maxIters) {
114 for (Index j = 0; j < L; ++j) {
115 const Scalar rho1 = rShadow.dot(rHat.col(j));
117 if (!(numext::isfinite)(rho1) || rho0 == RealScalar(0.0)) {
122 normr = (rhs - mat * (precond.solve(x) + x0)).stableNorm();
124 if (normr > normr_min || !(numext::isfinite)(normr)) {
129 tol_error = normr / normb;
132 x = precond.solve(x);
134 return (normr < tol * normb);
137 const Scalar beta = alpha * (rho1 / rho0);
140 uHat.leftCols(j + 1) = rHat.leftCols(j + 1) - beta * uHat.leftCols(j + 1);
141 uHat.col(j + 1).noalias() = mat * precond.solve(uHat.col(j));
142 const Scalar sigma = rShadow.dot(uHat.col(j + 1));
143 alpha = rho1 / sigma;
145 rHat.leftCols(j + 1) -= alpha * uHat.middleCols(1, j + 1);
146 rHat.col(j + 1).noalias() = mat * precond.solve(rHat.col(j));
148 x += alpha * uHat.col(0);
149 normr = rHat.col(0).stableNorm();
151 if (normr < tol * normb) {
158 bicg_convergence =
true;
160 }
else if (normr < normr_min) {
166 if (!bicg_convergence) {
175 const VectorType gamma = rHat.rightCols(L).householderQr().solve(rHat.col(0));
176 x.noalias() += rHat.leftCols(L) * gamma;
177 rHat.col(0).noalias() -= rHat.rightCols(L) * gamma;
178 uHat.col(0).noalias() -= uHat.rightCols(L) * gamma;
179 normr = rHat.col(0).stableNorm();
180 omega = gamma(L - 1);
182 if (normr < normr_min) {
202 Mx = numext::maxi(Mx, normr);
204 Mr = numext::maxi(Mr, normr);
206 if (normr < delta * normb && normb <= Mx) {
210 if (update_app || (normr < delta * Mr && normb <= Mr)) {
214 if (bicg_convergence) {
217 bicg_convergence =
false;
225 rHat.col(0).noalias() = b_prime - mat * precond.solve(x);
226 normr = rHat.col(0).stableNorm();
234 b_prime = rHat.col(0);
238 if (normr < normr_min) {
251 normr = (rhs - mat * (precond.solve(x) + x0)).stableNorm();
252 if (normr > normr_min || !(numext::isfinite)(normr)) {
257 tol_error = normr / normb;
261 x = precond.solve(x);
268template <
typename MatrixType_,
typename Preconditioner_ = DiagonalPreconditioner<
typename MatrixType_::Scalar>>
273template <
typename MatrixType_,
typename Preconditioner_>
274struct traits<Eigen::BiCGSTABL<MatrixType_, Preconditioner_>> {
275 using MatrixType = MatrixType_;
276 using Preconditioner = Preconditioner_;
281template <
typename MatrixType_,
typename Preconditioner_>
287 using Base::m_isInitialized;
288 using Base::m_iterations;
293 using MatrixType = MatrixType_;
294 using Scalar =
typename MatrixType::Scalar;
295 using RealScalar =
typename MatrixType::RealScalar;
296 using Preconditioner = Preconditioner_;
299 BiCGSTABL() =
default;
312 template <
typename MatrixDerived>
313 explicit BiCGSTABL(
const EigenBase<MatrixDerived> &A) : Base(A.derived()) {}
320 template <
typename Rhs,
typename Dest>
321 void _solve_vector_with_guess_impl(
const Rhs &b, Dest &x)
const {
323 m_iterations = max_iterations;
325 m_error = Base::m_tolerance;
327 bool ret = internal::bicgstabl(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error, m_L);
328 Index total_iterations = m_iterations;
331 while (ret && m_error > Base::m_tolerance && total_iterations < max_iterations) {
332 Index restart_iterations = max_iterations - total_iterations;
333 m_error = Base::m_tolerance;
334 ret = internal::bicgstabl(matrix(), b, x, Base::m_preconditioner, restart_iterations, m_error, m_L);
335 if (restart_iterations == 0)
break;
336 total_iterations += restart_iterations;
338 m_iterations = total_iterations;
345 eigen_assert(L >= 1 &&
"L needs to be positive");
Base class for linear iterative solvers.
Definition IterativeSolverBase.h:118
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