35#include <mkl_lapack.h>
39#define Glog std::cout << GridLogMessage
46#define CUDA_COMPLEX cuDoubleComplex
47#define CUDA_FLOAT double
48#define MAKE_CUDA_COMPLEX make_cuDoubleComplex
49#define CUDA_GEMM cublasZgemm
51#define CUDA_COMPLEX cuComplex
52#define CUDA_FLOAT float
53#define MAKE_CUDA_COMPLEX make_cuComplex
54#define CUDA_GEMM cublasCgemm
69 static bool less_pair(std::pair<RealD,Field const*>& left,
70 std::pair<RealD,Field const*>& right){
71 return left.first > (right.first);
75 void push(std::vector<RealD>& lmd,std::vector<Field>& evec,
int N) {
81 std::vector<Field> cpy(lmd.size(),evec[0].Grid());
82 for(
int i=0;i<lmd.size();i++) cpy[i] = evec[i];
84 std::vector<std::pair<RealD, Field const*> > emod(lmd.size());
86 for(
int i=0;i<lmd.size();++i) emod[i] = std::pair<RealD,Field const*>(lmd[i],&cpy[i]);
88 partial_sort(emod.begin(),emod.begin()+N,emod.end(),
less_pair);
90 typename std::vector<std::pair<RealD, Field const*> >::iterator it = emod.begin();
93 evec[i]=*(it->second);
97 void push(std::vector<RealD>& lmd,
int N) {
98 std::partial_sort(lmd.begin(),lmd.begin()+N,lmd.end(),
less_lmd);
101 return fabs(lmd) > fabs(thrs);
121 std::string
cname = std::string(
"ImplicitlyRestartedBlockLanczos");
146 cudaError_t cudaStat;
163 int _Nconv_test_interval,
172 Nu(_Nu),
Nk(_Nk),
Nm(_Nm),
178 { assert( (
Nk%
Nu==0) && (
Nm%
Nu==0) ); };
191 void orthogonalize(Field& w, std::vector<Field>& evec,
int k,
int if_print=0)
193 typedef typename Field::scalar_type MyComplex;
197 for(
int j=0; j<k; ++j){
200 if( norm(ip)/
norm2(w) > 1e-14)
201 Glog<<
"orthogonalize before: "<<j<<
" of "<<k<<
" "<< ip <<std::endl;
202 w = w - ip * evec[j];
205 if( norm(ip)/
norm2(w) > 1e-14)
206 Glog<<
"orthogonalize after: "<<j<<
" of "<<k<<
" "<< ip <<std::endl;
216 void orthogonalize(std::vector<Field>& w,
int _Nu, std::vector<Field>& evec,
int k,
int if_print=0)
218 typedef typename Field::scalar_type MyComplex;
222 for(
int j=0; j<k; ++j){
223 for(
int i=0; i<_Nu; ++i){
225 w[i] = w[i] - ip * evec[j];
227 for(
int i=0; i<_Nu; ++i)
235 Glog <<
"cuBLAS orthogonalize" << std::endl;
237 typedef typename Field::vector_object vobj;
239 typedef typename vobj::vector_type vector_type;
241 typedef typename Field::scalar_type MyComplex;
244 const uint64_t sites = grid->
lSites();
251 for (
int col=0; col<
Nu; ++col) {
256 for (
size_t row=0; row<sites*12; ++row) {
257 w_acc[col*sites*12+row] = z[row];
260 cublasHandle_t handle;
263 stat = cublasCreate(&handle);
265 Glog <<
"cuBLAS Zgemm"<< std::endl;
267 for (
int b=0; b<Nbatch; ++b) {
273 for (
size_t row=0; row<sites*12; ++row) {
274 evec_acc[col*sites*12+row] = z[row];
281 evec_acc, 12*sites, w_acc, 12*sites,
296 for (
int col=0; col<
Nu; ++col) {
300 for (
size_t row=0; row<sites*12; ++row) {
301 z[row] = w_acc[col*sites*12+row];
304 for (
int i=0; i<
Nu; ++i) {
308 Glog <<
"cuBLAS Zgemm done"<< std::endl;
310 cublasDestroy(handle);
312 Glog <<
"cuBLAS orthogonalize done" << std::endl;
314 Glog <<
"BLAS wrapper is not implemented" << std::endl;
323 typedef typename Field::scalar_type MyComplex;
326 for(
int j=0; j<k; ++j){
328 w = w - ip * evec[j*
Nu];
334 std::vector<Field>& evec,
335 const std::vector<Field>& src,
int& Nconv,
LanczosType Impl)
345 const uint64_t sites = grid->
lSites();
347 cudaStat = cudaMallocManaged((
void **)&w_acc,
Nu*sites*12*
sizeof(
CUDA_COMPLEX));
372 std::vector<Field>& evec,
373 const std::vector<Field>& src,
int& Nconv)
375 std::string fname = std::string(
cname+
"::calc_irbl()");
377 assert(grid == src[0].
Grid());
378 assert(
Nu = src.size() );
380 Glog << std::string(74,
'*') << std::endl;
381 Glog << fname +
" starting iteration 0 / "<<
MaxIter<< std::endl;
382 Glog << std::string(74,
'*') << std::endl;
383 Glog <<
" -- seek Nk = "<<
Nk <<
" vectors"<< std::endl;
384 Glog <<
" -- accept Nstop = "<<
Nstop <<
" vectors"<< std::endl;
385 Glog <<
" -- total Nm = "<<
Nm <<
" vectors"<< std::endl;
386 Glog <<
" -- size of eval = "<<
eval.size() << std::endl;
387 Glog <<
" -- size of evec = "<< evec.size() << std::endl;
389 Glog <<
"Diagonalisation is Eigen "<< std::endl;
392 Glog <<
"Diagonalisation is LAPACK "<< std::endl;
397 Glog << std::string(74,
'*') << std::endl;
399 assert(
Nm == evec.size() &&
Nm ==
eval.size());
401 std::vector<std::vector<ComplexD>> lmd(
Nu,std::vector<ComplexD>(
Nm,0.0));
402 std::vector<std::vector<ComplexD>> lme(
Nu,std::vector<ComplexD>(
Nm,0.0));
403 std::vector<std::vector<ComplexD>> lmd2(
Nu,std::vector<ComplexD>(
Nm,0.0));
404 std::vector<std::vector<ComplexD>> lme2(
Nu,std::vector<ComplexD>(
Nm,0.0));
405 std::vector<RealD> eval2(
Nm);
406 std::vector<RealD> resid(
Nk);
408 Eigen::MatrixXcd Qt = Eigen::MatrixXcd::Zero(
Nm,
Nm);
409 Eigen::MatrixXcd Q = Eigen::MatrixXcd::Zero(
Nm,
Nm);
411 std::vector<int> Iconv(
Nm);
412 std::vector<Field>
B(
Nm,grid);
414 std::vector<Field> f(
Nu,grid);
415 std::vector<Field> f_copy(
Nu,grid);
423 for (
int i=0; i<
Nu; ++i) {
424 Glog <<
"norm2(src[" << i <<
"])= "<<
norm2(src[i]) << std::endl;
427 Glog <<
"norm2(evec[" << i <<
"])= "<<
norm2(evec[i]) << std::endl;
435 for(iter = 0; iter<
MaxIter; ++iter){
437 Glog <<
"#Restart iteration = "<< iter << std::endl;
442 for(
int u=0; u<
Nu; ++u){
443 for(
int k=0; k<
Nm; ++k){
444 lmd2[u][k] = lmd[u][k];
445 lme2[u][k] = lme[u][k];
448 Qt = Eigen::MatrixXcd::Identity(
Nm,
Nm);
451 Glog <<
"#Ritz value before shift: "<< std::endl;
452 for(
int i=0; i<
Nm; ++i){
453 std::cout.precision(13);
454 std::cout <<
"[" << std::setw(4)<< std::setiosflags(std::ios_base::right) <<i<<
"] ";
455 std::cout <<
"Rval = "<<std::setw(20)<< std::setiosflags(std::ios_base::left)<< eval2[i] << std::endl;
460 Glog <<
" #Apply shifted QR transformations "<<std::endl;
464 Eigen::MatrixXcd BTDM = Eigen::MatrixXcd::Identity(
Nm,
Nm);
465 Q = Eigen::MatrixXcd::Identity(
Nm,
Nm);
469 for(
int ip=
Nk; ip<
Nm; ++ip){
475 for(
int i=0; i<k2; ++i)
B[i] = 0.0;
476 for(
int j=0; j<k2; ++j){
477 for(
int k=0; k<
Nm; ++k){
478 B[j].Checkerboard() = evec[k].Checkerboard();
479 B[j] += evec[k]*Q(k,j);
482 for(
int i=0; i<k2; ++i) evec[i] =
B[i];
488 for(
int u=0; u<
Nu; ++u){
489 for(
int k=0; k<
Nm; ++k){
490 lmd2[u][k] = lmd[u][k];
491 lme2[u][k] = lme[u][k];
494 Qt = Eigen::MatrixXcd::Identity(
Nm,
Nm);
497 Glog <<
"#Ritz value after shift: "<< std::endl;
498 for(
int i=0; i<
Nk; ++i){
499 std::cout.precision(13);
500 std::cout <<
"[" << std::setw(4)<< std::setiosflags(std::ios_base::right) <<i<<
"] ";
501 std::cout <<
"Rval = "<<std::setw(20)<< std::setiosflags(std::ios_base::left)<< eval2[i] << std::endl;
507 Glog <<
" #Convergence test: "<<std::endl;
508 for(
int k = 0; k<
Nk; ++k)
B[k]=0.0;
509 for(
int j = 0; j<
Nk; ++j){
510 for(
int k = 0; k<
Nk; ++k){
511 B[j].Checkerboard() = evec[k].Checkerboard();
512 B[j] += evec[k]*Qt(k,j);
517 for(
int i=0; i<
Nk; ++i){
522 eval2[i] = vnum/vden;
527 std::cout.precision(13);
528 std::cout <<
"[" << std::setw(4)<< std::setiosflags(std::ios_base::right) <<i<<
"] ";
529 std::cout <<
"eval = "<<std::setw(20)<< std::setiosflags(std::ios_base::left)<< eval2[i];
530 std::cout <<
" resid^2 = "<< std::setw(20)<< std::setiosflags(std::ios_base::right)<< vv<< std::endl;
541 Glog <<
" #modes converged: "<<Nconv<<std::endl;
542 for(
int i=0; i<Nconv; ++i){
543 std::cout.precision(13);
544 std::cout <<
"[" << std::setw(4)<< std::setiosflags(std::ios_base::right) <<Iconv[i]<<
"] ";
545 std::cout <<
"eval_conv = "<<std::setw(20)<< std::setiosflags(std::ios_base::left)<< eval2[Iconv[i]];
546 std::cout <<
" resid^2 = "<< std::setw(20)<< std::setiosflags(std::ios_base::right)<< resid[Iconv[i]]<< std::endl;
549 if ( Nconv>=
Nstop )
break;
553 Glog << std::string(74,
'*') << std::endl;
555 Glog << fname +
" NOT converged ; Summary :\n";
557 Glog << fname +
" CONVERGED ; Summary :\n";
560 evec.resize(Nconv,grid);
561 for(
int i=0; i<Nconv; ++i){
562 eval[i] = eval2[Iconv[i]];
563 evec[i] =
B[Iconv[i]];
567 Glog << std::string(74,
'*') << std::endl;
568 Glog <<
" -- Iterations = "<< iter <<
"\n";
570 Glog <<
" -- Nconv = "<< Nconv <<
"\n";
571 Glog << std::string(74,
'*') << std::endl;
577 std::vector<Field>& evec,
578 const std::vector<Field>& src,
int& Nconv)
580 std::string fname = std::string(
cname+
"::calc_rbl()");
582 assert(grid == src[0].
Grid());
583 assert(
Nu = src.size() );
587 int Nblock_p = Np/
Nu;
590 Glog << std::string(74,
'*') << std::endl;
591 Glog << fname +
" starting iteration 0 / "<<
MaxIter<< std::endl;
592 Glog << std::string(74,
'*') << std::endl;
593 Glog <<
" -- seek (min) Nk = "<<
Nk <<
" vectors"<< std::endl;
594 Glog <<
" -- seek (inc) Np = "<< Np <<
" vectors"<< std::endl;
595 Glog <<
" -- seek (max) Nm = "<<
Nm <<
" vectors"<< std::endl;
596 Glog <<
" -- accept Nstop = "<<
Nstop <<
" vectors"<< std::endl;
597 Glog <<
" -- size of eval = "<<
eval.size() << std::endl;
598 Glog <<
" -- size of evec = "<< evec.size() << std::endl;
600 Glog <<
"Diagonalisation is Eigen "<< std::endl;
603 Glog <<
"Diagonalisation is LAPACK "<< std::endl;
608 Glog << std::string(74,
'*') << std::endl;
610 assert(
Nm == evec.size() &&
Nm ==
eval.size());
612 std::vector<std::vector<ComplexD>> lmd(
Nu,std::vector<ComplexD>(
Nm,0.0));
613 std::vector<std::vector<ComplexD>> lme(
Nu,std::vector<ComplexD>(
Nm,0.0));
614 std::vector<std::vector<ComplexD>> lmd2(
Nu,std::vector<ComplexD>(
Nm,0.0));
615 std::vector<std::vector<ComplexD>> lme2(
Nu,std::vector<ComplexD>(
Nm,0.0));
616 std::vector<RealD> eval2(
Nk);
617 std::vector<RealD> resid(
Nm);
619 Eigen::MatrixXcd Qt = Eigen::MatrixXcd::Zero(
Nm,
Nm);
620 Eigen::MatrixXcd Q = Eigen::MatrixXcd::Zero(
Nm,
Nm);
622 std::vector<int> Iconv(
Nm);
625 std::vector<Field>
B(1,grid);
627 std::vector<Field> f(
Nu,grid);
628 std::vector<Field> f_copy(
Nu,grid);
636 for (
int i=0; i<
Nu; ++i) {
637 Glog <<
"norm2(src[" << i <<
"])= "<<
norm2(src[i]) << std::endl;
640 Glog <<
"norm2(evec[" << i <<
"])= "<<
norm2(evec[i]) << std::endl;
649 int Nblock_l, Nblock_r;
653 for(iter = 0; iter<
MaxIter; ++iter){
655 Glog <<
"#Restart iteration = "<< iter << std::endl;
657 Nblock_l =
Nblock_k + iter*Nblock_p;
658 Nblock_r = Nblock_l + Nblock_p;
664 for(
int b=Nblock_l; b<Nblock_r; ++b)
blockwiseStep(lmd,lme,evec,f,f_copy,b);
667 for(
int u=0; u<
Nu; ++u){
668 for(
int k=0; k<Nr; ++k){
669 lmd2[u][k] = lmd[u][k];
670 lme2[u][k] = lme[u][k];
673 Qt = Eigen::MatrixXcd::Identity(Nr,Nr);
675 _sort.push(eval2,Nr);
676 Glog <<
"#Ritz value: "<< std::endl;
677 for(
int i=0; i<Nr; ++i){
678 std::cout.precision(13);
679 std::cout <<
"[" << std::setw(4)<< std::setiosflags(std::ios_base::right) <<i<<
"] ";
680 std::cout <<
"Rval = "<<std::setw(20)<< std::setiosflags(std::ios_base::left)<< eval2[i] << std::endl;
684 Glog <<
" #Convergence test: "<<std::endl;
689 Glog <<
" #rotation for next check point evec"
690 << std::setw(4)<< std::setiosflags(std::ios_base::right)
691 <<
"["<< j <<
"]" <<std::endl;
692 for(
int k = 0; k<Nr; ++k){
693 B[0].Checkerboard() = evec[k].Checkerboard();
694 B[0] += evec[k]*Qt(k,j);
700 eval2[j] = vnum/vden;
705 std::cout.precision(13);
706 std::cout <<
"[" << std::setw(4)<< std::setiosflags(std::ios_base::right) <<j<<
"] ";
707 std::cout <<
"eval = "<<std::setw(20)<< std::setiosflags(std::ios_base::left)<< eval2[j];
708 std::cout <<
" resid^2 = "<< std::setw(20)<< std::setiosflags(std::ios_base::right)<< vv<< std::endl;
721 Glog <<
" #modes converged: "<<Nconv<<std::endl;
722 for(
int i=0; i<Nconv; ++i){
723 std::cout.precision(13);
724 std::cout <<
"[" << std::setw(4)<< std::setiosflags(std::ios_base::right) <<Iconv[i]<<
"] ";
725 std::cout <<
"eval_conv = "<<std::setw(20)<< std::setiosflags(std::ios_base::left)<< eval2[Iconv[i]];
726 std::cout <<
" resid^2 = "<< std::setw(20)<< std::setiosflags(std::ios_base::right)<< resid[Iconv[i]]<< std::endl;
730 if ( Nconv_guess >=
Nstop )
break;
734 Glog << std::string(74,
'*') << std::endl;
735 if ( Nconv_guess <
Nstop ) {
736 Glog << fname +
" NOT converged ; Summary :\n";
738 Glog << fname +
" CONVERGED ; Summary :\n";
740 std::vector<Field> Btmp(
Nstop,grid);
742 for(
int i=0; i<
Nstop; ++i){
744 for(
int k = 0; k<Nr; ++k){
745 Btmp[i].Checkerboard() = evec[k].Checkerboard();
746 Btmp[i] += evec[k]*Qt(k,i);
752 v -= vnum/vden*Btmp[i];
756 std::cout.precision(13);
757 std::cout <<
"[" << std::setw(4)<< std::setiosflags(std::ios_base::right) <<i<<
"] ";
758 std::cout <<
"eval = "<<std::setw(20)<< std::setiosflags(std::ios_base::left)<< vnum/vden;
759 std::cout <<
" resid^2 = "<< std::setw(20)<< std::setiosflags(std::ios_base::right)<< vv<< std::endl;
762 for(
int i=0; i<
Nstop; ++i) evec[i] = Btmp[i];
764 evec.resize(
Nstop,grid);
767 Glog << std::string(74,
'*') << std::endl;
768 Glog <<
" -- Iterations = "<< iter <<
"\n";
770 Glog <<
" -- Nconv = "<< Nconv <<
"\n";
771 Glog <<
" -- Nconv (guess) = "<< Nconv_guess <<
"\n";
772 Glog << std::string(74,
'*') << std::endl;
778 std::vector<std::vector<ComplexD>>& lme,
779 std::vector<Field>& evec,
780 std::vector<Field>& w,
781 std::vector<Field>& w_copy,
784 const RealD tiny = 1.0e-20;
787 int Nm = evec.size();
797 Glog <<
"Using split grid"<< std::endl;
806while ( k_start <
Nu) {
807 Glog <<
"k_start= "<<k_start<< std::endl;
808 for (
int u=0; u<
mrhs; ++u) in[u] = evec[L+k_start+u];
809Glog <<
"Split "<< std::endl;
811Glog <<
"Split done "<< std::endl;
813Glog <<
"Unsplit "<< std::endl;
815Glog <<
"Unsplit done "<< std::endl;
816 for (
int u=0; u<
mrhs; ++u) w[k_start+u] = in[u];
819 Glog <<
"Using split grid done "<< std::endl;
823 Glog <<
"Split grid testing "<< std::endl;
825 for (
int k=L, u=0; k<R; ++k, ++u) {
828 for (
int u=0; u<
Nu; ++u) {
830 Glog <<
"diff(split - non_split) "<<u<<
" " <<
norm2(w_copy[u]) << std::endl;
831 Glog <<
"Split grid testing done"<< std::endl;
835 Glog <<
"Poly done"<< std::endl;
836 Glog <<
"LinAlg "<< std::endl;
840 for (
int u=0; u<
Nu; ++u) {
842 for (
int k=L-
Nu+u; k<L; ++k) {
843 w[u] = w[u] - evec[k] *
conjugate(lme[u][k]);
855 for (
int u=0; u<
Nu; ++u) {
856 for (
int k=L+u; k<R; ++k) {
861 lmd[u][L+u] =
real(lmd[u][L+u]);
865 for (
int u=0; u<
Nu; ++u) {
866 for (
int k=L; k<R; ++k) {
867 w[u] = w[u] - evec[k]*lmd[u][k];
871 Glog <<
"LinAlg done"<< std::endl;
877 for (
int u=0; u<
Nu; ++u) {
878 for (
int k=L; k<R; ++k) {
885 Glog <<
"Gram Schmidt"<< std::endl;
888 Glog <<
"Gram Schmidt using cublas"<< std::endl;
892 for (
int u=1; u<
Nu; ++u) {
895 Glog <<
"Gram Schmidt done "<< std::endl;
897 Glog <<
"LinAlg "<< std::endl;
898 for (
int u=0; u<
Nu; ++u) {
900 for (
int v=u; v<
Nu; ++v) {
903 lme[u][L+u] =
real(lme[u][L+u]);
907 for (
int u=0; u<
Nu; ++u) {
909 assert (!isnan(
norm2(w[u])));
910 for (
int k=L+u; k<R; ++k) {
911 Glog <<
" In block "<< b <<
"," <<
" beta[" << u <<
"," << k-L <<
"] = " << lme[u][k] << std::endl;
914 Glog <<
"LinAlg done "<< std::endl;
917 for (
int u=0; u<
Nu; ++u) {
926 std::vector<std::vector<ComplexD>>& lmd,
927 std::vector<std::vector<ComplexD>>& lme,
929 Eigen::MatrixXcd & Qt,
934 Eigen::MatrixXcd BlockTriDiag = Eigen::MatrixXcd::Zero(
Nk,
Nk);
936 for (
int u=0; u<
Nu; ++u ) {
937 for (
int k=0; k<
Nk; ++k ) {
938 BlockTriDiag(k,u+(k/
Nu)*
Nu) = lmd[u][k];
942 for (
int u=0; u<
Nu; ++u ) {
943 for (
int k=
Nu; k<
Nk; ++k ) {
945 BlockTriDiag(u+(k/
Nu)*
Nu,k-
Nu) = lme[u][k-
Nu];
950 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXcd> eigensolver(BlockTriDiag);
952 for (
int i = 0; i <
Nk; i++) {
953 eval[
Nk-1-i] = eigensolver.eigenvalues()(i);
955 for (
int i = 0; i <
Nk; i++) {
956 for (
int j = 0; j <
Nk; j++) {
957 Qt(j,
Nk-1-i) = eigensolver.eigenvectors()(j,i);
965 void diagonalize_lapack(std::vector<RealD>&
eval,
966 std::vector<std::vector<ComplexD>>& lmd,
967 std::vector<std::vector<ComplexD>>& lme,
969 Eigen::MatrixXcd & Qt,
972 Glog <<
"diagonalize_lapack: Nu= "<<
Nu<<
" Nk= "<<
Nk<<
" Nm= "<<std::endl;
975 Eigen::MatrixXcd BlockTriDiag = Eigen::MatrixXcd::Zero(
Nk,
Nk);
977 for (
int u=0; u<
Nu; ++u ) {
978 for (
int k=0; k<
Nk; ++k ) {
980 BlockTriDiag(k,u+(k/
Nu)*
Nu) = lmd[u][k];
984 for (
int u=0; u<
Nu; ++u ) {
985 for (
int k=
Nu; k<
Nk; ++k ) {
988 BlockTriDiag(u+(k/
Nu)*
Nu,k-
Nu) = lme[u][k-
Nu];
997 double *evals_tmp = (
double *) malloc(NN*
sizeof(
double));
998 MKL_Complex16 *evec_tmp = (MKL_Complex16 *) malloc(NN*NN*
sizeof(MKL_Complex16));
999 MKL_Complex16 *DD = (MKL_Complex16 *) malloc(NN*NN*
sizeof(MKL_Complex16));
1000 for (
int i = 0; i< NN; i++) {
1001 for (
int j = 0; j <NN ; j++) {
1002 evec_tmp[i*NN+j].real=0.;
1003 evec_tmp[i*NN+j].imag=0.;
1004 DD[i*NN+j].real=BlockTriDiag(i,j).real();
1005 DD[i*NN+j].imag=BlockTriDiag(i,j).imag();
1008 MKL_INT evals_found;
1009 MKL_INT lwork = (3*NN);
1010 MKL_INT lrwork = (24*NN);
1011 MKL_INT liwork = NN*10 ;
1012 MKL_INT iwork[liwork];
1013 double rwork[lrwork];
1015 MKL_Complex16 *work = (MKL_Complex16 *) malloc(lwork*
sizeof(MKL_Complex16));
1016 MKL_INT isuppz[2*NN];
1026 int interval = (NN/total)+1;
1027 double vl = 0.0, vu = 0.0;
1028 MKL_INT il = interval*node+1 , iu = interval*(node+1);
1030 Glog <<
"node "<<node<<
"il "<<il<<
"iu "<<iu<<std::endl;
1033 memset(evals_tmp,0,
sizeof(
double)*NN);
1035 zheevr(&jobz, &range, &uplo, &NN,
1039 &evals_found, evals_tmp, (MKL_Complex16*)evec_tmp, &NN,
1046 for (
int i = iu-1; i>= il-1; i--){
1047 evals_tmp[i] = evals_tmp[i - (il-1)];
1048 if (il>1) evals_tmp[i-(il-1)]=0.;
1049 for (
int j = 0; j< NN; j++){
1050 evec_tmp[i*NN+j] = evec_tmp[(i - (il-1))*NN+j];
1052 evec_tmp[(i-(il-1))*NN+j].
imag=0.;
1053 evec_tmp[(i-(il-1))*NN+j].
real=0.;
1063 for (
int i = 0; i <
Nk; i++)
1064 eval[
Nk-1-i] = evals_tmp[i];
1065 for (
int i = 0; i <
Nk; i++) {
1066 for (
int j = 0; j <
Nk; j++) {
1068 Qt(j,
Nk-1-i)=std::complex<double>
1078 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXcd> eigensolver(BlockTriDiag);
1080 for (
int i = 0; i <
Nk; i++) {
1081 Glog <<
"eval = "<<i<<
" " <<
eval[
Nk-1-i] <<
" "<< eigensolver.eigenvalues()(i) <<std::endl;
1084 for (
int i = 0; i <
Nk; i++) {
1085 for (
int j = 0; j <
Nk; j++) {
1088 MKL_Complex16 tmp = evec_tmp[i*
Nk+j];
1092 Glog<<
"Qt "<<j<<
" "<<
Nk-1-i<<
" = " << norm(Qt(j,
Nk-1-i))<<
" "<<
1093 norm(eigensolver.eigenvectors()(j,i)) <<std::endl;
1108 std::vector<std::vector<ComplexD>>& lmd,
1109 std::vector<std::vector<ComplexD>>& lme,
1111 Eigen::MatrixXcd & Qt,
1114 Qt = Eigen::MatrixXcd::Identity(
Nm,
Nm);
1119 diagonalize_lapack(
eval,lmd,lme,
Nu,
Nk,
Nm,Qt,grid);
1128 std::vector<std::vector<ComplexD>>& lmd,
1129 std::vector<std::vector<ComplexD>>& lme,
1130 int Nu,
int Nb,
int Nk,
int Nm,
1131 Eigen::MatrixXcd& M)
1134 assert(
Nk%
Nu == 0 &&
Nm%
Nu == 0 );
1136 M = Eigen::MatrixXcd::Zero(
Nk,
Nk);
1139 for (
int u=0; u<
Nu; ++u ) {
1140 for (
int k=0; k<
Nk; ++k ) {
1141 M(k,u+(k/
Nu)*
Nu) = lmd[u][k];
1145 for (
int u=0; u<
Nu; ++u ) {
1146 for (
int k=
Nu; k<
Nk; ++k ) {
1148 M(u+(k/
Nu)*
Nu,k-
Nu) = lme[u][k-
Nu];
1156 std::vector<std::vector<ComplexD>>& lmd,
1157 std::vector<std::vector<ComplexD>>& lme,
1158 int Nu,
int Nb,
int Nk,
int Nm,
1159 Eigen::MatrixXcd& M)
1162 assert(
Nk%
Nu == 0 &&
Nm%
Nu == 0 );
1166 for (
int u=0; u<
Nu; ++u ) {
1167 for (
int k=0; k<
Nk; ++k ) {
1168 lmd[u][k] = M(k,u+(k/
Nu)*
Nu);
1172 for (
int u=0; u<
Nu; ++u ) {
1173 for (
int k=
Nu; k<
Nk; ++k ) {
1174 lme[u][k-
Nu] = M(u+(k/
Nu)*
Nu,k-
Nu);
1184 Eigen::MatrixXcd& Qprod)
1187 Eigen::MatrixXcd Q = Eigen::MatrixXcd::Zero(
Nm,
Nm);
1188 Eigen::MatrixXcd R = Eigen::MatrixXcd::Zero(
Nm,
Nm);
1189 Eigen::MatrixXcd Mtmp = Eigen::MatrixXcd::Zero(
Nm,
Nm);
1192 for (
int i=0; i<
Nm; ++i ) {
1193 Mtmp(i,i) = M(i,i) - Dsh;
1196 Eigen::HouseholderQR<Eigen::MatrixXcd> QRD(Mtmp);
1197 Q = QRD.householderQ();
1220 Mtmp = Eigen::MatrixXcd::Zero(
Nm,
Nm);
1222 for (
int i=0; i<
Nm; ++i) {
1223 for (
int j=0; j<
Nm-(
Nu+1); ++j) {
1224 for (
int k=0; k<
Nu+1+j; ++k) {
1225 Mtmp(i,j) += Qprod(i,k)*Q(k,j);
1229 for (
int i=0; i<
Nm; ++i) {
1230 for (
int j=
Nm-(
Nu+1); j<
Nm; ++j) {
1231 for (
int k=0; k<
Nm; ++k) {
1232 Mtmp(i,j) += Qprod(i,k)*Q(k,j);
1248 Mtmp = Eigen::MatrixXcd::Zero(
Nm,
Nm);
1250 for (
int a=0, i=0, kmax=0; a<
Nu+1; ++a) {
1251 for (
int j=0; j<
Nm-a; ++j) {
1254 if (kmax >
Nm) kmax =
Nm;
1255 for (
int k=i; k<kmax; ++k) {
1256 Mtmp(i,j) += R(i,k)*Q(k,j);
1258 Mtmp(j,i) =
conj(Mtmp(i,j));
1262 for (
int i=0; i<
Nm; ++i) {
1263 Mtmp(i,i) =
real(Mtmp(i,i)) + Dsh;
1282 Eigen::MatrixXd A = Eigen::MatrixXd::Zero(3,3);
1283 Eigen::MatrixXd Q = Eigen::MatrixXd::Zero(3,3);
1284 Eigen::MatrixXd R = Eigen::MatrixXd::Zero(3,3);
1285 Eigen::MatrixXd P = Eigen::MatrixXd::Zero(3,3);
1297 Glog <<
"matrix A before ColPivHouseholder" << std::endl;
1298 for (
int i=0; i<3; i++ ) {
1299 for (
int j=0; j<3; j++ ) {
1300 Glog <<
"A[" << i <<
"," << j <<
"] = " << A(i,j) <<
'\n';
1305 Eigen::ColPivHouseholderQR<Eigen::MatrixXd> QRD(A);
1307 Glog <<
"matrix A after ColPivHouseholder" << std::endl;
1308 for (
int i=0; i<3; i++ ) {
1309 for (
int j=0; j<3; j++ ) {
1310 Glog <<
"A[" << i <<
"," << j <<
"] = " << A(i,j) <<
'\n';
1315 Glog <<
"HouseholderQ with sequence lenth = nonzeroPiviots" << std::endl;
1316 Q = QRD.householderQ().setLength(QRD.nonzeroPivots());
1317 for (
int i=0; i<3; i++ ) {
1318 for (
int j=0; j<3; j++ ) {
1319 Glog <<
"Q[" << i <<
"," << j <<
"] = " << Q(i,j) <<
'\n';
1324 Glog <<
"HouseholderQ with sequence lenth = 1" << std::endl;
1325 Q = QRD.householderQ().setLength(1);
1326 for (
int i=0; i<3; i++ ) {
1327 for (
int j=0; j<3; j++ ) {
1328 Glog <<
"Q[" << i <<
"," << j <<
"] = " << Q(i,j) <<
'\n';
1333 Glog <<
"HouseholderQ with sequence lenth = 2" << std::endl;
1334 Q = QRD.householderQ().setLength(2);
1335 for (
int i=0; i<3; i++ ) {
1336 for (
int j=0; j<3; j++ ) {
1337 Glog <<
"Q[" << i <<
"," << j <<
"] = " << Q(i,j) <<
'\n';
1342 Glog <<
"matrixR" << std::endl;
1344 for (
int i=0; i<3; i++ ) {
1345 for (
int j=0; j<3; j++ ) {
1346 Glog <<
"R[" << i <<
"," << j <<
"] = " << R(i,j) <<
'\n';
1351 Glog <<
"rank = " << QRD.rank() << std::endl;
1352 Glog <<
"threshold = " << QRD.threshold() << std::endl;
1354 Glog <<
"matrixP" << std::endl;
1355 P = QRD.colsPermutation();
1356 for (
int i=0; i<3; i++ ) {
1357 for (
int j=0; j<3; j++ ) {
1358 Glog <<
"P[" << i <<
"," << j <<
"] = " << P(i,j) <<
'\n';
1364 Glog <<
"QR decomposition without column pivoting" << std::endl;
1376 Glog <<
"matrix A before Householder" << std::endl;
1377 for (
int i=0; i<3; i++ ) {
1378 for (
int j=0; j<3; j++ ) {
1379 Glog <<
"A[" << i <<
"," << j <<
"] = " << A(i,j) <<
'\n';
1384 Eigen::HouseholderQR<Eigen::MatrixXd> QRDplain(A);
1386 Glog <<
"HouseholderQ" << std::endl;
1387 Q = QRDplain.householderQ();
1388 for (
int i=0; i<3; i++ ) {
1389 for (
int j=0; j<3; j++ ) {
1390 Glog <<
"Q[" << i <<
"," << j <<
"] = " << Q(i,j) <<
'\n';
1395 Glog <<
"matrix A after Householder" << std::endl;
1396 for (
int i=0; i<3; i++ ) {
1397 for (
int j=0; j<3; j++ ) {
1398 Glog <<
"A[" << i <<
"," << j <<
"] = " << A(i,j) <<
'\n';
1410#undef MAKE_CUDA_COMPLEX
accelerator_inline Grid_simd< S, V > sqrt(const Grid_simd< S, V > &r)
#define MAKE_CUDA_COMPLEX
accelerator_inline sobj eval(const uint64_t ss, const sobj &arg)
Lattice< vobj > real(const Lattice< vobj > &lhs)
Lattice< vobj > imag(const Lattice< vobj > &lhs)
Lattice< vobj > conjugate(const Lattice< vobj > &lhs)
ComplexD innerProduct(const Lattice< vobj > &left, const Lattice< vobj > &right)
RealD norm2(const Lattice< vobj > &arg)
void Grid_unsplit(std::vector< Lattice< Vobj > > &full, Lattice< Vobj > &split)
void Grid_split(std::vector< Lattice< Vobj > > &full, Lattice< Vobj > &split)
#define autoView(l_v, l, mode)
std::complex< RealD > ComplexD
void GlobalSumVector(RealF *, int N)
void show_decomposition()
void calc(std::vector< RealD > &eval, std::vector< Field > &evec, const std::vector< Field > &src, int &Nconv, LanczosType Impl)
IRBLdiagonalisation diagonalisation
void orthogonalize(Field &w, std::vector< Field > &evec, int k, int if_print=0)
void orthogonalize(std::vector< Field > &w, int _Nu, std::vector< Field > &evec, int k, int if_print=0)
void diagonalize_Eigen(std::vector< RealD > &eval, std::vector< std::vector< ComplexD > > &lmd, std::vector< std::vector< ComplexD > > &lme, int Nu, int Nk, int Nm, Eigen::MatrixXcd &Qt, GridBase *grid)
void packHermitBlockTriDiagMatfromEigen(std::vector< std::vector< ComplexD > > &lmd, std::vector< std::vector< ComplexD > > &lme, int Nu, int Nb, int Nk, int Nm, Eigen::MatrixXcd &M)
static RealD normalize(Field &v, int if_print=0)
void reorthogonalize(Field &w, std::vector< Field > &evec, int k)
GridRedBlackCartesian * sf_grid
GridRedBlackCartesian * f_grid
void orthogonalize_blockhead(Field &w, std::vector< Field > &evec, int k, int Nu)
LinearOperatorBase< Field > & _SLinop
LinearOperatorBase< Field > & _Linop
void calc_rbl(std::vector< RealD > &eval, std::vector< Field > &evec, const std::vector< Field > &src, int &Nconv)
void shiftedQRDecompEigen(Eigen::MatrixXcd &M, int Nu, int Nm, RealD Dsh, Eigen::MatrixXcd &Qprod)
void calc_irbl(std::vector< RealD > &eval, std::vector< Field > &evec, const std::vector< Field > &src, int &Nconv)
void diagonalize(std::vector< RealD > &eval, std::vector< std::vector< ComplexD > > &lmd, std::vector< std::vector< ComplexD > > &lme, int Nu, int Nk, int Nm, Eigen::MatrixXcd &Qt, GridBase *grid)
OperatorFunction< Field > & _poly
ImplicitlyRestartedBlockLanczos(LinearOperatorBase< Field > &Linop, LinearOperatorBase< Field > &SLinop, GridRedBlackCartesian *FrbGrid, GridRedBlackCartesian *SFrbGrid, int _mrhs, OperatorFunction< Field > &poly, int _Nstop, int _Nconv_test_interval, int _Nu, int _Nk, int _Nm, RealD _eresid, int _MaxIter, IRBLdiagonalisation _diagonalisation=IRBLdiagonaliseWithEigen)
void exampleQRDecompEigen(void)
void blockwiseStep(std::vector< std::vector< ComplexD > > &lmd, std::vector< std::vector< ComplexD > > &lme, std::vector< Field > &evec, std::vector< Field > &w, std::vector< Field > &w_copy, int b)
void unpackHermitBlockTriDiagMatToEigen(std::vector< std::vector< ComplexD > > &lmd, std::vector< std::vector< ComplexD > > &lme, int Nu, int Nb, int Nk, int Nm, Eigen::MatrixXcd &M)
void orthogonalize_blas(std::vector< Field > &w, std::vector< Field > &evec, int R, int do_print=0)
static bool less_lmd(RealD left, RealD right)
bool saturated(RealD lmd, RealD thrs)
static bool less_pair(std::pair< RealD, Field const * > &left, std::pair< RealD, Field const * > &right)
void push(std::vector< RealD > &lmd, std::vector< Field > &evec, int N)
void push(std::vector< RealD > &lmd, int N)
@ IRBLdiagonaliseWithEigen
@ IRBLdiagonaliseWithDSTEGR