#ifndef GRID_PREC_GCR_H #define GRID_PREC_GCR_H /////////////////////////////////////////////////////////////////////////////////////////////////////// //VPGCR Abe and Zhang, 2005. //INTERNATIONAL JOURNAL OF NUMERICAL ANALYSIS AND MODELING //Computing and Information Volume 2, Number 2, Pages 147-161 //NB. Likely not original reference since they are focussing on a preconditioner variant. // but VPGCR was nicely written up in their paper /////////////////////////////////////////////////////////////////////////////////////////////////////// namespace Grid { template class PrecGeneralisedConjugateResidual : public OperatorFunction { public: RealD Tolerance; Integer MaxIterations; int verbose; int mmax; int nstep; int steps; LinearFunction &Preconditioner; PrecGeneralisedConjugateResidual(RealD tol,Integer maxit,LinearFunction &Prec,int _mmax,int _nstep) : Tolerance(tol), MaxIterations(maxit), Preconditioner(Prec), mmax(_mmax), nstep(_nstep) { verbose=1; }; void operator() (LinearOperatorBase &Linop,const Field &src, Field &psi){ psi=zero; RealD cp, ssq,rsq; ssq=norm2(src); rsq=Tolerance*Tolerance*ssq; Field r(src._grid); steps=0; for(int k=0;k &Linop,const Field &src, Field &psi,RealD rsq){ RealD cp; RealD a, b, c, d; RealD zAz, zAAz; RealD rAq, rq; GridBase *grid = src._grid; Field r(grid); Field z(grid); Field tmp(grid); Field ttmp(grid); Field Az(grid); //////////////////////////////// // history for flexible orthog //////////////////////////////// std::vector q(mmax,grid); std::vector p(mmax,grid); std::vector qq(mmax); ////////////////////////////////// // initial guess x0 is taken as nonzero. // r0=src-A x0 = src ////////////////////////////////// Linop.HermOpAndNorm(psi,Az,zAz,zAAz); r=src-Az; ///////////////////// // p = Prec(r) ///////////////////// Preconditioner(r,z); std::cout<(mmax-1))?(mmax-1):(kp); // if more than mmax done, we orthog all mmax history. for(int back=0;back=0); b=-real(innerProduct(q[peri_back],Az))/qq[peri_back]; p[peri_kp]=p[peri_kp]+b*p[peri_back]; q[peri_kp]=q[peri_kp]+b*q[peri_back]; } qq[peri_kp]=norm2(q[peri_kp]); // could use axpy_norm } assert(0); // never reached return cp; } }; } #endif