/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/algorithms/iterative/PrecGeneralisedConjugateResidual.h Copyright (C) 2015 Author: Azusa Yamaguchi Author: Peter Boyle 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_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_BEGIN(Grid); template class PrecGeneralisedConjugateResidual : public OperatorFunction { public: RealD Tolerance; Integer MaxIterations; int verbose; int mmax; int nstep; int steps; GridStopWatch PrecTimer; GridStopWatch MatTimer; GridStopWatch LinalgTimer; 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); PrecTimer.Reset(); MatTimer.Reset(); LinalgTimer.Reset(); GridStopWatch SolverTimer; SolverTimer.Start(); 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 ////////////////////////////////// MatTimer.Start(); Linop.HermOpAndNorm(psi,Az,zAz,zAAz); MatTimer.Stop(); r=src-Az; ///////////////////// // p = Prec(r) ///////////////////// PrecTimer.Start(); Preconditioner(r,z); PrecTimer.Stop(); MatTimer.Start(); Linop.HermOp(z,tmp); MatTimer.Stop(); ttmp=tmp; tmp=tmp-r; /* 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; } }; NAMESPACE_END(Grid); #endif