16#include "./InternalHeaderCheck.h"
35template <
typename Vector,
typename RealScalar>
36typename Vector::Scalar omega(
const Vector& t,
const Vector& s, RealScalar angle) {
38 typedef typename Vector::Scalar Scalar;
39 const RealScalar ns = s.stableNorm();
40 const RealScalar nt = t.stableNorm();
41 const Scalar ts = t.dot(s);
42 const RealScalar rho =
abs(ts / (nt * ns));
45 if (ts == Scalar(0)) {
52 return angle * (ns / nt) * (ts /
abs(ts));
54 return ts / (nt * nt);
57template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
58bool idrs(
const MatrixType& A,
const Rhs& b, Dest& x,
const Preconditioner& precond,
Index& iter,
59 typename Dest::RealScalar& relres,
Index S,
bool smoothing,
typename Dest::RealScalar angle,
61 typedef typename Dest::RealScalar RealScalar;
62 typedef typename Dest::Scalar Scalar;
63 typedef Matrix<Scalar, Dynamic, 1> VectorType;
64 typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> DenseMatrixType;
65 const Index N = b.size();
66 S = S < x.rows() ? S : x.rows();
67 const RealScalar tol = relres;
68 const Index maxit = iter;
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))) {
99 const RealScalar mp = RealScalar(1e3) * NumTraits<Scalar>::epsilon();
102 const RealScalar tolb = tol * normb;
103 VectorType r = b - A * x;
112 RealScalar normr = r.stableNorm();
117 relres = normr / normb;
121 DenseMatrixType G = DenseMatrixType::Zero(N, S);
122 DenseMatrixType U = DenseMatrixType::Zero(N, S);
123 DenseMatrixType M = DenseMatrixType::Identity(S, S);
124 VectorType t(N), v(N);
130 while (normr > tolb && iter < maxit) {
132 VectorType f = (r.adjoint() * P).adjoint();
134 for (
Index k = 0; k < S; ++k) {
137 lu_solver.compute(M.block(k, k, S - k, S - k));
138 VectorType c = lu_solver.solve(f.segment(k, S - k));
140 v = r - G.rightCols(S - k) * c;
142 v = precond.solve(v);
145 U.col(k) = U.rightCols(S - k) * c + om * v;
146 G.col(k) = A * U.col(k);
149 for (
Index i = 0; i < k - 1; ++i) {
151 Scalar alpha = P.col(i).dot(G.col(k)) / M(i, i);
152 G.col(k) = G.col(k) - alpha * G.col(i);
153 U.col(k) = U.col(k) - alpha * U.col(i);
158 M.block(k, k, S - k, 1) = (G.col(k).adjoint() * P.rightCols(S - k)).adjoint();
160 if (internal::isApprox(M(k, k), Scalar(0))) {
165 Scalar beta = f(k) / M(k, k);
166 r = r - beta * G.col(k);
167 x = x + beta * U.col(k);
168 normr = r.stableNorm();
170 if (replacement && normr > tolb / mp) {
178 Scalar gamma = t.dot(r_s) / t.stableNorm();
179 r_s = r_s - gamma * t;
180 x_s = x_s - gamma * (x_s - x);
181 normr = r_s.stableNorm();
184 if (normr < tolb || iter == maxit) {
190 f.segment(k + 1, S - (k + 1)) = f.segment(k + 1, S - (k + 1)) - beta * M.block(k + 1, k, S - (k + 1), 1);
194 if (normr < tolb || iter == maxit) {
202 v = precond.solve(v);
208 om = internal::omega(t, r, angle);
210 if (om == RealScalar(0.0)) {
216 normr = r.stableNorm();
218 if (replacement && normr > tolb / mp) {
223 if (trueres && normr < normb) {
231 Scalar gamma = t.dot(r_s) / t.stableNorm();
232 r_s = r_s - gamma * t;
233 x_s = x_s - gamma * (x_s - x);
234 normr = r_s.stableNorm();
244 relres = normr / normb;
250template <
typename MatrixType_,
typename Preconditioner_ = DiagonalPreconditioner<
typename MatrixType_::Scalar> >
255template <
typename MatrixType_,
typename Preconditioner_>
256struct traits<Eigen::IDRS<MatrixType_, Preconditioner_> > {
257 typedef MatrixType_ MatrixType;
258 typedef Preconditioner_ Preconditioner;
304template <
typename MatrixType_,
typename Preconditioner_>
307 typedef MatrixType_ MatrixType;
308 typedef typename MatrixType::Scalar Scalar;
309 typedef typename MatrixType::RealScalar RealScalar;
310 typedef Preconditioner_ Preconditioner;
316 using Base::m_isInitialized;
317 using Base::m_iterations;
326 IDRS() : m_S(4), m_smoothing(false), m_angle(RealScalar(0.7)), m_residual(false) {}
338 template <
typename MatrixDerived>
340 : Base(A.derived()), m_S(4), m_smoothing(false), m_angle(RealScalar(0.7)), m_residual(false) {}
347 template <
typename Rhs,
typename Dest>
350 m_error = Base::m_tolerance;
352 bool ret = internal::idrs(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error, m_S, m_smoothing, m_angle,
385 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:305
void setResidualUpdate(bool update)
Definition IDRS.h:390
IDRS()
Definition IDRS.h:326
IDRS(const EigenBase< MatrixDerived > &A)
Definition IDRS.h:339
void _solve_vector_with_guess_impl(const Rhs &b, Dest &x) const
Definition IDRS.h:348
void setSmoothing(bool smoothing)
Definition IDRS.h:373
void setS(Index S)
Definition IDRS.h:359
void setAngle(RealScalar angle)
Definition IDRS.h:385
Index maxIterations() const
Matrix< Type, Size, 1 > Vector
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