/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/algorithms/approx/Chebyshev.h Copyright (C) 2015 Author: Peter Boyle 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_CHEBYSHEV_H #define GRID_CHEBYSHEV_H #include #include namespace Grid { //////////////////////////////////////////////////////////////////////////////////////////// // Simple general polynomial with user supplied coefficients //////////////////////////////////////////////////////////////////////////////////////////// template class HermOpOperatorFunction : public OperatorFunction { void operator() (LinearOperatorBase &Linop, const Field &in, Field &out) { Linop.HermOp(in,out); }; }; template class Polynomial : public OperatorFunction { private: std::vector Coeffs; public: Polynomial(std::vector &_Coeffs) : Coeffs(_Coeffs) { }; // Implement the required interface void operator() (LinearOperatorBase &Linop, const Field &in, Field &out) { Field AtoN(in._grid); Field Mtmp(in._grid); AtoN = in; out = AtoN*Coeffs[0]; // std::cout <<"Poly in " < class Chebyshev : public OperatorFunction { private: std::vector Coeffs; int order; RealD hi; RealD lo; public: void csv(std::ostream &out){ RealD diff = hi-lo; for (RealD x=lo-0.2*diff; x U(M); std::vector a(M); std::vector g(M); for(int n=0;n<=M;n++){ U[n] = std::sin((n+1)*std::acos(lmax))/std::sin(std::acos(lmax)); sumUsq += U[n]*U[n]; } sumUsq = std::sqrt(sumUsq); for(int i=1;i<=M;i++){ a[i] = U[i]/sumUsq; } g[0] = 1.0; for(int m=1;m<=M;m++){ g[m] = 0; for(int i=0;i<=M-m;i++){ g[m]+= a[i]*a[m+i]; } } for(int m=1;m<=M;m++){ Coeffs[m]*=g[m]; } } RealD approx(RealD x) // Convenience for plotting the approximation { RealD Tn; RealD Tnm; RealD Tnp; RealD y=( x-0.5*(hi+lo))/(0.5*(hi-lo)); RealD T0=1; RealD T1=y; RealD sum; sum = 0.5*Coeffs[0]*T0; sum+= Coeffs[1]*T1; Tn =T1; Tnm=T0; for(int i=2;i &Linop, const Field &in, Field &out) { GridBase *grid=in._grid; int vol=grid->gSites(); Field T0(grid); T0 = in; Field T1(grid); Field T2(grid); Field y(grid); Field *Tnm = &T0; Field *Tn = &T1; Field *Tnp = &T2; // Tn=T1 = (xscale M + mscale)in RealD xscale = 2.0/(hi-lo); RealD mscale = -(hi+lo)/(hi-lo); Linop.HermOp(T0,y); T1=y*xscale+in*mscale; // sum = .5 c[0] T0 + c[1] T1 out = (0.5*Coeffs[0])*T0 + Coeffs[1]*T1; for(int n=2;n class ChebyshevLanczos : public Chebyshev { private: std::vector Coeffs; int order; RealD alpha; RealD beta; RealD mu; public: ChebyshevLanczos(RealD _alpha,RealD _beta,RealD _mu,int _order) : alpha(_alpha), beta(_beta), mu(_mu) { order=_order; Coeffs.resize(order); for(int i=0;i<_order;i++){ Coeffs[i] = 0.0; } Coeffs[order-1]=1.0; }; void csv(std::ostream &out){ for (RealD x=-1.2*alpha; x<1.2*alpha; x+=(2.0*alpha)/10000) { RealD f = approx(x); out<< x<<" "< &Linop, const Field &in, Field &out) { GridBase *grid=in._grid; Field tmp(grid); RealD aa= alpha*alpha; RealD bb= beta * beta; Linop.HermOp(in,out); out = out - mu*in; Linop.HermOp(out,tmp); tmp = tmp - mu * out; out = (2.0/ (aa-bb) ) * tmp - ((aa+bb)/(aa-bb))*in; }; // Implement the required interface void operator() (LinearOperatorBase &Linop, const Field &in, Field &out) { GridBase *grid=in._grid; int vol=grid->gSites(); Field T0(grid); T0 = in; Field T1(grid); Field T2(grid); Field y(grid); Field *Tnm = &T0; Field *Tn = &T1; Field *Tnp = &T2; // Tn=T1 = (xscale M )*in AminusMuSq(Linop,T0,T1); // sum = .5 c[0] T0 + c[1] T1 out = (0.5*Coeffs[0])*T0 + Coeffs[1]*T1; for(int n=2;n