QUDA  v1.1.0
A library for QCD on GPUs
eigensolve_quda.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <quda.h>
4 #include <quda_internal.h>
5 #include <dirac_quda.h>
6 #include <color_spinor_field.h>
7 
8 namespace quda
9 {
10 
11  // Local enum for the LU axpy block type
13 
15  {
16  using range = std::pair<int, int>;
17 
18  protected:
19  const DiracMatrix &mat;
22 
23  // Problem parameters
24  //------------------
25  int n_ev;
26  int n_kr;
27  int n_conv;
29  double tol;
30  bool reverse;
31  char spectrum[3];
33  // Algorithm variables
34  //--------------------
35  bool converged;
41  int iter;
44  int iter_keep;
47  int num_keep;
48 
49  std::vector<double> residua;
50 
51  // Device side vector workspace
52  std::vector<ColorSpinorField *> r;
53  std::vector<ColorSpinorField *> d_vecs_tmp;
54 
57 
59 
60  public:
67 
71  virtual ~EigenSolver();
72 
76  virtual bool hermitian() = 0;
77 
83  virtual void operator()(std::vector<ColorSpinorField *> &kSpace, std::vector<Complex> &evals) = 0;
84 
92 
98  void prepareInitialGuess(std::vector<ColorSpinorField *> &kSpace);
99 
105  void checkChebyOpMax(const DiracMatrix &mat, std::vector<ColorSpinorField *> &kSpace);
106 
112  void prepareKrylovSpace(std::vector<ColorSpinorField *> &kSpace, std::vector<Complex> &evals);
113 
119  double setEpsilon(const QudaPrecision prec);
120 
125  void queryPrec(const QudaPrecision prec);
126 
130  void printEigensolverSetup();
131 
137  void cleanUpEigensolver(std::vector<ColorSpinorField *> &kSpace, std::vector<Complex> &evals);
138 
146  void matVec(const DiracMatrix &mat, ColorSpinorField &out, const ColorSpinorField &in);
147 
155  void chebyOp(const DiracMatrix &mat, ColorSpinorField &out, const ColorSpinorField &in);
156 
165 
174  void blockOrthogonalize(std::vector<ColorSpinorField *> v, std::vector<ColorSpinorField *> &r, int j);
175 
181  void orthonormalizeMGS(std::vector<ColorSpinorField *> &v, int j);
182 
190  bool orthoCheck(std::vector<ColorSpinorField *> v, int j);
191 
202  void rotateVecs(std::vector<ColorSpinorField *> &kSpace, const double *rot_array, const int offset, const int dim,
203  const int keep, const int locked, TimeProfile &profile);
204 
215  void rotateVecsComplex(std::vector<ColorSpinorField *> &kSpace, const Complex *rot_array, const int offset,
216  const int dim, const int keep, const int locked, TimeProfile &profile);
217 
224  void permuteVecs(std::vector<ColorSpinorField *> &kSpace, int *mat, int size);
225 
239  void blockRotate(std::vector<ColorSpinorField *> &kSpace, double *array, int rank, const range &i, const range &j,
240  blockType b_type);
241 
255  void blockRotateComplex(std::vector<ColorSpinorField *> &kSpace, Complex *array, int rank, const range &i,
256  const range &j, blockType b_type, int offset);
257 
265  void blockReset(std::vector<ColorSpinorField *> &kSpace, int js, int je, int offset);
266 
275  void deflate(std::vector<ColorSpinorField *> &sol, const std::vector<ColorSpinorField *> &src,
276  const std::vector<ColorSpinorField *> &evecs, const std::vector<Complex> &evals,
277  bool accumulate = false) const;
278 
288  void deflate(ColorSpinorField &sol, const ColorSpinorField &src, const std::vector<ColorSpinorField *> &evecs,
289  const std::vector<Complex> &evals, bool accumulate = false)
290  {
291  // FIXME add support for mixed-precison dot product to avoid this copy
292  if (src.Precision() != evecs[0]->Precision() && !tmp1) {
293  ColorSpinorParam param(*evecs[0]);
295  }
296  ColorSpinorField *src_tmp = src.Precision() != evecs[0]->Precision() ? tmp1 : const_cast<ColorSpinorField *>(&src);
297  blas::copy(*src_tmp, src); // no-op if these alias
298  std::vector<ColorSpinorField *> src_ {src_tmp};
299  std::vector<ColorSpinorField *> sol_ {&sol};
300  deflate(sol_, src_, evecs, evals, accumulate);
301  }
302 
312  void deflateSVD(std::vector<ColorSpinorField *> &sol, const std::vector<ColorSpinorField *> &vec,
313  const std::vector<ColorSpinorField *> &evecs, const std::vector<Complex> &evals,
314  bool accumulate = false) const;
315 
325  void deflateSVD(ColorSpinorField &sol, const ColorSpinorField &src, const std::vector<ColorSpinorField *> &evecs,
326  const std::vector<Complex> &evals, bool accumulate = false)
327  {
328  // FIXME add support for mixed-precison dot product to avoid this copy
329  if (src.Precision() != evecs[0]->Precision() && !tmp1) {
330  ColorSpinorParam param(*evecs[0]);
332  }
333  ColorSpinorField *src_tmp = src.Precision() != evecs[0]->Precision() ? tmp1 : const_cast<ColorSpinorField *>(&src);
334  blas::copy(*src_tmp, src); // no-op if these alias
335  std::vector<ColorSpinorField *> src_ {src_tmp};
336  std::vector<ColorSpinorField *> sol_ {&sol};
337  deflateSVD(sol_, src_, evecs, evals, accumulate);
338  }
339 
346  void computeSVD(const DiracMatrix &mat, std::vector<ColorSpinorField *> &evecs, std::vector<Complex> &evals);
347 
355  void computeEvals(const DiracMatrix &mat, std::vector<ColorSpinorField *> &evecs, std::vector<Complex> &evals,
356  int size);
357 
364  void computeEvals(const DiracMatrix &mat, std::vector<ColorSpinorField *> &evecs, std::vector<Complex> &evals)
365  {
366  computeEvals(mat, evecs, evals, n_conv);
367  }
368 
375  void loadFromFile(const DiracMatrix &mat, std::vector<ColorSpinorField *> &eig_vecs, std::vector<Complex> &evals);
376 
384  void sortArrays(QudaEigSpectrumType spec_type, int n, std::vector<Complex> &x, std::vector<Complex> &y);
385 
394  void sortArrays(QudaEigSpectrumType spec_type, int n, std::vector<double> &x, std::vector<Complex> &y);
395 
404  void sortArrays(QudaEigSpectrumType spec_type, int n, std::vector<Complex> &x, std::vector<double> &y);
405 
415  void sortArrays(QudaEigSpectrumType spec_type, int n, std::vector<double> &x, std::vector<double> &y);
416  };
417 
421  class TRLM : public EigenSolver
422  {
423 
424  public:
432 
436  virtual ~TRLM();
437 
441  virtual bool hermitian() { return true; }
443  // Variable size matrix
444  std::vector<double> ritz_mat;
445 
446  // Tridiagonal/Arrow matrix, fixed size.
447  double *alpha;
448  double *beta;
449 
455  void operator()(std::vector<ColorSpinorField *> &kSpace, std::vector<Complex> &evals);
456 
462  void lanczosStep(std::vector<ColorSpinorField *> v, int j);
463 
468  void reorder(std::vector<ColorSpinorField *> &kSpace);
469 
473  void eigensolveFromArrowMat();
474 
479  void computeKeptRitz(std::vector<ColorSpinorField *> &kSpace);
480 
481  };
482 
486  class BLKTRLM : public TRLM
487  {
488  public:
496 
500  virtual ~BLKTRLM();
501 
502  virtual bool hermitian() { return true; }
504  // Variable size matrix
505  std::vector<Complex> block_ritz_mat;
506 
510 
513 
516 
522  void operator()(std::vector<ColorSpinorField *> &kSpace, std::vector<Complex> &evals);
523 
529  void blockLanczosStep(std::vector<ColorSpinorField *> v, int j);
530 
535 
541  void updateBlockBeta(int k, int arrow_offset);
542 
548  void computeBlockKeptRitz(std::vector<ColorSpinorField *> &kSpace);
549  };
550 
554  class IRAM : public EigenSolver
555  {
556 
557  public:
561 
569 
573  virtual bool hermitian() { return false; }
578  virtual ~IRAM();
579 
585  void operator()(std::vector<ColorSpinorField *> &kSpace, std::vector<Complex> &evals);
586 
594  void arnoldiStep(std::vector<ColorSpinorField *> &v, std::vector<ColorSpinorField *> &r, double &beta, int j);
595 
601  void eigensolveFromUpperHess(std::vector<Complex> &evals, const double beta);
602 
608  void rotateBasis(std::vector<ColorSpinorField *> &v, int keep);
609 
615  void qrShifts(const std::vector<Complex> evals, const int num_shifts);
616 
622  void qrIteration(Complex **Q, Complex **R);
623 
631  void reorder(std::vector<ColorSpinorField *> &kSpace, std::vector<Complex> &evals,
632  const QudaEigSpectrumType spec_type);
633  };
634 
650  void arpack_solve(std::vector<ColorSpinorField *> &h_evecs, std::vector<Complex> &h_evals, const DiracMatrix &mat,
651  QudaEigParam *eig_param, TimeProfile &profile);
652 
653 } // namespace quda
Block Thick Restarted Lanczos Method.
Complex * block_alpha
std::vector< Complex > block_ritz_mat
void operator()(std::vector< ColorSpinorField * > &kSpace, std::vector< Complex > &evals)
Compute eigenpairs.
Complex * block_beta
void eigensolveFromBlockArrowMat()
Get the eigendecomposition from the current block arrow matrix.
void computeBlockKeptRitz(std::vector< ColorSpinorField * > &kSpace)
Rotate the Ritz vectors usinng the arrow matrix eigendecomposition Uses a complex ritz matrix.
Complex * jth_block
virtual bool hermitian()
BLKTRLM(const DiracMatrix &mat, QudaEigParam *eig_param, TimeProfile &profile)
Constructor for Thick Restarted Eigensolver class.
void updateBlockBeta(int k, int arrow_offset)
Accumulate the R products of QR into the block beta array.
virtual ~BLKTRLM()
Destructor for Thick Restarted Eigensolver class.
void blockLanczosStep(std::vector< ColorSpinorField * > v, int j)
block lanczos step: extends the Krylov space in block step
static ColorSpinorField * Create(const ColorSpinorParam &param)
virtual void operator()(std::vector< ColorSpinorField * > &kSpace, std::vector< Complex > &evals)=0
Computes the eigen decomposition for the operator passed to create.
void blockOrthogonalize(std::vector< ColorSpinorField * > v, std::vector< ColorSpinorField * > &r, int j)
Orthogonalise input vectors r against vector space v using block-BLAS.
void blockReset(std::vector< ColorSpinorField * > &kSpace, int js, int je, int offset)
Copy temp part of kSpace, zero out for next use.
void matVec(const DiracMatrix &mat, ColorSpinorField &out, const ColorSpinorField &in)
Applies the specified matVec operation: M, Mdag, MMdag, MdagM.
void blockRotate(std::vector< ColorSpinorField * > &kSpace, double *array, int rank, const range &i, const range &j, blockType b_type)
Rotate part of kSpace.
bool orthoCheck(std::vector< ColorSpinorField * > v, int j)
Check orthonormality of input vector space v.
void deflateSVD(ColorSpinorField &sol, const ColorSpinorField &src, const std::vector< ColorSpinorField * > &evecs, const std::vector< Complex > &evals, bool accumulate=false)
Deflate a a given source vector with a given with a set of left and right singular vectors This is a ...
void rotateVecs(std::vector< ColorSpinorField * > &kSpace, const double *rot_array, const int offset, const int dim, const int keep, const int locked, TimeProfile &profile)
Rotate the Krylov space.
void deflate(std::vector< ColorSpinorField * > &sol, const std::vector< ColorSpinorField * > &src, const std::vector< ColorSpinorField * > &evecs, const std::vector< Complex > &evals, bool accumulate=false) const
Deflate a set of source vectors with a given eigenspace.
void prepareInitialGuess(std::vector< ColorSpinorField * > &kSpace)
Check for an initial guess. If none present, populate with rands, then orthonormalise.
TimeProfile & profile
void computeEvals(const DiracMatrix &mat, std::vector< ColorSpinorField * > &evecs, std::vector< Complex > &evals)
Compute eigenvalues and their residiua. This variant compute the number of converged eigenvalues.
void deflateSVD(std::vector< ColorSpinorField * > &sol, const std::vector< ColorSpinorField * > &vec, const std::vector< ColorSpinorField * > &evecs, const std::vector< Complex > &evals, bool accumulate=false) const
Deflate a set of source vectors with a set of left and right singular vectors.
void sortArrays(QudaEigSpectrumType spec_type, int n, std::vector< Complex > &x, std::vector< Complex > &y)
Sort array the first n elements of x according to spec_type, y comes along for the ride.
EigenSolver(const DiracMatrix &mat, QudaEigParam *eig_param, TimeProfile &profile)
Constructor for base Eigensolver class.
void orthonormalizeMGS(std::vector< ColorSpinorField * > &v, int j)
Orthonormalise input vector space v using Modified Gram-Schmidt.
const DiracMatrix & mat
virtual bool hermitian()=0
std::vector< ColorSpinorField * > r
void checkChebyOpMax(const DiracMatrix &mat, std::vector< ColorSpinorField * > &kSpace)
Check for a maximum of the Chebyshev operator.
double setEpsilon(const QudaPrecision prec)
Set the epsilon parameter.
QudaPrecision save_prec
void computeEvals(const DiracMatrix &mat, std::vector< ColorSpinorField * > &evecs, std::vector< Complex > &evals, int size)
Compute eigenvalues and their residiua.
void computeSVD(const DiracMatrix &mat, std::vector< ColorSpinorField * > &evecs, std::vector< Complex > &evals)
Computes Left/Right SVD from pre computed Right/Left.
ColorSpinorField * tmp2
void rotateVecsComplex(std::vector< ColorSpinorField * > &kSpace, const Complex *rot_array, const int offset, const int dim, const int keep, const int locked, TimeProfile &profile)
Rotate the Krylov space.
void permuteVecs(std::vector< ColorSpinorField * > &kSpace, int *mat, int size)
Permute the vector space using the permutation matrix.
double estimateChebyOpMax(const DiracMatrix &mat, ColorSpinorField &out, ColorSpinorField &in)
Estimate the spectral radius of the operator for the max value of the Chebyshev polynomial.
QudaEigParam * eig_param
void queryPrec(const QudaPrecision prec)
Query the eigensolver precision to stdout.
static EigenSolver * create(QudaEigParam *eig_param, const DiracMatrix &mat, TimeProfile &profile)
Creates the eigensolver using the parameters given and the matrix.
void prepareKrylovSpace(std::vector< ColorSpinorField * > &kSpace, std::vector< Complex > &evals)
Extend the Krylov space.
void deflate(ColorSpinorField &sol, const ColorSpinorField &src, const std::vector< ColorSpinorField * > &evecs, const std::vector< Complex > &evals, bool accumulate=false)
Deflate a given source vector with a given eigenspace. This is a wrapper variant for a single source ...
void loadFromFile(const DiracMatrix &mat, std::vector< ColorSpinorField * > &eig_vecs, std::vector< Complex > &evals)
Load and check eigenpairs from file.
void cleanUpEigensolver(std::vector< ColorSpinorField * > &kSpace, std::vector< Complex > &evals)
Release memory, save eigenvectors, resize the Krylov space to its original dimension.
std::vector< ColorSpinorField * > d_vecs_tmp
void blockRotateComplex(std::vector< ColorSpinorField * > &kSpace, Complex *array, int rank, const range &i, const range &j, blockType b_type, int offset)
Rotate part of kSpace.
ColorSpinorField * tmp1
void printEigensolverSetup()
Dump the eigensolver parameters to stdout.
void chebyOp(const DiracMatrix &mat, ColorSpinorField &out, const ColorSpinorField &in)
Promoted the specified matVec operation: M, Mdag, MMdag, MdagM to a Chebyshev polynomial.
std::vector< double > residua
Implicitly Restarted Arnoldi Method.
Complex ** Qmat
void rotateBasis(std::vector< ColorSpinorField * > &v, int keep)
Rotate the Krylov space.
Definition: eig_iram.cpp:125
IRAM(const DiracMatrix &mat, QudaEigParam *eig_param, TimeProfile &profile)
Constructor for Thick Restarted Eigensolver class.
Definition: eig_iram.cpp:19
virtual ~IRAM()
Destructor for Thick Restarted Eigensolver class.
Definition: eig_iram.cpp:587
Complex ** upperHess
void qrIteration(Complex **Q, Complex **R)
Apply One step of the the QR algorithm.
Definition: eig_iram.cpp:227
virtual bool hermitian()
void eigensolveFromUpperHess(std::vector< Complex > &evals, const double beta)
Get the eigendecomposition from the upper Hessenberg matrix via QR.
Definition: eig_iram.cpp:312
void arnoldiStep(std::vector< ColorSpinorField * > &v, std::vector< ColorSpinorField * > &r, double &beta, int j)
Arnoldi step: extends the Krylov space by one vector.
Definition: eig_iram.cpp:47
Complex ** Rmat
void reorder(std::vector< ColorSpinorField * > &kSpace, std::vector< Complex > &evals, const QudaEigSpectrumType spec_type)
Reorder the Krylov space and eigenvalues.
Definition: eig_iram.cpp:135
void operator()(std::vector< ColorSpinorField * > &kSpace, std::vector< Complex > &evals)
Compute eigenpairs.
Definition: eig_iram.cpp:432
void qrShifts(const std::vector< Complex > evals, const int num_shifts)
Apply shifts to the upper Hessenberg matrix via QR decomposition.
Definition: eig_iram.cpp:197
QudaPrecision Precision() const
Thick Restarted Lanczos Method.
std::vector< double > ritz_mat
void eigensolveFromArrowMat()
Get the eigendecomposition from the arrow matrix.
Definition: eig_trlm.cpp:276
virtual bool hermitian()
double * beta
double * alpha
void lanczosStep(std::vector< ColorSpinorField * > v, int j)
Lanczos step: extends the Krylov space.
Definition: eig_trlm.cpp:205
void computeKeptRitz(std::vector< ColorSpinorField * > &kSpace)
Rotate the Ritz vectors usinng the arrow matrix eigendecomposition.
Definition: eig_trlm.cpp:339
void operator()(std::vector< ColorSpinorField * > &kSpace, std::vector< Complex > &evals)
Compute eigenpairs.
Definition: eig_trlm.cpp:43
virtual ~TRLM()
Destructor for Thick Restarted Eigensolver class.
Definition: eig_trlm.cpp:195
TRLM(const DiracMatrix &mat, QudaEigParam *eig_param, TimeProfile &profile)
Constructor for Thick Restarted Eigensolver class.
Definition: eig_trlm.cpp:19
void reorder(std::vector< ColorSpinorField * > &kSpace)
Reorder the Krylov space by eigenvalue.
Definition: eig_trlm.cpp:249
std::array< int, 4 > dim
QudaPrecision prec
void mat(void *out, void **link, void *in, int dagger_bit, int mu, QudaPrecision sPrecision, QudaPrecision gPrecision)
enum QudaPrecision_s QudaPrecision
enum QudaEigSpectrumType_s QudaEigSpectrumType
void copy(ColorSpinorField &dst, const ColorSpinorField &src)
Definition: blas_quda.h:24
void arpack_solve(std::vector< ColorSpinorField * > &h_evecs, std::vector< Complex > &h_evals, const DiracMatrix &mat, QudaEigParam *eig_param, TimeProfile &profile)
The QUDA interface function. One passes two allocated arrays to hold the the eigenmode data,...
std::complex< double > Complex
Definition: quda_internal.h:86
QudaGaugeParam param
Definition: pack_test.cpp:18
Main header file for the QUDA library.