39#ifndef EIGEN_IDRSTABL_H
40#define EIGEN_IDRSTABL_H
43#include "./InternalHeaderCheck.h"
49template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
50bool idrstabl(
const MatrixType &mat,
const Rhs &rhs, Dest &x,
const Preconditioner &precond, Index &iters,
51 typename Dest::RealScalar &tol_error, Index L, Index S) {
56 using Scalar =
typename Dest::Scalar;
57 using RealScalar =
typename Dest::RealScalar;
58 using VectorType = Matrix<Scalar, Dynamic, 1>;
59 using DenseMatrixType = Matrix<Scalar, Dynamic, Dynamic, ColMajor>;
61 const Index N = x.rows();
64 const Index maxIters = iters;
66 const RealScalar rhs_norm = rhs.stableNorm();
67 const RealScalar tol = tol_error * rhs_norm;
79 FullPivLU<DenseMatrixType> lu_solver;
81 if (S >= N || L >= N) {
86 lu_solver.compute(DenseMatrixType(mat));
87 x = lu_solver.solve(rhs);
88 tol_error = (rhs - mat * x).stableNorm() / rhs_norm;
93 DenseMatrixType u(N, L + 1);
94 DenseMatrixType r(N, L + 1);
96 DenseMatrixType V(N * (L + 1), S);
100 VectorType update(N);
107 r.col(0).noalias() = rhs - mat * x;
110 tol_error = r.col(0).stableNorm();
113 DenseMatrixType h_FOM = DenseMatrixType::Zero(S, S - 1);
116 DenseMatrixType U(N * (L + 1), S);
117 for (Index col_index = 0; col_index < S; ++col_index) {
122 if (col_index != 0) {
126 VectorType w = mat * precond.solve(u.col(0));
127 for (Index i = 0; i < col_index; ++i) {
128 auto v = U.col(i).head(N);
129 h_FOM(i, col_index - 1) = v.dot(w);
130 w -= h_FOM(i, col_index - 1) * v;
133 h_FOM(col_index, col_index - 1) = u.col(0).stableNorm();
135 if (abs(h_FOM(col_index, col_index - 1)) != RealScalar(0)) {
160 u.col(0) /= h_FOM(col_index, col_index - 1);
164 u.col(0).normalize();
167 U.col(col_index).head(N) = u.col(0);
172 Scalar beta = r.col(0).stableNorm();
173 VectorType e1 = VectorType::Zero(S - 1);
175 lu_solver.compute(h_FOM.topLeftCorner(S - 1, S - 1));
176 VectorType y = lu_solver.solve(e1);
177 VectorType x2 = x + U.topLeftCorner(N, S - 1) * y;
181 RealScalar FOM_residual = (h_FOM(S - 1, S - 2) * y(S - 2) * U.col(S - 1).head(N)).stableNorm();
183 if (FOM_residual < tol) {
187 x = precond.solve(x2);
190 tol_error = FOM_residual / rhs_norm;
207 DenseMatrixType R_T = internal::random_orthonormal_basis<DenseMatrixType>(N, S).adjoint();
208 DenseMatrixType AR_T = DenseMatrixType(R_T * mat);
211 DenseMatrixType sigma(S, S);
213 bool reset_while =
false;
215 while (k < maxIters) {
216 for (Index j = 1; j <= L; ++j) {
221 for (Index i = 0; i < S; ++i) {
222 sigma.col(i).noalias() = AR_T * precond.solve(U.block(N * (j - 1), i, N, 1));
225 lu_solver.compute(sigma);
229 alpha = lu_solver.solve(R_T * r.col(0));
232 alpha = lu_solver.solve(AR_T * precond.solve(r.col(j - 2)));
236 update.noalias() = U.topRows(N) * alpha;
237 r.col(0).noalias() -= mat * precond.solve(update);
240 for (Index i = 1; i <= j - 2; ++i) {
242 r.col(i).noalias() -= U.block(N * (i + 1), 0, N, S) * alpha;
246 r.col(j - 1).noalias() = mat * precond.solve(r.col(j - 2));
248 tol_error = r.col(0).stableNorm();
250 if (tol_error < tol) {
256 bool break_normalization =
false;
257 for (Index q = 1; q <= S; ++q) {
260 u.leftCols(j + 1) = r.leftCols(j + 1);
263 u.leftCols(j) = u.middleCols(1, j);
268 u.leftCols(j).reshaped() -= U.topRows(N * j) * lu_solver.solve(AR_T * precond.solve(u.col(j - 1)));
271 u.col(j).noalias() = mat * precond.solve(u.col(j - 1));
282 for (Index i = 0; i <= q - 2; ++i) {
283 auto v = V.col(i).segment(N * j, N);
284 Scalar h = v.squaredNorm();
285 h = v.dot(u.col(j)) / h;
286 u.leftCols(j + 1).reshaped() -= h * V.col(i).head(N * (j + 1));
290 Scalar normalization_constant = u.col(j).stableNorm();
293 if (normalization_constant == RealScalar(0.0)) {
294 break_normalization =
true;
297 u.leftCols(j + 1) /= normalization_constant;
300 V.col(q - 1).head(N * (j + 1)) = u.leftCols(j + 1).reshaped();
303 if (!break_normalization) {
312 r.col(L).noalias() = mat * precond.solve(r.col(L - 1));
317 ColPivHouseholderQR<DenseMatrixType> qr_solver(r.rightCols(L));
318 gamma = qr_solver.solve(r.col(0));
321 update.noalias() = r.leftCols(L) * gamma;
323 r.col(0).noalias() -= mat * precond.solve(update);
327 tol_error = r.col(0).stableNorm();
329 if (tol_error < tol) {
342 for (Index i = 1; i <= L; ++i) {
343 U.topRows(N) -= U.block(N * i, 0, N, S) * gamma(i - 1);
352 x = precond.solve(x);
355 tol_error = tol_error / rhs_norm;
361template <
typename MatrixType_,
typename Preconditioner_ = DiagonalPreconditioner<
typename MatrixType_::Scalar>>
366template <
typename MatrixType_,
typename Preconditioner_>
367struct traits<IDRSTABL<MatrixType_, Preconditioner_>> {
368 using MatrixType = MatrixType_;
369 using Preconditioner = Preconditioner_;
413template <
typename MatrixType_,
typename Preconditioner_>
419 using Base::m_isInitialized;
420 using Base::m_iterations;
426 using MatrixType = MatrixType_;
427 using Scalar =
typename MatrixType::Scalar;
428 using RealScalar =
typename MatrixType::RealScalar;
429 using Preconditioner = Preconditioner_;
445 template <
typename MatrixDerived>
454 template <
typename Rhs,
typename Dest>
457 m_error = Base::m_tolerance;
458 bool ret = internal::idrstabl(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error, m_L, m_S);
466 eigen_assert(L >= 1 &&
"L needs to be positive");
472 eigen_assert(S >= 1 &&
"S needs to be positive");
The IDR(s)STAB(l) is a combination of IDR(s) and BiCGSTAB(l). It is a short-recurrences Krylov method...
Definition IDRSTABL.h:414
void setL(Index L)
Definition IDRSTABL.h:465
void setS(Index S)
Definition IDRSTABL.h:471
IDRSTABL(const EigenBase< MatrixDerived > &A)
Definition IDRSTABL.h:446
void _solve_vector_with_guess_impl(const Rhs &b, Dest &x) const
Definition IDRSTABL.h:455
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