/************************************************************************************* 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(_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 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 == IRLdiagonaliseWithDSTEGR ) { clog << "Diagonalisation is DSTEGR "<< std::endl; } else if ( diagonalisation == IRLdiagonaliseWithQR ) { clog << "Diagonalisation is QR "<< std::endl; } else if ( diagonalisation == IRLdiagonaliseWithEigen ) { clog << "Diagonalisation is Eigen "<< std::endl; } 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); Eigen::MatrixXcd Qt = 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); int k1 = 1; int k2 = Nk; Nconv = 0; RealD beta_k; // Set initial vector for (int i=0; i=Nstop ){ goto converged; } } // end of iter loop clog <<"**************************************************************************"<< std::endl; std::cout<< GridLogError << fname + " NOT converged."; clog <<"**************************************************************************"<< std::endl; abort(); converged: // Sorting eval.resize(Nconv); evec.resize(Nconv,grid); 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; clog << "A: b = " << b << std::endl; // 3. wk:=Avk−βkv_{k−1} for (int k=L, u=0; k0) { clog << "B: b = " << b << std::endl; for (int u=0; u