38#ifndef EIGEN_IDRSTABL_H
39#define EIGEN_IDRSTABL_H
45template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
46bool idrstabl(
const MatrixType &mat,
const Rhs &rhs, Dest &x,
const Preconditioner &precond,
Index &iters,
47 typename Dest::RealScalar &tol_error,
Index L,
Index S) {
53 typedef typename Dest::Scalar Scalar;
54 typedef typename Dest::RealScalar RealScalar;
55 typedef Matrix<Scalar, Dynamic, 1> VectorType;
56 typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> DenseMatrixType;
58 const Index N = x.rows();
61 const Index maxIters = iters;
63 const RealScalar rhs_norm = rhs.stableNorm();
64 const RealScalar tol = tol_error * rhs_norm;
76 FullPivLU<DenseMatrixType> lu_solver;
78 if (S >= N || L >= N) {
83 lu_solver.compute(DenseMatrixType(mat));
84 x = lu_solver.solve(rhs);
85 tol_error = (rhs - mat * x).stableNorm() / rhs_norm;
90 DenseMatrixType u(N, L + 1);
91 DenseMatrixType r(N, L + 1);
93 DenseMatrixType V(N * (L + 1), S);
104 r.col(0) = rhs - mat * x;
107 tol_error = r.col(0).stableNorm();
110 DenseMatrixType h_FOM = DenseMatrixType::Zero(S, S - 1);
113 DenseMatrixType U(N * (L + 1), S);
114 for (
Index col_index = 0; col_index < S; ++col_index) {
119 if (col_index != 0) {
123 VectorType w = mat * precond.solve(u.col(0));
124 for (
Index i = 0; i < col_index; ++i) {
125 auto v = U.col(i).head(N);
126 h_FOM(i, col_index - 1) = v.dot(w);
127 w -= h_FOM(i, col_index - 1) * v;
130 h_FOM(col_index, col_index - 1) = u.col(0).stableNorm();
132 if (
abs(h_FOM(col_index, col_index - 1)) != RealScalar(0)) {
157 u.col(0) /= h_FOM(col_index, col_index - 1);
161 u.col(0).normalize();
164 U.col(col_index).head(N) = u.col(0);
169 Scalar beta = r.col(0).stableNorm();
170 VectorType e1 = VectorType::Zero(S - 1);
172 lu_solver.compute(h_FOM.topLeftCorner(S - 1, S - 1));
173 VectorType y = lu_solver.solve(e1);
174 VectorType x2 = x + U.topLeftCorner(N, S - 1) * y;
178 RealScalar FOM_residual = (h_FOM(S - 1, S - 2) * y(S - 2) * U.col(S - 1).head(N)).stableNorm();
180 if (FOM_residual < tol) {
184 x = precond.solve(x2);
187 tol_error = FOM_residual / rhs_norm;
204 const HouseholderQR<DenseMatrixType> qr(DenseMatrixType::Random(N, S));
205 DenseMatrixType R_T = (qr.householderQ() * DenseMatrixType::Identity(N, S)).adjoint();
206 DenseMatrixType AR_T = DenseMatrixType(R_T * mat);
209 DenseMatrixType sigma(S, S);
211 bool reset_while =
false;
213 while (k < maxIters) {
214 for (
Index j = 1; j <= L; ++j) {
219 for (
Index i = 0; i < S; ++i) {
220 sigma.col(i).noalias() = AR_T * precond.solve(U.block(N * (j - 1), i, N, 1));
223 lu_solver.compute(sigma);
227 alpha.noalias() = lu_solver.solve(R_T * r.col(0));
230 alpha.noalias() = lu_solver.solve(AR_T * precond.solve(r.col(j - 2)));
234 update.noalias() = U.topRows(N) * alpha;
235 r.col(0) -= mat * precond.solve(update);
238 for (
Index i = 1; i <= j - 2; ++i) {
240 r.col(i) -= U.block(N * (i + 1), 0, N, S) * alpha;
244 r.col(j - 1).noalias() = mat * precond.solve(r.col(j - 2));
246 tol_error = r.col(0).stableNorm();
248 if (tol_error < tol) {
254 bool break_normalization =
false;
255 for (
Index q = 1; q <= S; ++q) {
258 u.leftCols(j + 1) = r.leftCols(j + 1);
261 u.leftCols(j) = u.middleCols(1, j);
266 u.reshaped().head(u.rows() * j) -= U.topRows(N * j) * lu_solver.solve(AR_T * precond.solve(u.col(j - 1)));
269 u.col(j).noalias() = mat * precond.solve(u.col(j - 1));
280 for (
Index i = 0; i <= q - 2; ++i) {
281 auto v = V.col(i).segment(N * j, N);
282 Scalar h = v.squaredNorm();
283 h = v.dot(u.col(j)) / h;
284 u.reshaped().head(u.rows() * (j + 1)) -= h * V.block(0, i, N * (j + 1), 1);
288 Scalar normalization_constant = u.col(j).stableNorm();
291 if (normalization_constant == RealScalar(0.0)) {
292 break_normalization =
true;
295 u.leftCols(j + 1) /= normalization_constant;
298 V.block(0, q - 1, N * (j + 1), 1).noalias() = u.reshaped().head(u.rows() * (j + 1));
301 if (break_normalization ==
false) {
310 r.col(L).noalias() = mat * precond.solve(r.col(L - 1));
315 ColPivHouseholderQR<DenseMatrixType> qr_solver(r.rightCols(L));
316 gamma.noalias() = qr_solver.solve(r.col(0));
319 update.noalias() = r.leftCols(L) * gamma;
321 r.col(0) -= mat * precond.solve(update);
325 tol_error = r.col(0).stableNorm();
327 if (tol_error < tol) {
340 for (
Index i = 1; i <= L; ++i) {
341 U.topRows(N) -= U.block(N * i, 0, N, S) * gamma(i - 1);
350 x = precond.solve(x);
353 tol_error = tol_error / rhs_norm;
359template <
typename MatrixType_,
typename Preconditioner_ = DiagonalPreconditioner<
typename MatrixType_::Scalar>>
364template <
typename MatrixType_,
typename Preconditioner_>
365struct traits<IDRSTABL<MatrixType_, Preconditioner_>> {
366 typedef MatrixType_ MatrixType;
367 typedef Preconditioner_ Preconditioner;
411template <
typename MatrixType_,
typename Preconditioner_>
416 using Base::m_isInitialized;
417 using Base::m_iterations;
423 typedef MatrixType_ MatrixType;
424 typedef typename MatrixType::Scalar Scalar;
425 typedef typename MatrixType::RealScalar RealScalar;
426 typedef Preconditioner_ Preconditioner;
442 template <
typename MatrixDerived>
451 template <
typename Rhs,
typename Dest>
454 m_error = Base::m_tolerance;
455 bool ret = internal::idrstabl(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error, m_L, m_S);
463 eigen_assert(L >= 1 &&
"L needs to be positive");
469 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:412
void setL(Index L)
Definition IDRSTABL.h:462
IDRSTABL()
Definition IDRSTABL.h:430
void setS(Index S)
Definition IDRSTABL.h:468
IDRSTABL(const EigenBase< MatrixDerived > &A)
Definition IDRSTABL.h:443
void _solve_vector_with_guess_impl(const Rhs &b, Dest &x) const
Definition IDRSTABL.h:452
Index maxIterations() const
Namespace containing all symbols from the Eigen library.
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index