17#include "./InternalHeaderCheck.h"
36template <
typename Vector,
typename RealScalar>
37typename Vector::Scalar omega(
const Vector& t,
const Vector& s, RealScalar angle) {
39 using Scalar =
typename Vector::Scalar;
40 const RealScalar ns = s.stableNorm();
41 const RealScalar nt = t.stableNorm();
42 const Scalar ts = t.dot(s);
43 const RealScalar rho = abs(ts / (nt * ns));
46 if (ts == Scalar(0)) {
53 return angle * (ns / nt) * (ts / abs(ts));
55 return ts / (nt * nt);
58template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
59bool idrs(
const MatrixType& A,
const Rhs& b, Dest& x,
const Preconditioner& precond, Index& iter,
60 typename Dest::RealScalar& relres, Index S,
bool smoothing,
typename Dest::RealScalar angle,
62 using RealScalar =
typename Dest::RealScalar;
63 using Scalar =
typename Dest::Scalar;
64 using VectorType = Matrix<Scalar, Dynamic, 1>;
65 using DenseMatrixType = Matrix<Scalar, Dynamic, Dynamic, ColMajor>;
66 const Index N = b.size();
67 S = numext::mini(S, x.rows());
68 const RealScalar tol = relres;
69 const Index maxit = iter;
73 FullPivLU<DenseMatrixType> lu_solver;
75 DenseMatrixType P = internal::random_orthonormal_basis<DenseMatrixType>(N, S);
77 const RealScalar normb = b.stableNorm();
79 if (normb == RealScalar(0)) {
96 const RealScalar mp = RealScalar(1e3) * NumTraits<Scalar>::epsilon();
99 const RealScalar tolb = tol * normb;
100 VectorType r = b - A * x;
109 RealScalar normr = r.stableNorm();
114 relres = normr / normb;
118 DenseMatrixType G = DenseMatrixType::Zero(N, S);
119 DenseMatrixType U = DenseMatrixType::Zero(N, S);
120 DenseMatrixType M = DenseMatrixType::Identity(S, S);
121 VectorType t(N), v(N);
127 while (normr > tolb && iter < maxit) {
129 VectorType f = (r.adjoint() * P).adjoint();
131 for (Index k = 0; k < S; ++k) {
134 lu_solver.compute(M.block(k, k, S - k, S - k));
135 VectorType c = lu_solver.solve(f.segment(k, S - k));
137 v.noalias() = r - G.rightCols(S - k) * c;
139 v = precond.solve(v);
142 U.col(k) = U.rightCols(S - k) * c + om * v;
143 G.col(k).noalias() = A * U.col(k);
146 for (Index i = 0; i < k - 1; ++i) {
148 Scalar alpha = P.col(i).dot(G.col(k)) / M(i, i);
149 G.col(k) = G.col(k) - alpha * G.col(i);
150 U.col(k) = U.col(k) - alpha * U.col(i);
155 M.block(k, k, S - k, 1) = (G.col(k).adjoint() * P.rightCols(S - k)).adjoint();
157 if (M(k, k) == Scalar(0)) {
162 Scalar beta = f(k) / M(k, k);
163 r = r - beta * G.col(k);
164 x = x + beta * U.col(k);
165 normr = r.stableNorm();
167 if (replacement && normr > tolb / mp) {
175 Scalar gamma = t.dot(r_s) / t.stableNorm();
176 r_s = r_s - gamma * t;
177 x_s = x_s - gamma * (x_s - x);
178 normr = r_s.stableNorm();
181 if (normr < tolb || iter == maxit) {
187 f.segment(k + 1, S - (k + 1)) = f.segment(k + 1, S - (k + 1)) - beta * M.block(k + 1, k, S - (k + 1), 1);
191 if (normr < tolb || iter == maxit) {
199 v = precond.solve(v);
205 om = internal::omega(t, r, angle);
207 if (om == RealScalar(0.0)) {
213 normr = r.stableNorm();
215 if (replacement && normr > tolb / mp) {
220 if (trueres && normr < normb) {
221 r.noalias() = b - A * x;
228 Scalar gamma = t.dot(r_s) / t.stableNorm();
229 r_s = r_s - gamma * t;
230 x_s = x_s - gamma * (x_s - x);
231 normr = r_s.stableNorm();
241 relres = normr / normb;
247template <
typename MatrixType_,
typename Preconditioner_ = DiagonalPreconditioner<
typename MatrixType_::Scalar> >
252template <
typename MatrixType_,
typename Preconditioner_>
253struct traits<Eigen::IDRS<MatrixType_, Preconditioner_> > {
254 using MatrixType = MatrixType_;
255 using Preconditioner = Preconditioner_;
301template <
typename MatrixType_,
typename Preconditioner_>
304 using MatrixType = MatrixType_;
305 using Scalar =
typename MatrixType::Scalar;
306 using RealScalar =
typename MatrixType::RealScalar;
307 using Preconditioner = Preconditioner_;
313 using Base::m_isInitialized;
314 using Base::m_iterations;
317 bool m_smoothing =
false;
318 RealScalar m_angle = RealScalar(0.7);
319 bool m_residual =
false;
335 template <
typename MatrixDerived>
343 template <
typename Rhs,
typename Dest>
346 m_error = Base::m_tolerance;
348 bool ret = internal::idrs(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error, m_S, m_smoothing, m_angle,
381 void setAngle(RealScalar angle) { m_angle = angle; }
The Induced Dimension Reduction method (IDR(s)) is a short-recurrences Krylov method for sparse squar...
Definition IDRS.h:302
void setResidualUpdate(bool update)
Definition IDRS.h:386
IDRS(const EigenBase< MatrixDerived > &A)
Definition IDRS.h:336
void _solve_vector_with_guess_impl(const Rhs &b, Dest &x) const
Definition IDRS.h:344
void setSmoothing(bool smoothing)
Definition IDRS.h:369
void setS(Index S)
Definition IDRS.h:355
void setAngle(RealScalar angle)
Definition IDRS.h:381
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
Matrix< Type, Size, 1 > Vector
Size×1 vector of type Type.
Definition Matrix.h:532
Definition EigenBase.h:34