/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/algorithms/iterative/ImplicitlyRestartedBlockLanczos.h Copyright (C) 2015 Author: Peter Boyle Author: Chulwoo Jung Author: Yong-Chull Jang Author: Guido Cossu This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. See the full license in the file "LICENSE" in the top level distribution directory *************************************************************************************/ /* END LEGAL */ #ifndef GRID_IRBL_H #define GRID_IRBL_H #include //memset #define clog std::cout << GridLogMessage namespace Grid { ///////////////////////////////////////////////////////////// // Implicitly restarted block lanczos ///////////////////////////////////////////////////////////// template class ImplicitlyRestartedBlockLanczos { private: std::string cname = std::string("ImplicitlyRestartedBlockLanczos"); int MaxIter; // Max iterations int Nstop; // Number of evecs checked for convergence int Nu; // Numbeer of vecs in the unit block int Nk; // Number of converged sought int Nm; // total number of vectors int Nblock_k; // Nk/Nu int Nblock_m; // Nm/Nu RealD eresid; IRLdiagonalisation diagonalisation; //////////////////////////////////// // Embedded objects //////////////////////////////////// SortEigen _sort; LinearOperatorBase &_Linop; OperatorFunction &_poly; ///////////////////////// // Constructor ///////////////////////// public: ImplicitlyRestartedBlockLanczos(LinearOperatorBase &Linop, // op OperatorFunction & poly, // polynomial int _Nstop, // really sought vecs int _Nu, // vecs in the unit block int _Nk, // sought vecs int _Nm, // total vecs RealD _eresid, // resid in lmd deficit int _MaxIter, // Max iterations IRLdiagonalisation _diagonalisation = IRLdiagonaliseWithEigen) : _Linop(Linop), _poly(poly), Nstop(_Nstop), Nu(_Nu), Nk(_Nk), Nm(_Nm), Nblock_m(_Nm/_Nu), Nblock_k(_Nk/_Nu), //eresid(_eresid), MaxIter(10), eresid(_eresid), MaxIter(_MaxIter), diagonalisation(_diagonalisation) { assert( (Nk%Nu==0) && (Nm%Nu==0) ); }; //////////////////////////////// // Helpers //////////////////////////////// static RealD normalize(Field& v) { RealD nn = norm2(v); nn = sqrt(nn); v = v * (1.0/nn); return nn; } void orthogonalize(Field& w, std::vector& evec, int k) { typedef typename Field::scalar_type MyComplex; MyComplex ip; for(int j=0; j& evec, int k, int Nu) { typedef typename Field::scalar_type MyComplex; MyComplex ip; for(int j=0; j K P = M − K † Compute the factorization AVM = VM HM + fM eM repeat Q=I for i = 1,...,P do QiRi =HM −θiI Q = QQi H M = Q †i H M Q i end for βK =HM(K+1,K) σK =Q(M,K) r=vK+1βK +rσK VK =VM(1:M)Q(1:M,1:K) HK =HM(1:K,1:K) →AVK =VKHK +fKe†K † Extend to an M = K + P step factorization AVM = VMHM + fMeM until convergence */ void calc(std::vector& eval, std::vector& evec, const std::vector& src, int& Nconv) { std::string fname = std::string(cname+"::calc()"); GridBase *grid = evec[0]._grid; assert(grid == src[0]._grid); assert( Nu = src.size() ); clog << std::string(74,'*') << std::endl; clog << fname + " starting iteration 0 / "<< MaxIter<< std::endl; clog << std::string(74,'*') << std::endl; clog <<" -- seek Nk = "<< Nk <<" vectors"<< std::endl; clog <<" -- accept Nstop = "<< Nstop <<" vectors"<< std::endl; clog <<" -- total Nm = "<< Nm <<" vectors"<< std::endl; clog <<" -- size of eval = "<< eval.size() << std::endl; clog <<" -- size of evec = "<< evec.size() << std::endl; if ( diagonalisation == IRLdiagonaliseWithEigen ) { clog << "Diagonalisation is Eigen "<< std::endl; } else { abort(); } clog << std::string(74,'*') << std::endl; assert(Nm == evec.size() && Nm == eval.size()); std::vector> lmd(Nu,std::vector(Nm,0.0)); std::vector> lme(Nu,std::vector(Nm,0.0)); std::vector> lmd2(Nu,std::vector(Nm,0.0)); std::vector> lme2(Nu,std::vector(Nm,0.0)); std::vector eval2(Nm); std::vector resid(Nk); Eigen::MatrixXcd Qt = Eigen::MatrixXcd::Zero(Nm,Nm); Eigen::MatrixXcd Q = Eigen::MatrixXcd::Zero(Nm,Nm); std::vector Iconv(Nm); std::vector B(Nm,grid); // waste of space replicating std::vector f(Nu,grid); std::vector f_copy(Nu,grid); Field v(grid); Nconv = 0; RealD beta_k; // set initial vector for (int i=0; i=Nstop ){ goto converged; } for(int i=0; i>& lmd, std::vector>& lme, std::vector& evec, std::vector& w, std::vector& w_copy, int b) { const RealD tiny = 1.0e-20; int Nu = w.size(); int Nm = evec.size(); assert( b < Nm/Nu ); // converts block index to full indicies for an interval [L,R) int L = Nu*b; int R = Nu*(b+1); Real beta; // 3. wk:=Avk−βkv_{k−1} for (int k=L, u=0; k0) { for (int u=0; u>& lmd, std::vector>& lme, int Nu, int Nb, int Nk, int Nm, Eigen::MatrixXcd& M) { //clog << "packHermitBlockTriDiagMatfromEigen() begin" << '\n'; assert( Nk%Nu == 0 && Nm%Nu == 0 ); assert( Nk <= Nm ); // rearrange for ( int u=0; u QRD(Mtmp); Q = QRD.householderQ(); R = QRD.matrixQR(); // upper triangular part is the R matrix. // lower triangular part used to represent series // of Q sequence. // equivalent operation of Qprod *= Q //M = Eigen::MatrixXcd::Zero(Nm,Nm); //for (int i=0; i Nm) kmax = Nm; for (int k=i; ki) M(i,j) = conj(M(j,i)); // if (i-j > Nu || j-i > Nu) M(i,j) = 0.; // } //} //clog << "shiftedQRDecompEigen() end" << endl; } void exampleQRDecompEigen(void) { Eigen::MatrixXd A = Eigen::MatrixXd::Zero(3,3); Eigen::MatrixXd Q = Eigen::MatrixXd::Zero(3,3); Eigen::MatrixXd R = Eigen::MatrixXd::Zero(3,3); Eigen::MatrixXd P = Eigen::MatrixXd::Zero(3,3); A(0,0) = 12.0; A(0,1) = -51.0; A(0,2) = 4.0; A(1,0) = 6.0; A(1,1) = 167.0; A(1,2) = -68.0; A(2,0) = -4.0; A(2,1) = 24.0; A(2,2) = -41.0; clog << "matrix A before ColPivHouseholder" << std::endl; for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "A[" << i << "," << j << "] = " << A(i,j) << '\n'; } } clog << std::endl; Eigen::ColPivHouseholderQR QRD(A); clog << "matrix A after ColPivHouseholder" << std::endl; for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "A[" << i << "," << j << "] = " << A(i,j) << '\n'; } } clog << std::endl; clog << "HouseholderQ with sequence lenth = nonzeroPiviots" << std::endl; Q = QRD.householderQ().setLength(QRD.nonzeroPivots()); for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "Q[" << i << "," << j << "] = " << Q(i,j) << '\n'; } } clog << std::endl; clog << "HouseholderQ with sequence lenth = 1" << std::endl; Q = QRD.householderQ().setLength(1); for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "Q[" << i << "," << j << "] = " << Q(i,j) << '\n'; } } clog << std::endl; clog << "HouseholderQ with sequence lenth = 2" << std::endl; Q = QRD.householderQ().setLength(2); for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "Q[" << i << "," << j << "] = " << Q(i,j) << '\n'; } } clog << std::endl; clog << "matrixR" << std::endl; R = QRD.matrixR(); for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "R[" << i << "," << j << "] = " << R(i,j) << '\n'; } } clog << std::endl; clog << "rank = " << QRD.rank() << std::endl; clog << "threshold = " << QRD.threshold() << std::endl; clog << "matrixP" << std::endl; P = QRD.colsPermutation(); for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "P[" << i << "," << j << "] = " << P(i,j) << '\n'; } } clog << std::endl; clog << "QR decomposition without column pivoting" << std::endl; A(0,0) = 12.0; A(0,1) = -51.0; A(0,2) = 4.0; A(1,0) = 6.0; A(1,1) = 167.0; A(1,2) = -68.0; A(2,0) = -4.0; A(2,1) = 24.0; A(2,2) = -41.0; clog << "matrix A before Householder" << std::endl; for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "A[" << i << "," << j << "] = " << A(i,j) << '\n'; } } clog << std::endl; Eigen::HouseholderQR QRDplain(A); clog << "HouseholderQ" << std::endl; Q = QRDplain.householderQ(); for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "Q[" << i << "," << j << "] = " << Q(i,j) << '\n'; } } clog << std::endl; clog << "matrix A after Householder" << std::endl; for ( int i=0; i<3; i++ ) { for ( int j=0; j<3; j++ ) { clog << "A[" << i << "," << j << "] = " << A(i,j) << '\n'; } } clog << std::endl; } }; } #undef clog #endif