29#ifndef EIGEN_BICGSTABL_H
30#define EIGEN_BICGSTABL_H
46template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
47bool bicgstabl(
const MatrixType &mat,
const Rhs &rhs, Dest &x,
const Preconditioner &precond,
Index &iters,
48 typename Dest::RealScalar &tol_error,
Index L) {
51 typedef typename Dest::RealScalar RealScalar;
52 typedef typename Dest::Scalar Scalar;
53 const Index N = rhs.size();
54 L = L < x.rows() ? L : x.rows();
58 const RealScalar tol = tol_error;
59 const Index maxIters = iters;
61 typedef Matrix<Scalar, Dynamic, 1> VectorType;
62 typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> DenseMatrixType;
64 DenseMatrixType rHat(N, L + 1);
65 DenseMatrixType uHat(N, L + 1);
70 rHat.col(0) = rhs - mat * x0;
74 VectorType rShadow = VectorType::Random(N);
76 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 (internal::isApprox(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) = 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) = 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 += rHat.leftCols(L) * gamma;
177 rHat.col(0) -= rHat.rightCols(L) * gamma;
178 uHat.col(0) -= 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) = 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 typedef MatrixType_ MatrixType;
276 typedef Preconditioner_ Preconditioner;
281template <
typename MatrixType_,
typename Preconditioner_>
286 using Base::m_isInitialized;
287 using Base::m_iterations;
292 typedef MatrixType_ MatrixType;
293 typedef typename MatrixType::Scalar Scalar;
294 typedef typename MatrixType::RealScalar RealScalar;
295 typedef Preconditioner_ Preconditioner;
298 BiCGSTABL() : m_L(2) {}
311 template <
typename MatrixDerived>
312 explicit BiCGSTABL(
const EigenBase<MatrixDerived> &A) : Base(A.derived()), m_L(2) {}
319 template <
typename Rhs,
typename Dest>
320 void _solve_vector_with_guess_impl(
const Rhs &b, Dest &x)
const {
323 m_error = Base::m_tolerance;
325 bool ret = internal::bicgstabl(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error, m_L);
332 eigen_assert(L >= 1 &&
"L needs to be positive");
Index maxIterations() const
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index