15 #include "./InternalHeaderCheck.h"
34 template <
typename Vector,
typename RealScalar>
38 const RealScalar ns = s.stableNorm();
39 const RealScalar nt = t.stableNorm();
40 const Scalar ts = t.dot(s);
41 const RealScalar rho =
abs(ts / (nt * ns));
44 if (ts == Scalar(0)) {
51 return angle * (ns / nt) * (ts /
abs(ts));
53 return ts / (nt * nt);
56 template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
57 bool idrs(
const MatrixType& A,
const Rhs& b, Dest& x,
const Preconditioner& precond,
Index& iter,
58 typename Dest::RealScalar& relres,
Index S,
bool smoothing,
typename Dest::RealScalar angle,
60 typedef typename Dest::RealScalar RealScalar;
61 typedef typename Dest::Scalar Scalar;
63 typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> DenseMatrixType;
64 const Index N = b.size();
65 S = S < x.rows() ? S : x.rows();
66 const RealScalar tol = relres;
67 const Index maxit = iter;
69 Index replacements = 0;
72 FullPivLU<DenseMatrixType> lu_solver;
76 HouseholderQR<DenseMatrixType> qr(DenseMatrixType::Random(N, S));
77 P = (qr.householderQ() * DenseMatrixType::Identity(N, S));
80 const RealScalar normb = b.stableNorm();
82 if (internal::isApprox(normb, RealScalar(0))) {
100 const RealScalar mp = RealScalar(1e3) * NumTraits<Scalar>::epsilon();
103 const RealScalar tolb = tol * normb;
104 VectorType r = b - A * x;
113 RealScalar normr = r.stableNorm();
118 relres = normr / normb;
122 DenseMatrixType G = DenseMatrixType::Zero(N, S);
123 DenseMatrixType U = DenseMatrixType::Zero(N, S);
124 DenseMatrixType M = DenseMatrixType::Identity(S, S);
125 VectorType t(N), v(N);
131 while (normr > tolb && iter < maxit) {
133 VectorType f = (r.adjoint() * P).adjoint();
135 for (
Index k = 0; k < S; ++k) {
138 lu_solver.compute(M.block(k, k, S - k, S - k));
139 VectorType c = lu_solver.solve(f.segment(k, S - k));
141 v = r - G.rightCols(S - k) * c;
143 v = precond.solve(v);
146 U.col(k) = U.rightCols(S - k) * c + om * v;
147 G.col(k) = A * U.col(k);
150 for (
Index i = 0; i < k - 1; ++i) {
152 Scalar alpha = P.col(i).dot(G.col(k)) / M(i, i);
153 G.col(k) = G.col(k) - alpha * G.col(i);
154 U.col(k) = U.col(k) - alpha * U.col(i);
159 M.block(k, k, S - k, 1) = (G.col(k).adjoint() * P.rightCols(S - k)).adjoint();
161 if (internal::isApprox(M(k, k), Scalar(0))) {
166 Scalar beta = f(k) / M(k, k);
167 r = r - beta * G.col(k);
168 x = x + beta * U.col(k);
169 normr = r.stableNorm();
171 if (replacement && normr > tolb / mp) {
179 Scalar gamma = t.dot(r_s) / t.stableNorm();
180 r_s = r_s - gamma * t;
181 x_s = x_s - gamma * (x_s - x);
182 normr = r_s.stableNorm();
185 if (normr < tolb || iter == maxit) {
191 f.segment(k + 1, S - (k + 1)) = f.segment(k + 1, S - (k + 1)) - beta * M.block(k + 1, k, S - (k + 1), 1);
195 if (normr < tolb || iter == maxit) {
203 v = precond.solve(v);
209 om = internal::omega(t, r, angle);
211 if (om == RealScalar(0.0)) {
217 normr = r.stableNorm();
219 if (replacement && normr > tolb / mp) {
224 if (trueres && normr < normb) {
233 Scalar gamma = t.dot(r_s) / t.stableNorm();
234 r_s = r_s - gamma * t;
235 x_s = x_s - gamma * (x_s - x);
236 normr = r_s.stableNorm();
246 relres = normr / normb;
252 template <
typename MatrixType_,
typename Preconditioner_ = DiagonalPreconditioner<
typename MatrixType_::Scalar> >
257 template <
typename MatrixType_,
typename Preconditioner_>
258 struct traits<
Eigen::IDRS<MatrixType_, Preconditioner_> > {
259 typedef MatrixType_ MatrixType;
260 typedef Preconditioner_ Preconditioner;
306 template <
typename MatrixType_,
typename Preconditioner_>
309 typedef MatrixType_ MatrixType;
310 typedef typename MatrixType::Scalar Scalar;
311 typedef typename MatrixType::RealScalar RealScalar;
312 typedef Preconditioner_ Preconditioner;
318 using Base::m_isInitialized;
319 using Base::m_iterations;
328 IDRS() : m_S(4), m_smoothing(false), m_angle(RealScalar(0.7)), m_residual(false) {}
340 template <
typename MatrixDerived>
342 :
Base(A.derived()), m_S(4), m_smoothing(false), m_angle(RealScalar(0.7)), m_residual(false) {}
349 template <
typename Rhs,
typename Dest>
352 m_error = Base::m_tolerance;
354 bool ret = internal::idrs(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error, m_S, m_smoothing, m_angle,
387 void setAngle(RealScalar angle) { m_angle = angle; }
internal::traits< Derived >::Scalar Scalar
The Induced Dimension Reduction method (IDR(s)) is a short-recurrences Krylov method for sparse squar...
Definition: IDRS.h:307
void setResidualUpdate(bool update)
Definition: IDRS.h:392
IDRS()
Definition: IDRS.h:328
IDRS(const EigenBase< MatrixDerived > &A)
Definition: IDRS.h:341
void _solve_vector_with_guess_impl(const Rhs &b, Dest &x) const
Definition: IDRS.h:350
void setSmoothing(bool smoothing)
Definition: IDRS.h:375
void setS(Index S)
Definition: IDRS.h:361
void setAngle(RealScalar angle)
Definition: IDRS.h:387
Index maxIterations() const
Matrix< Type, Size, 1 > Vector
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)