ARPACK-Armadillo
SymEigsSolver.h
1 // Copyright (C) 2015 Yixuan Qiu
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef SYM_EIGS_SOLVER_H
8 #define SYM_EIGS_SOLVER_H
9 
10 #include <armadillo>
11 #include <vector> // std::vector
12 #include <cmath> // std::abs, std::pow, std::sqrt
13 #include <algorithm> // std::max, std::min
14 #include <limits> // std::numeric_limits
15 #include <stdexcept> // std::invalid_argument
16 
17 #include "SelectionRule.h"
18 #include "LinAlg/UpperHessenbergQR.h"
19 #include "LinAlg/TridiagEigen.h"
20 #include "MatOp/DenseGenMatProd.h"
21 #include "MatOp/DenseSymShiftSolve.h"
22 
23 
29 
137 template < typename Scalar = double,
138  int SelectionRule = LARGEST_MAGN,
139  typename OpType = DenseGenMatProd<double> >
141 {
142 private:
143  typedef arma::Mat<Scalar> Matrix;
144  typedef arma::Col<Scalar> Vector;
145  typedef arma::uvec BoolVector;
146 
147 protected:
148  OpType *op; // object to conduct matrix operation,
149  // e.g. matrix-vector product
150 
151 private:
152  const int dim_n; // dimension of matrix A
153 
154 protected:
155  const int nev; // number of eigenvalues requested
156 
157 private:
158  const int ncv; // number of ritz values
159  int nmatop; // number of matrix operations called
160  int niter; // number of restarting iterations
161 
162  Matrix fac_V; // V matrix in the Arnoldi factorization
163  Matrix fac_H; // H matrix in the Arnoldi factorization
164  Vector fac_f; // residual in the Arnoldi factorization
165 
166 protected:
167  Vector ritz_val; // ritz values
168 
169 private:
170  Matrix ritz_vec; // ritz vectors
171  BoolVector ritz_conv; // indicator of the convergence of ritz values
172 
173  const Scalar prec; // precision parameter used to test convergence
174  // prec = epsilon^(2/3)
175  // epsilon is the machine precision,
176  // e.g. ~= 1e-16 for the "double" type
177 
178  // Arnoldi factorization starting from step-k
179  inline void factorize_from(int from_k, int to_m, const Vector &fk);
180 
181  // Implicitly restarted Arnoldi factorization
182  inline void restart(int k);
183 
184  // Calculate the number of converged Ritz values
185  inline int num_converged(Scalar tol);
186 
187  // Return the adjusted nev for restarting
188  inline int nev_adjusted(int nconv);
189 
190  // Retrieve and sort ritz values and ritz vectors
191  inline void retrieve_ritzpair();
192 
193 protected:
194  // Sort the first nev Ritz pairs in decreasing magnitude order
195  // This is used to return the final results
196  inline virtual void sort_ritzpair();
197 
198 public:
216  SymEigsSolver(OpType *op_, int nev_, int ncv_) :
217  op(op_),
218  dim_n(op->rows()),
219  nev(nev_),
220  ncv(ncv_ > dim_n ? dim_n : ncv_),
221  nmatop(0),
222  niter(0),
223  prec(std::pow(std::numeric_limits<Scalar>::epsilon(), Scalar(2.0) / 3))
224  {
225  if(nev_ < 1 || nev_ > dim_n - 1)
226  throw std::invalid_argument("nev must satisfy 1 <= nev <= n - 1, n is the size of matrix");
227 
228  if(ncv_ <= nev_ || ncv_ > dim_n)
229  throw std::invalid_argument("ncv must satisfy nev < ncv <= n, n is the size of matrix");
230  }
231 
241  inline void init(Scalar *init_resid);
242 
250  inline void init();
251 
260  inline int compute(int maxit = 1000, Scalar tol = 1e-10);
261 
265  inline int num_iterations() { return niter; }
266 
270  inline int num_operations() { return nmatop; }
271 
279  inline Vector eigenvalues();
280 
290  inline Matrix eigenvectors(int nvec);
294  inline Matrix eigenvectors() { return eigenvectors(nev); }
295 };
296 
297 
298 // Implementations
299 #include "SymEigsSolver_Impl.h"
300 
301 
423 template <typename Scalar = double,
424  int SelectionRule = LARGEST_MAGN,
425  typename OpType = DenseSymShiftSolve<double> >
426 class SymEigsShiftSolver: public SymEigsSolver<Scalar, SelectionRule, OpType>
427 {
428 private:
429  typedef arma::Col<Scalar> Vector;
430 
431  Scalar sigma;
432 
433  // First transform back the ritz values, and then sort
434  inline void sort_ritzpair()
435  {
436  Vector ritz_val_org = Scalar(1.0) / this->ritz_val.head(this->nev) + sigma;
437  this->ritz_val.head(this->nev) = ritz_val_org;
439  }
440 public:
459  SymEigsShiftSolver(OpType *op_, int nev_, int ncv_, Scalar sigma_) :
460  SymEigsSolver<Scalar, SelectionRule, OpType>(op_, nev_, ncv_),
461  sigma(sigma_)
462  {
463  this->op->set_shift(sigma);
464  }
465 };
466 
467 
468 
469 #endif // SYM_EIGS_SOLVER_H
SymEigsSolver(OpType *op_, int nev_, int ncv_)
int num_operations()
SymEigsShiftSolver(OpType *op_, int nev_, int ncv_, Scalar sigma_)
int compute(int maxit=1000, Scalar tol=1e-10)
Matrix eigenvectors()
int num_iterations()