/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/algorithms/approx/Chebyshev.h Copyright (C) 2015 Author: Peter Boyle Author: paboyle Author: Christoph Lehner 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 NAMESPACE_BEGIN(Grid); struct ChebyParams : Serializable { GRID_SERIALIZABLE_CLASS_MEMBERS(ChebyParams, RealD, alpha, RealD, beta, int, Npoly); }; //////////////////////////////////////////////////////////////////////////////////////////// // Generic Chebyshev approximations //////////////////////////////////////////////////////////////////////////////////////////// template class Chebyshev : public OperatorFunction { private: std::vector Coeffs; int order; RealD hi; RealD lo; public: void csv(std::ostream &out){ RealD diff = hi-lo; RealD delta = diff*1.0e-9; for (RealD x=lo; 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::quiet_NaN(); } // Implement the required interface void operator() (LinearOperatorBase &Linop, const Field &in, Field &out) { GridBase *grid=in._grid; // std::cout << "Chevyshef(): in._grid="< &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