81 std::cout.precision(13);
84 if( (vv<eresid*eresid) ) conv = 1;
86 std::cout<<
GridLogIRL <<
"[" << std::setw(3)<<j<<
"] "
87 <<
"eval = "<<std::setw(25)<<
eval <<
" (" << eval_poly <<
")"
88 <<
" |H B[i] - eval[i]B[i]|^2 / evalMaxApprox^2 " << std::setw(25) << vv
89 <<
" target " << eresid*eresid <<
" conv " <<conv
151 int _MinRestart=0,
int _orth_period = 1,
167 int _MinRestart=0,
int _orth_period = 1,
211 void calc(std::vector<RealD>&
eval, std::vector<Field>& evec,
const Field& src,
int& Nconv,
bool reverse=
false)
214 assert(grid == evec[0].
Grid());
217 std::cout <<
GridLogIRL <<
"**************************************************************************"<< std::endl;
218 std::cout <<
GridLogIRL <<
" ImplicitlyRestartedLanczos::calc() starting iteration 0 / "<<
MaxIter<< std::endl;
219 std::cout <<
GridLogIRL <<
"**************************************************************************"<< std::endl;
220 std::cout <<
GridLogIRL <<
" -- seek Nk = " <<
Nk <<
" vectors"<< std::endl;
221 std::cout <<
GridLogIRL <<
" -- accept Nstop = " <<
Nstop <<
" vectors"<< std::endl;
222 std::cout <<
GridLogIRL <<
" -- total Nm = " <<
Nm <<
" vectors"<< std::endl;
223 std::cout <<
GridLogIRL <<
" -- size of eval = " <<
eval.size() << std::endl;
224 std::cout <<
GridLogIRL <<
" -- size of evec = " << evec.size() << std::endl;
226 std::cout <<
GridLogIRL <<
"Diagonalisation is DSTEGR "<<std::endl;
228 std::cout <<
GridLogIRL <<
"Diagonalisation is QR "<<std::endl;
230 std::cout <<
GridLogIRL <<
"Diagonalisation is Eigen "<<std::endl;
232 std::cout <<
GridLogIRL <<
"**************************************************************************"<< std::endl;
234 assert(
Nm <= evec.size() &&
Nm <=
eval.size());
237 RealD evalMaxApprox = 0.0;
241 std::cout <<
GridLogIRL <<
" IRL source norm " <<
norm2(src) << std::endl;
242 const int _MAX_ITER_IRL_MEVAPP_ = 50;
243 for (
int i=0;i<_MAX_ITER_IRL_MEVAPP_;i++) {
251 RealD na = std::sqrt(vnum/vden);
252 if (fabs(evalMaxApprox/na - 1.0) < 0.0001)
253 i=_MAX_ITER_IRL_MEVAPP_;
255 std::cout <<
GridLogIRL <<
" Approximation of largest eigenvalue: " << evalMaxApprox << std::endl;
259 std::cout <<
GridLogIRL <<
" Final evalMaxApprox " << evalMaxApprox << std::endl;
261 std::vector<RealD> lme(
Nm);
262 std::vector<RealD> lme2(
Nm);
263 std::vector<RealD> eval2(
Nm);
264 std::vector<RealD> eval2_copy(
Nm);
265 Eigen::MatrixXd Qt = Eigen::MatrixXd::Zero(
Nm,
Nm);
282 std::cout<<
GridLogIRL <<
"Initial "<<
Nk <<
"steps done "<<std::endl;
289 for(iter = 0; iter<
MaxIter; ++iter){
293 std::cout<<
GridLogMessage <<
" **********************"<< std::endl;
294 std::cout<<
GridLogMessage <<
" Restart iteration = "<< iter << std::endl;
295 std::cout<<
GridLogMessage <<
" **********************"<< std::endl;
297 std::cout<<
GridLogIRL <<
" running "<<
Nm-
Nk <<
" steps: "<<std::endl;
307 for(
int k=0; k<
Nm; ++k){
308 eval2[k] =
eval[k+k1-1];
309 lme2[k] = lme[k+k1-1];
311 Qt = Eigen::MatrixXd::Identity(
Nm,
Nm);
313 std::cout<<
GridLogIRL <<
" diagonalized "<<std::endl;
319 std::partial_sort(eval2.begin(),eval2.begin()+
Nm,eval2.end(),std::greater<RealD>());
320 std::cout<<
GridLogIRL <<
" evals sorted "<<std::endl;
322 for(
int io=0; io<k2;io+=chunk){
323 std::cout<<
GridLogIRL <<
"eval "<< std::setw(3) << io ;
324 for(
int ii=0;ii<chunk;ii++){
326 std::cout<<
" "<< std::setw(12)<< eval2[io+ii];
328 std::cout << std::endl;
334 Qt = Eigen::MatrixXd::Identity(
Nm,
Nm);
335 for(
int ip=k2; ip<
Nm; ++ip){
338 std::cout<<
GridLogIRL <<
"QR decomposed "<<std::endl;
340 assert(k2<
Nm); assert(k2<
Nm); assert(k1>0);
343 std::cout<<
GridLogIRL <<
"basisRotated by Qt *"<<k1-1<<
","<<k2+1<<
")"<<std::endl;
349 f += lme[k2-1] * evec[k2];
351 beta_k = std::sqrt(beta_k);
352 std::cout<<
GridLogIRL<<
" beta(k) = "<<beta_k<<std::endl;
354 RealD betar = 1.0/beta_k;
355 evec[k2] = betar * f;
361 for(
int k=0; k<
Nm; ++k){
365 Qt = Eigen::MatrixXd::Identity(
Nm,
Nm);
367 std::cout<<
GridLogIRL <<
" Diagonalized "<<std::endl;
372 std::cout <<
GridLogIRL <<
"Test convergence: rotate subset of vectors to test convergence " << std::endl;
374 Field
B(grid);
B.Checkerboard() = evec[0].Checkerboard();
378 for(
int jj = 1; jj<=
Nstop; jj*=2){
380 RealD e = eval2_copy[j];
389 RealD e = eval2_copy[0];
391 if( !
_Tester.TestConvergence(j,
eresid,
B,e,evalMaxApprox) ) allconv=0;
393 if ( allconv ) Nconv =
Nstop;
396 std::cout<<
GridLogIRL<<
" #modes converged: >= "<<Nconv<<
"/"<<
Nstop<<std::endl;
403 std::cout <<
GridLogIRL <<
"iter < MinRestart: do not yet test for convergence\n";
412 Field
B(grid);
B.Checkerboard() = evec[0].Checkerboard();
414 std::cout <<
GridLogIRL <<
" Rotated basis"<<std::endl;
419 for(
int j = 0; j<=
Nk; j++){
421 if(
_Tester.ReconstructEval(j,
eresid,
B,eval2[j],evalMaxApprox) ) {
426 if ( Nconv <
Nstop ) {
427 std::cout <<
GridLogIRL <<
"Nconv ("<<Nconv<<
") < Nstop ("<<
Nstop<<
")"<<std::endl;
428 std::cout <<
GridLogIRL <<
"returning Nstop vectors, the last "<<
Nstop-Nconv <<
"of which might meet convergence criterion only approximately" <<std::endl;
434 evec.resize(
Nstop,grid);
439 std::cout <<
GridLogIRL <<
"**************************************************************************"<< std::endl;
440 std::cout <<
GridLogIRL <<
"ImplicitlyRestartedLanczos CONVERGED ; Summary :\n";
441 std::cout <<
GridLogIRL <<
"**************************************************************************"<< std::endl;
442 std::cout <<
GridLogIRL <<
" -- Iterations = "<< iter <<
"\n";
443 std::cout <<
GridLogIRL <<
" -- beta(k) = "<< beta_k <<
"\n";
444 std::cout <<
GridLogIRL <<
" -- Nconv = "<< Nconv <<
"\n";
445 std::cout <<
GridLogIRL <<
"**************************************************************************"<< std::endl;
459 void step(std::vector<RealD>& lmd,
460 std::vector<RealD>& lme,
461 std::vector<Field>& evec,
462 Field& w,
int Nm,
int k)
464 std::cout<<
GridLogDebug <<
"Lanczos step " <<k<<std::endl;
465 const RealD tiny = 1.0e-20;
470 Field& evec_k = evec[k];
474 if(k>0) w -= lme[k-1] * evec[k-1];
479 w = w - alph * evec_k;
487 std::cout<<
GridLogDebug <<
"Orthogonalising " <<k<<std::endl;
489 std::cout<<
GridLogDebug <<
"Orthogonalised " <<k<<std::endl;
492 if(k <
Nm-1) evec[k+1] = w;
494 std::cout<<
GridLogIRL <<
"Lanczos step alpha[" << k <<
"] = " << zalph <<
" beta[" << k <<
"] = "<<beta<<std::endl;
496 std::cout<<
GridLogIRL <<
" beta is tiny "<<beta<<std::endl;
498 std::cout<<
GridLogDebug <<
"Lanczos step complete " <<k<<std::endl;
503 Eigen::MatrixXd & Qt,
506 Eigen::MatrixXd TriDiag = Eigen::MatrixXd::Zero(
Nk,
Nk);
508 for(
int i=0;i<
Nk;i++) TriDiag(i,i) = lmd[i];
509 for(
int i=0;i<
Nk-1;i++) TriDiag(i,i+1) = lme[i];
510 for(
int i=0;i<
Nk-1;i++) TriDiag(i+1,i) = lme[i];
512 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eigensolver(TriDiag);
514 for (
int i = 0; i <
Nk; i++) {
515 lmd[
Nk-1-i] = eigensolver.eigenvalues()(i);
517 for (
int i = 0; i <
Nk; i++) {
518 for (
int j = 0; j <
Nk; j++) {
519 Qt(
Nk-1-i,j) = eigensolver.eigenvectors()(j,i);
528 std::vector<RealD>& lme,
531 RealD Dsh,
int kmin,
int kmax)
536 RealD Fden = 1.0/hypot(lmd[k]-Dsh,lme[k]);
537 RealD c = ( lmd[k] -Dsh) *Fden;
538 RealD s = -lme[k] *Fden;
540 RealD tmpa1 = lmd[k];
541 RealD tmpa2 = lmd[k+1];
544 lmd[k] = c*c*tmpa1 +s*s*tmpa2 -2.0*c*s*tmpb;
545 lmd[k+1] = s*s*tmpa1 +c*c*tmpa2 +2.0*c*s*tmpb;
546 lme[k] = c*s*(tmpa1-tmpa2) +(c*c-s*s)*tmpb;
548 lme[k+1] = c*lme[k+1];
550 for(
int i=0; i<
Nk; ++i){
551 RealD Qtmp1 = Qt(k,i);
552 RealD Qtmp2 = Qt(k+1,i);
553 Qt(k,i) = c*Qtmp1 - s*Qtmp2;
554 Qt(k+1,i)= s*Qtmp1 + c*Qtmp2;
558 for(
int k = kmin; k < kmax-1; ++k){
560 RealD Fden = 1.0/hypot(x,lme[k-1]);
561 RealD c = lme[k-1]*Fden;
564 RealD tmpa1 = lmd[k];
565 RealD tmpa2 = lmd[k+1];
568 lmd[k] = c*c*tmpa1 +s*s*tmpa2 -2.0*c*s*tmpb;
569 lmd[k+1] = s*s*tmpa1 +c*c*tmpa2 +2.0*c*s*tmpb;
570 lme[k] = c*s*(tmpa1-tmpa2) +(c*c-s*s)*tmpb;
571 lme[k-1] = c*lme[k-1] -s*x;
575 lme[k+1] = c*lme[k+1];
578 for(
int i=0; i<
Nk; ++i){
579 RealD Qtmp1 = Qt(k,i);
580 RealD Qtmp2 = Qt(k+1,i);
581 Qt(k,i) = c*Qtmp1 -s*Qtmp2;
582 Qt(k+1,i) = s*Qtmp1 +c*Qtmp2;
587 void diagonalize(std::vector<RealD>& lmd, std::vector<RealD>& lme,
589 Eigen::MatrixXd & Qt,
592 Qt = Eigen::MatrixXd::Identity(
Nm,
Nm);
605void LAPACK_dstegr(
char *jobz,
char *range,
int *n,
double *d,
double *e,
606 double *vl,
double *vu,
int *il,
int *iu,
double *abstol,
607 int *m,
double *w,
double *z,
int *ldz,
int *isuppz,
608 double *work,
int *lwork,
int *iwork,
int *liwork,
613 std::vector<RealD>& lme,
621 double evals_tmp[NN];
622 double evec_tmp[NN][NN];
623 memset(evec_tmp[0],0,
sizeof(
double)*NN*NN);
626 for (
int i = 0; i< NN; i++) {
627 for (
int j = i - 1; j <= i + 1; j++) {
628 if ( j < NN && j >= 0 ) {
629 if (i==j) DD[i] = lmd[i];
630 if (i==j) evals_tmp[i] = lmd[i];
631 if (j==(i-1)) EE[j] = lme[j];
636 int lwork = ( (18*NN) > (1+4*NN+NN*NN)? (18*NN):(1+4*NN+NN*NN)) ;
637 int liwork = 3+NN*10 ;
650 int interval = (NN/total)+1;
651 double vl = 0.0, vu = 0.0;
652 int il = interval*node+1 , iu = interval*(node+1);
656 memset(evals_tmp,0,
sizeof(
double)*NN);
658 LAPACK_dstegr(&jobz, &range, &NN,
659 (
double*)DD, (
double*)EE,
662 &evals_found, evals_tmp, (
double*)evec_tmp, &NN,
664 work, &lwork, iwork, &liwork,
666 for (
int i = iu-1; i>= il-1; i--){
667 evals_tmp[i] = evals_tmp[i - (il-1)];
668 if (il>1) evals_tmp[i-(il-1)]=0.;
669 for (
int j = 0; j< NN; j++){
670 evec_tmp[i][j] = evec_tmp[i - (il-1)][j];
671 if (il>1) evec_tmp[i-(il-1)][j]=0.;
683 for(
int i=0;i<NN;i++){
684 lmd [NN-1-i]=evals_tmp[i];
685 for(
int j=0;j<NN;j++){
686 Qt((NN-1-i),j)=evec_tmp[i][j];
696 Eigen::MatrixXd & Qt,
704 for(
int iter=0; iter<QRiter; ++iter){
707 RealD dsub = lmd[kmax-1]-lmd[kmax-2];
708 RealD dd = std::sqrt(dsub*dsub + 4.0*lme[kmax-2]*lme[kmax-2]);
709 RealD Dsh = 0.5*(lmd[kmax-2]+lmd[kmax-1] +dd*(dsub/fabs(dsub)));
716 for(
int j=kmax-1; j>= kmin; --j){
717 RealD dds = fabs(lmd[j-1])+fabs(lmd[j]);
718 if(fabs(lme[j-1])+dds > dds){
727 for(
int j=0; j<kmax-1; ++j){
728 RealD dds = fabs(lmd[j])+fabs(lmd[j+1]);
729 if(fabs(lme[j])+dds > dds){
735 std::cout <<
GridLogError <<
"[QL method] Error - Too many iteration: "<<QRiter<<
"\n";
@ IRLdiagonaliseWithEigen
@ IRLdiagonaliseWithDSTEGR
accelerator_inline sobj eval(const uint64_t ss, const sobj &arg)
void basisRotate(VField &basis, Matrix &Qt, int j0, int j1, int k0, int k1, int Nm)
void basisOrthogonalize(std::vector< Field > &basis, Field &w, int k)
void basisSortInPlace(std::vector< Field > &_v, std::vector< RealD > &sort_vals, bool reverse)
void basisRotateJ(Field &result, std::vector< Field > &basis, Eigen::MatrixXd &Qt, int j, int k0, int k1, int Nm)
Lattice< vobj > real(const Lattice< vobj > &lhs)
ComplexD innerProduct(const Lattice< vobj > &left, const Lattice< vobj > &right)
RealD norm2(const Lattice< vobj > &arg)
Lattice< obj > pow(const Lattice< obj > &rhs_i, RealD y)
GridLogger GridLogError(1, "Error", GridLogColours, "RED")
GridLogger GridLogIRL(1, "IRL", GridLogColours, "NORMAL")
GridLogger GridLogDebug(1, "Debug", GridLogColours, "PURPLE")
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
#define NAMESPACE_BEGIN(A)
std::complex< RealD > ComplexD
void GlobalSumVector(RealF *, int N)
LinearFunction< Field > & _HermOp
int TestConvergence(int j, RealD eresid, Field &B, RealD &eval, RealD evalMaxApprox)
ImplicitlyRestartedLanczosHermOpTester(LinearFunction< Field > &HermOp)
int ReconstructEval(int j, RealD resid, Field &B, RealD &eval, RealD evalMaxApprox)
virtual int TestConvergence(int j, RealD resid, Field &evec, RealD &eval, RealD evalMaxApprox)=0
virtual int ReconstructEval(int j, RealD resid, Field &evec, RealD &eval, RealD evalMaxApprox)=0
ImplicitlyRestartedLanczosTester< Field > & _Tester
LinearFunction< Field > & _PolyOp
void diagonalize(std::vector< RealD > &lmd, std::vector< RealD > &lme, int Nk, int Nm, Eigen::MatrixXd &Qt, GridBase *grid)
void diagonalize_Eigen(std::vector< RealD > &lmd, std::vector< RealD > &lme, int Nk, int Nm, Eigen::MatrixXd &Qt, GridBase *grid)
ImplicitlyRestartedLanczos(LinearFunction< Field > &PolyOp, LinearFunction< Field > &HermOp, ImplicitlyRestartedLanczosTester< Field > &Tester, int _Nstop, int _Nk, int _Nm, RealD _eresid, int _MaxIter, RealD _betastp=0.0, int _MinRestart=0, int _orth_period=1, IRLdiagonalisation _diagonalisation=IRLdiagonaliseWithEigen)
void QR_decomp(std::vector< RealD > &lmd, std::vector< RealD > &lme, int Nk, int Nm, Eigen::MatrixXd &Qt, RealD Dsh, int kmin, int kmax)
void diagonalize_lapack(std::vector< RealD > &lmd, std::vector< RealD > &lme, int Nk, int Nm, Eigen::MatrixXd &Qt, GridBase *grid)
static RealD normalise(T &v)
void diagonalize_QR(std::vector< RealD > &lmd, std::vector< RealD > &lme, int Nk, int Nm, Eigen::MatrixXd &Qt, GridBase *grid)
void orthogonalize(Field &w, std::vector< Field > &evec, int k)
void step(std::vector< RealD > &lmd, std::vector< RealD > &lme, std::vector< Field > &evec, Field &w, int Nm, int k)
LinearFunction< Field > & _HermOp
void calc(std::vector< RealD > &eval, std::vector< Field > &evec, const Field &src, int &Nconv, bool reverse=false)
ImplicitlyRestartedLanczos(LinearFunction< Field > &PolyOp, LinearFunction< Field > &HermOp, int _Nstop, int _Nk, int _Nm, RealD _eresid, int _MaxIter, RealD _betastp=0.0, int _MinRestart=0, int _orth_period=1, IRLdiagonalisation _diagonalisation=IRLdiagonaliseWithEigen)
IRLdiagonalisation diagonalisation
ImplicitlyRestartedLanczosHermOpTester< Field > SimpleTester