Warning, file /include/eigen3/unsupported/Eigen/src/IterativeSolvers/MINRES.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef EIGEN_MINRES_H_
0014 #define EIGEN_MINRES_H_
0015
0016
0017 namespace Eigen {
0018
0019 namespace internal {
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 template<typename MatrixType, typename Rhs, typename Dest, typename Preconditioner>
0031 EIGEN_DONT_INLINE
0032 void minres(const MatrixType& mat, const Rhs& rhs, Dest& x,
0033 const Preconditioner& precond, Index& iters,
0034 typename Dest::RealScalar& tol_error)
0035 {
0036 using std::sqrt;
0037 typedef typename Dest::RealScalar RealScalar;
0038 typedef typename Dest::Scalar Scalar;
0039 typedef Matrix<Scalar,Dynamic,1> VectorType;
0040
0041
0042 const RealScalar rhsNorm2(rhs.squaredNorm());
0043 if(rhsNorm2 == 0)
0044 {
0045 x.setZero();
0046 iters = 0;
0047 tol_error = 0;
0048 return;
0049 }
0050
0051
0052 const Index maxIters(iters);
0053 const Index N(mat.cols());
0054 const RealScalar threshold2(tol_error*tol_error*rhsNorm2);
0055
0056
0057 VectorType v_old(N);
0058 VectorType v( VectorType::Zero(N) );
0059 VectorType v_new(rhs-mat*x);
0060 RealScalar residualNorm2(v_new.squaredNorm());
0061 VectorType w(N);
0062 VectorType w_new(precond.solve(v_new));
0063
0064 RealScalar beta_new2(v_new.dot(w_new));
0065 eigen_assert(beta_new2 >= 0.0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE");
0066 RealScalar beta_new(sqrt(beta_new2));
0067 const RealScalar beta_one(beta_new);
0068
0069 RealScalar c(1.0);
0070 RealScalar c_old(1.0);
0071 RealScalar s(0.0);
0072 RealScalar s_old(0.0);
0073 VectorType p_oold(N);
0074 VectorType p_old(VectorType::Zero(N));
0075 VectorType p(p_old);
0076 RealScalar eta(1.0);
0077
0078 iters = 0;
0079 while ( iters < maxIters )
0080 {
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 const RealScalar beta(beta_new);
0092 v_old = v;
0093 v_new /= beta_new;
0094 w_new /= beta_new;
0095 v = v_new;
0096 w = w_new;
0097 v_new.noalias() = mat*w - beta*v_old;
0098 const RealScalar alpha = v_new.dot(w);
0099 v_new -= alpha*v;
0100 w_new = precond.solve(v_new);
0101 beta_new2 = v_new.dot(w_new);
0102 eigen_assert(beta_new2 >= 0.0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE");
0103 beta_new = sqrt(beta_new2);
0104
0105
0106 const RealScalar r2 =s*alpha+c*c_old*beta;
0107 const RealScalar r3 =s_old*beta;
0108 const RealScalar r1_hat=c*alpha-c_old*s*beta;
0109 const RealScalar r1 =sqrt( std::pow(r1_hat,2) + std::pow(beta_new,2) );
0110 c_old = c;
0111 s_old = s;
0112 c=r1_hat/r1;
0113 s=beta_new/r1;
0114
0115
0116 p_oold = p_old;
0117 p_old = p;
0118 p.noalias()=(w-r2*p_old-r3*p_oold) /r1;
0119 x += beta_one*c*eta*p;
0120
0121
0122
0123 residualNorm2 *= s*s;
0124
0125 if ( residualNorm2 < threshold2)
0126 {
0127 break;
0128 }
0129
0130 eta=-s*eta;
0131 iters++;
0132 }
0133
0134
0135
0136 tol_error = std::sqrt(residualNorm2 / rhsNorm2);
0137 }
0138
0139 }
0140
0141 template< typename _MatrixType, int _UpLo=Lower,
0142 typename _Preconditioner = IdentityPreconditioner>
0143 class MINRES;
0144
0145 namespace internal {
0146
0147 template< typename _MatrixType, int _UpLo, typename _Preconditioner>
0148 struct traits<MINRES<_MatrixType,_UpLo,_Preconditioner> >
0149 {
0150 typedef _MatrixType MatrixType;
0151 typedef _Preconditioner Preconditioner;
0152 };
0153
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194 template< typename _MatrixType, int _UpLo, typename _Preconditioner>
0195 class MINRES : public IterativeSolverBase<MINRES<_MatrixType,_UpLo,_Preconditioner> >
0196 {
0197
0198 typedef IterativeSolverBase<MINRES> Base;
0199 using Base::matrix;
0200 using Base::m_error;
0201 using Base::m_iterations;
0202 using Base::m_info;
0203 using Base::m_isInitialized;
0204 public:
0205 using Base::_solve_impl;
0206 typedef _MatrixType MatrixType;
0207 typedef typename MatrixType::Scalar Scalar;
0208 typedef typename MatrixType::RealScalar RealScalar;
0209 typedef _Preconditioner Preconditioner;
0210
0211 enum {UpLo = _UpLo};
0212
0213 public:
0214
0215
0216 MINRES() : Base() {}
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228 template<typename MatrixDerived>
0229 explicit MINRES(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {}
0230
0231
0232 ~MINRES(){}
0233
0234
0235 template<typename Rhs,typename Dest>
0236 void _solve_vector_with_guess_impl(const Rhs& b, Dest& x) const
0237 {
0238 typedef typename Base::MatrixWrapper MatrixWrapper;
0239 typedef typename Base::ActualMatrixType ActualMatrixType;
0240 enum {
0241 TransposeInput = (!MatrixWrapper::MatrixFree)
0242 && (UpLo==(Lower|Upper))
0243 && (!MatrixType::IsRowMajor)
0244 && (!NumTraits<Scalar>::IsComplex)
0245 };
0246 typedef typename internal::conditional<TransposeInput,Transpose<const ActualMatrixType>, ActualMatrixType const&>::type RowMajorWrapper;
0247 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(MatrixWrapper::MatrixFree,UpLo==(Lower|Upper)),MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY);
0248 typedef typename internal::conditional<UpLo==(Lower|Upper),
0249 RowMajorWrapper,
0250 typename MatrixWrapper::template ConstSelfAdjointViewReturnType<UpLo>::Type
0251 >::type SelfAdjointWrapper;
0252
0253 m_iterations = Base::maxIterations();
0254 m_error = Base::m_tolerance;
0255 RowMajorWrapper row_mat(matrix());
0256 internal::minres(SelfAdjointWrapper(row_mat), b, x,
0257 Base::m_preconditioner, m_iterations, m_error);
0258 m_info = m_error <= Base::m_tolerance ? Success : NoConvergence;
0259 }
0260
0261 protected:
0262
0263 };
0264
0265 }
0266
0267 #endif