15 #include <Eigen/Eigenvalues> 16 #include <Eigen/Dense> 23 using namespace Eigen;
58 if (
nEv == 0)
errorQuda(
"nEv=0 passed to Eigensolver\n");
59 if (
nKr == 0)
errorQuda(
"nKr=0 passed to Eigensolver\n");
63 for (
int i = 0; i <
nKr; i++) {
residua[i] = 0.0; }
118 eig_solver =
new TRLM(eig_param, mat, profile);
120 default:
errorQuda(
"Invalid eig solver type");
151 double delta = (b - a) / 2.0;
152 double theta = (b + a) / 2.0;
153 double sigma1 = -delta / theta;
155 double d1 = sigma1 / delta;
162 blas::caxpby(d2, const_cast<ColorSpinorField &>(in), d1, out);
178 double sigma_old = sigma1;
182 sigma = 1.0 / (2.0 / sigma1 - sigma_old);
184 d1 = 2.0 * sigma / delta;
186 d3 = -sigma * sigma_old;
212 std::vector<ColorSpinorField *> vecs_ptr;
213 for (
int i = 0; i < j + 1; i++) { vecs_ptr.push_back(vecs[i]); }
218 for (
int i = 0; i < j + 1; i++) {
230 std::vector<ColorSpinorField *> eig_vecs, std::vector<Complex> evals)
242 std::vector<ColorSpinorField *> eig_vecs_ptr;
243 for (
int i = 0; i < n_defl; i++) eig_vecs_ptr.push_back(eig_vecs[i]);
250 for (
int i = 0; i < n_defl; i++) { s[i] /= evals[i].real(); }
269 if (evecs.size() != (
unsigned int)(2 * nConv))
270 errorQuda(
"Incorrect deflation space sized %d passed to computeSVD, expected %d", (
int)(evecs.size()), 2 * nConv);
274 for (
int i = 0; i <
nConv; i++) {
290 mat.
Expose()->
M(*evecs[nConv + i], *evecs[i]);
298 blas::ax(1.0 / norm, *evecs[nConv + i]);
301 printfQuda(
"Sval[%04d] = %+.16e %+.16e sigma - sqrt(|lambda|) = %+.16e\n", i, sigma_tmp[i].real(),
302 sigma_tmp[i].imag(), sigma_tmp[i].real() -
sqrt(
abs(lambda.real())));
303 evals[i] = sigma_tmp[i];
310 std::vector<ColorSpinorField *> eig_vecs, std::vector<Complex> evals)
321 std::vector<ColorSpinorField *> left_vecs_ptr;
322 for (
int i = n_defl; i < 2 * n_defl; i++) left_vecs_ptr.push_back(eig_vecs[i]);
330 std::vector<ColorSpinorField *> right_vecs_ptr;
331 for (
int i = 0; i < n_defl; i++) {
332 right_vecs_ptr.push_back(eig_vecs[i]);
333 s[i] /= evals[i].real();
346 std::vector<Complex> &evals,
int size)
348 for (
int i = 0; i <
size; i++) {
368 const int Nvec = eig_vecs.size();
369 if (strcmp(vec_infile.c_str(),
"") != 0) {
371 printfQuda(
"Start loading %04d vectors from %s\n", Nvec, vec_infile.c_str());
373 std::vector<ColorSpinorField *>
tmp;
378 eig_vecs[0]->Precision());
383 for (
int i = 0; i < Nvec; i++) { tmp.push_back(eig_vecs[i]); }
386 void **
V =
static_cast<void **
>(
safe_malloc(Nvec *
sizeof(
void *)));
387 for (
int i = 0; i < Nvec; i++) {
394 read_spinor_field(vec_infile.c_str(), &V[0], tmp[0]->Precision(), tmp[0]->X(), tmp[0]->Ncolor(), tmp[0]->Nspin(),
395 Nvec, 0, (
char **)0);
399 for (
int i = 0; i < Nvec; i++) {
400 *eig_vecs[i] = *tmp[i];
407 errorQuda(
"No eigenspace input file defined.");
410 errorQuda(
"\nQIO library was not built.\n");
422 const int Nvec = eig_vecs.size();
423 std::vector<ColorSpinorField *>
tmp;
428 eig_vecs[0]->Precision());
431 for (
int i = 0; i < Nvec; i++) {
433 *tmp[i] = *eig_vecs[i];
436 for (
int i = 0; i < Nvec; i++) { tmp.push_back(eig_vecs[i]); }
441 void **
V =
static_cast<void **
>(
safe_malloc(Nvec *
sizeof(
void *)));
442 for (
int i = 0; i < Nvec; i++) {
449 write_spinor_field(vec_outfile.c_str(), &V[0], tmp[0]->Precision(), tmp[0]->X(), tmp[0]->Ncolor(), tmp[0]->Nspin(),
450 Nvec, 0, (
char **)0);
455 for (
int i = 0; i < Nvec; i++)
delete tmp[i];
459 errorQuda(
"\nQIO library was not built.\n");
466 std::vector<Complex> &evals)
469 std::vector<ColorSpinorField *> vecs_ptr;
470 for (
int i = 0; i <
nConv; i++) { vecs_ptr.push_back(kSpace[i]); }
481 for (
int i = 0; i <
nConv; i++) {
483 printfQuda(
"EigValue[%04d]: (%+.16e, %+.16e) residual %.16e\n", i, evals[i].real(), evals[i].imag(),
residua[i]);
510 for (
int i = 0; i <
nKr; i++) {
516 if (nKr <
nEv + 6)
errorQuda(
"nKr=%d must be greater than nEv+6=%d\n", nKr,
nEv + 6);
519 errorQuda(
"Only real spectrum type (LR or SR) can be passed to the TR Lanczos solver");
525 void TRLM::operator()(std::vector<ColorSpinorField *> &kSpace, std::vector<Complex> &evals)
541 RNG *rng =
new RNG(*kSpace[0], 1234);
562 for (
int i =
nConv; i <
nEv; i++) evals.push_back(0.0);
566 double mat_norm = 0.0;
571 epsilon = DBL_EPSILON;
575 epsilon = FLT_EPSILON;
586 default:
errorQuda(
"Invalid precision %d", prec);
592 printfQuda(
"*****************************\n");
593 printfQuda(
"**** START TRLM SOLUTION ****\n");
594 printfQuda(
"*****************************\n");
614 if (fabs(
alpha[i]) > mat_norm) mat_norm = fabs(
alpha[i]);
618 for (
int i = 1; i < (nKr -
num_locked); i++) {
633 if (
residua[i + num_locked] <
tol * mat_norm) {
635 printfQuda(
"**** Converged %d resid=%+.6e condition=%.6e ****\n", i,
residua[i + num_locked],
tol * mat_norm);
662 for (
int i = 0; i <
nKr; i++) {
679 printfQuda(
"kSpace size at convergence/max restarts = %d\n", (
int)kSpace.size());
681 for (
unsigned int i =
nConv; i < kSpace.size(); i++) {
delete kSpace[i]; }
682 kSpace.resize(
nConv);
689 errorQuda(
"TRLM failed to compute the requested %d vectors with a %d search space and %d Krylov space in %d " 690 "restart steps. Exiting.",
693 warningQuda(
"TRLM failed to compute the requested %d vectors with a %d search space and %d Krylov space in %d " 694 "restart steps. Continuing with current lanczos factorisation.",
699 printfQuda(
"TRLM computed the requested %d vectors in %d restart steps and %d OP*x operations.\n",
nConv,
703 for (
int i = 0; i <
nConv; i++) {
711 for (
int i = 0; i <
nConv; i++) {
712 printfQuda(
"EigValue[%04d]: (%+.16e, %+.16e) residual %.16e\n", i, evals[i].real(), evals[i].imag(),
725 std::vector<ColorSpinorField *> vecs_ptr;
726 for (
int i = 0; i <
nConv; i++) { vecs_ptr.push_back(kSpace[i]); }
731 printfQuda(
"*****************************\n");
732 printfQuda(
"***** END TRLM SOLUTION *****\n");
733 printfQuda(
"*****************************\n");
761 int start = (j >
num_keep) ? j - 1 : 0;
762 for (
int i = start; i < j; i++) {
816 MatrixXd A = MatrixXd::Zero(dim, dim);
818 for (
int i = 0; i < dim * dim; i++)
ritz_mat[i] = 0.0;
822 for (
int i = num_locked; i <
nKr - 1; i++) {
826 alpha[nKr - 1] *= -1.0;
830 for (
int i = 0; i < dim; i++) {
836 for (
int i = 0; i < arrow_pos - 1; i++) {
843 for (
int i = arrow_pos - 1; i < dim - 1; i++) {
851 SelfAdjointEigenSolver<MatrixXd> eigensolver;
852 eigensolver.compute(A);
855 for (
int i = 0; i < dim; i++)
856 for (
int j = 0; j < dim; j++)
ritz_mat[dim * i + j] = eigensolver.eigenvectors().col(i)[j];
858 for (
int i = 0; i < dim; i++) {
866 for (
int i = num_locked; i <
nKr; i++) {
alpha[i] *= -1.0; }
875 int offset =
nKr + 1;
878 if ((
int)kSpace.size() < offset +
iter_keep) {
879 for (
int i = kSpace.size(); i < offset +
iter_keep; i++) {
895 std::vector<ColorSpinorField *> vecs_ptr;
896 std::vector<ColorSpinorField *> kSpace_ptr;
897 kSpace_ptr.push_back(kSpace[k]);
898 for (
int j = 1; j < dim; j++) {
899 vecs_ptr.push_back(kSpace[num_locked + j]);
900 ritz_mat_col[j - 1].real(
ritz_mat[i * dim + j]);
901 ritz_mat_col[j - 1].imag(0.0);
910 for (
int i = 0; i <
iter_keep; i++) *kSpace[i + num_locked] = *kSpace[offset + i];
cudaColorSpinorField * tmp2
void ax(double a, ColorSpinorField &x)
void Init()
Initialize CURAND RNG states.
void setPrecision(QudaPrecision precision, QudaPrecision ghost_precision=QUDA_INVALID_PRECISION, bool force_native=false)
cudaColorSpinorField * tmp1
enum QudaPrecision_s QudaPrecision
__host__ __device__ ValueType norm(const complex< ValueType > &z)
Returns the magnitude of z squared.
QudaVerbosity getVerbosity()
void eigensolveFromArrowMat(int nLocked, int arror_pos)
Get the eigendecomposition from the arrow matrix.
double norm2(const ColorSpinorField &a)
__host__ __device__ ValueType sqrt(ValueType x)
Complex cDotProduct(ColorSpinorField &, ColorSpinorField &)
void deflate(std::vector< ColorSpinorField *> vec_defl, std::vector< ColorSpinorField *> vec, std::vector< ColorSpinorField *> evecs, std::vector< Complex > evals)
Deflate vector with Eigenvectors.
void chebyOp(const DiracMatrix &mat, ColorSpinorField &out, const ColorSpinorField &in)
Promoted the specified matVec operation: M, Mdag, MMdag, MdagM to a Chebyshev polynomial.
cudaColorSpinorField * tmp
static ColorSpinorField * Create(const ColorSpinorParam ¶m)
TRLM(QudaEigParam *eig_param, const DiracMatrix &mat, TimeProfile &profile)
Constructor for Thick Restarted Eigensolver class.
static void loadVectors(std::vector< ColorSpinorField *> &eig_vecs, std::string file)
Load vectors from file.
void caxpbypczw(const Complex &a, ColorSpinorField &x, const Complex &b, ColorSpinorField &y, const Complex &c, ColorSpinorField &z, ColorSpinorField &w)
double reDotProduct(ColorSpinorField &x, ColorSpinorField &y)
void computeKeptRitz(std::vector< ColorSpinorField *> &kSpace)
Get the eigen-decomposition from the arrow matrix.
void copy(ColorSpinorField &dst, const ColorSpinorField &src)
void operator()(std::vector< ColorSpinorField *> &kSpace, std::vector< Complex > &evals)
Compute eigenpairs.
__host__ __device__ void sum(double &a, double &b)
void lanczosStep(std::vector< ColorSpinorField *> v, int j)
Lanczos step: extends the Kylov space.
static void saveVectors(const std::vector< ColorSpinorField *> &eig_vecs, std::string file)
Save vectors to file.
void deflateSVD(std::vector< ColorSpinorField *> vec_defl, std::vector< ColorSpinorField *> vec, std::vector< ColorSpinorField *> evecs, std::vector< Complex > evals)
Deflate vector with both left and Right singular vectors.
QudaBoolean require_convergence
QudaFieldLocation location
static EigenSolver * create(QudaEigParam *eig_param, const DiracMatrix &mat, TimeProfile &profile)
Creates the eigensolver using the parameters given and the matrix.
QudaFieldOrder fieldOrder
void Release()
Release Device memory for CURAND RNG states.
void loadFromFile(const DiracMatrix &mat, std::vector< ColorSpinorField *> &eig_vecs, std::vector< Complex > &evals)
Load and check eigenpairs from file.
void axpy(double a, ColorSpinorField &x, ColorSpinorField &y)
Class declaration to initialize and hold CURAND RNG states.
void matVec(const DiracMatrix &mat, ColorSpinorField &out, const ColorSpinorField &in)
Applies the specified matVec operation: M, Mdag, MMdag, MdagM.
std::vector< double > ritz_mat
void computeSVD(const DiracMatrix &mat, std::vector< ColorSpinorField *> &evecs, std::vector< Complex > &evals)
Computes Left/Right SVD from pre computed Right/Left.
std::complex< double > Complex
void caxpy(const Complex &a, ColorSpinorField &x, ColorSpinorField &y)
#define safe_malloc(size)
void zero(ColorSpinorField &a)
Complex blockOrthogonalize(std::vector< ColorSpinorField *> v, std::vector< ColorSpinorField *> r, int j)
Orthogonalise input vector r against vector space v using block-BLAS.
virtual void M(ColorSpinorField &out, const ColorSpinorField &in) const =0
virtual ~TRLM()
Destructor for Thick Restarted Eigensolver class.
cpuColorSpinorField * out
DEVICEHOST void swap(Real &a, Real &b)
std::vector< ColorSpinorField * > r
void reorder(std::vector< ColorSpinorField *> &kSpace)
Reorder the Krylov space by eigenvalue.
void write_spinor_field(const char *filename, void *V[], QudaPrecision precision, const int *X, int nColor, int nSpin, int Nvec, int argc, char *argv[])
void caxpby(const Complex &a, ColorSpinorField &x, const Complex &b, ColorSpinorField &y)
QudaEigSpectrumType spectrum
__host__ __device__ ValueType abs(ValueType x)
void computeEvals(const DiracMatrix &mat, std::vector< ColorSpinorField *> &evecs, std::vector< Complex > &evals, int k)
Compute eigenvalues and their residiua.
void mat(void *out, void **link, void *in, int dagger_bit, int mu, QudaPrecision sPrecision, QudaPrecision gPrecision)
void read_spinor_field(const char *filename, void *V[], QudaPrecision precision, const int *X, int nColor, int nSpin, int Nvec, int argc, char *argv[])
const Dirac * Expose() const
void spinorNoise(ColorSpinorField &src, RNG &randstates, QudaNoiseType type)
Generate a random noise spinor. This variant allows the user to manage the RNG state.
EigenSolver(QudaEigParam *eig_param, TimeProfile &profile)
Constructor for base Eigensolver class.
Thick Restarted Lanczos Method.