/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/algorithms/iterative/LocalCoherenceLanczos.h Copyright (C) 2015 Author: Christoph Lehner Author: paboyle 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_LOCAL_COHERENCE_IRL_H #define GRID_LOCAL_COHERENCE_IRL_H NAMESPACE_BEGIN(Grid); struct LanczosParams : Serializable { public: GRID_SERIALIZABLE_CLASS_MEMBERS(LanczosParams, ChebyParams, Cheby,/*Chebyshev*/ int, Nstop, /*Vecs in Lanczos must converge Nstop < Nk < Nm*/ int, Nk, /*Vecs in Lanczos seek converge*/ int, Nm, /*Total vecs in Lanczos include restart*/ RealD, resid, /*residual*/ int, MaxIt, RealD, betastp, /* ? */ int, MinRes); // Must restart }; struct LocalCoherenceLanczosParams : Serializable { public: GRID_SERIALIZABLE_CLASS_MEMBERS(LocalCoherenceLanczosParams, bool, doFine, bool, doFineRead, bool, doCoarse, bool, doCoarseRead, LanczosParams, FineParams, LanczosParams, CoarseParams, ChebyParams, Smoother, RealD , coarse_relax_tol, std::vector, blockSize, std::string, config, std::vector < std::complex >, omega, RealD, mass, RealD, M5); }; // Duplicate functionality; ProjectedFunctionHermOp could be used with the trivial function template class ProjectedHermOp : public LinearFunction > > { public: typedef iVector CoarseSiteVector; typedef Lattice CoarseField; typedef Lattice CoarseScalar; // used for inner products on fine field typedef Lattice FineField; LinearOperatorBase &_Linop; Aggregation &_Aggregate; ProjectedHermOp(LinearOperatorBase& linop, Aggregation &aggregate) : _Linop(linop), _Aggregate(aggregate) { }; void operator()(const CoarseField& in, CoarseField& out) { GridBase *FineGrid = _Aggregate.FineGrid; FineField fin(FineGrid); FineField fout(FineGrid); _Aggregate.PromoteFromSubspace(in,fin); std::cout< class ProjectedFunctionHermOp : public LinearFunction > > { public: typedef iVector CoarseSiteVector; typedef Lattice CoarseField; typedef Lattice CoarseScalar; // used for inner products on fine field typedef Lattice FineField; OperatorFunction & _poly; LinearOperatorBase &_Linop; Aggregation &_Aggregate; ProjectedFunctionHermOp(OperatorFunction & poly,LinearOperatorBase& linop, Aggregation &aggregate) : _poly(poly), _Linop(linop), _Aggregate(aggregate) { }; void operator()(const CoarseField& in, CoarseField& out) { GridBase *FineGrid = _Aggregate.FineGrid; FineField fin(FineGrid) ;fin.Checkerboard() =_Aggregate.Checkerboard(); FineField fout(FineGrid);fout.Checkerboard() =_Aggregate.Checkerboard(); _Aggregate.PromoteFromSubspace(in,fin); std::cout< class ImplicitlyRestartedLanczosSmoothedTester : public ImplicitlyRestartedLanczosTester > > { public: typedef iVector CoarseSiteVector; typedef Lattice CoarseField; typedef Lattice CoarseScalar; // used for inner products on fine field typedef Lattice FineField; LinearFunction & _Poly; OperatorFunction & _smoother; LinearOperatorBase &_Linop; Aggregation &_Aggregate; RealD _coarse_relax_tol; ImplicitlyRestartedLanczosSmoothedTester(LinearFunction &Poly, OperatorFunction &smoother, LinearOperatorBase &Linop, Aggregation &Aggregate, RealD coarse_relax_tol=5.0e3) : _smoother(smoother), _Linop(Linop),_Aggregate(Aggregate), _Poly(Poly), _coarse_relax_tol(coarse_relax_tol) { }; int TestConvergence(int j,RealD eresid,CoarseField &B, RealD &eval,RealD evalMaxApprox) { CoarseField v(B); RealD eval_poly = eval; // Apply operator _Poly(B,v); RealD vnum = real(innerProduct(B,v)); // HermOp. RealD vden = norm2(B); RealD vv0 = norm2(v); eval = vnum/vden; v -= eval*B; RealD vv = norm2(v) / ::pow(evalMaxApprox,2.0); std::cout.precision(13); std::cout< nbasis ) eresid = eresid*_coarse_relax_tol; if( (vv class LocalCoherenceLanczos { public: typedef iVector CoarseSiteVector; typedef Lattice CoarseScalar; // used for inner products on fine field typedef Lattice CoarseField; typedef Lattice FineField; protected: GridBase *_CoarseGrid; GridBase *_FineGrid; int _checkerboard; LinearOperatorBase & _FineOp; // FIXME replace Aggregation with vector of fine; the code reuse is too small for // the hassle and complexity of cross coupling. Aggregation _Aggregate; std::vector evals_fine; std::vector evals_coarse; std::vector evec_coarse; public: LocalCoherenceLanczos(GridBase *FineGrid, GridBase *CoarseGrid, LinearOperatorBase &FineOp, int checkerboard) : _CoarseGrid(CoarseGrid), _FineGrid(FineGrid), _Aggregate(CoarseGrid,FineGrid,checkerboard), _FineOp(FineOp), _checkerboard(checkerboard) { evals_fine.resize(0); evals_coarse.resize(0); }; void Orthogonalise(void ) { _Aggregate.Orthogonalise(); } template static RealD normalise(T& v) { RealD nn = norm2(v); nn = ::sqrt(nn); v = v * (1.0/nn); return nn; } void fakeFine(void) { int Nk = nbasis; _Aggregate.subspace.resize(Nk,_FineGrid); _Aggregate.subspace[0]=1.0; _Aggregate.subspace[0].Checkerboard()=_checkerboard; normalise(_Aggregate.subspace[0]); PlainHermOp Op(_FineOp); for(int k=1;k Op(_FineOp); ImplicitlyRestartedLanczosHermOpTester SimpleTester(Op); for(int k=0;k ChebySmooth(cheby_smooth); ProjectedFunctionHermOp ChebyOp (ChebySmooth,_FineOp,_Aggregate); ImplicitlyRestartedLanczosSmoothedTester ChebySmoothTester(ChebyOp,ChebySmooth,_FineOp,_Aggregate,relax); for(int k=0;k Cheby(cheby_parms); FunctionHermOp ChebyOp(Cheby,_FineOp); PlainHermOp Op(_FineOp); evals_fine.resize(Nm); _Aggregate.subspace.resize(Nm,_FineGrid); ImplicitlyRestartedLanczos IRL(ChebyOp,Op,Nstop,Nk,Nm,resid,MaxIt,betastp,MinRes); FineField src(_FineGrid); src=1.0; src.Checkerboard() = _checkerboard; int Nconv; IRL.calc(evals_fine,_Aggregate.subspace,src,Nconv,false); // Shrink down to number saved assert(Nstop>=nbasis); assert(Nconv>=nbasis); evals_fine.resize(nbasis); _Aggregate.subspace.resize(nbasis,_FineGrid); } void calcCoarse(ChebyParams cheby_op,ChebyParams cheby_smooth,RealD relax, int Nstop, int Nk, int Nm,RealD resid, RealD MaxIt, RealD betastp, int MinRes) { Chebyshev Cheby(cheby_op); ProjectedHermOp Op(_FineOp,_Aggregate); ProjectedFunctionHermOp ChebyOp (Cheby,_FineOp,_Aggregate); ////////////////////////////////////////////////////////////////////////////////////////////////// // create a smoother and see if we can get a cheap convergence test and smooth inside the IRL ////////////////////////////////////////////////////////////////////////////////////////////////// Chebyshev ChebySmooth(cheby_smooth); ImplicitlyRestartedLanczosSmoothedTester ChebySmoothTester(ChebyOp,ChebySmooth,_FineOp,_Aggregate,relax); evals_coarse.resize(Nm); evec_coarse.resize(Nm,_CoarseGrid); CoarseField src(_CoarseGrid); src=1.0; ImplicitlyRestartedLanczos IRL(ChebyOp,ChebyOp,ChebySmoothTester,Nstop,Nk,Nm,resid,MaxIt,betastp,MinRes); int Nconv=0; IRL.calc(evals_coarse,evec_coarse,src,Nconv,false); assert(Nconv>=Nstop); evals_coarse.resize(Nstop); evec_coarse.resize (Nstop,_CoarseGrid); for (int i=0;i