/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/algorithms/iterative/MADWF.h Copyright (C) 2015 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 */ #pragma once NAMESPACE_BEGIN(Grid); template X=0> inline void convert(const Fieldi &from,Fieldo &to) { precisionChange(to,from); } template X=0> inline void convert(const Fieldi &from,Fieldo &to) { to=from; } struct MADWFinnerIterCallbackBase{ virtual void operator()(const RealD current_resid){} virtual ~MADWFinnerIterCallbackBase(){} }; template class MADWF { private: typedef typename Matrixo::FermionField FermionFieldo; typedef typename Matrixi::FermionField FermionFieldi; PVinverter & PauliVillarsSolvero;// For the outer field SchurSolver & SchurSolveri; // For the inner approx field Guesser & Guesseri; // To deflate the inner approx solves Matrixo & Mato; // Action object for outer Matrixi & Mati; // Action object for inner RealD target_resid; int maxiter; //operator() is called on "callback" at the end of every inner iteration. This allows for example the adjustment of the inner //tolerance to speed up subsequent iteration MADWFinnerIterCallbackBase* callback; public: MADWF(Matrixo &_Mato, Matrixi &_Mati, PVinverter &_PauliVillarsSolvero, SchurSolver &_SchurSolveri, Guesser & _Guesseri, RealD resid, int _maxiter, MADWFinnerIterCallbackBase* _callback = NULL) : Mato(_Mato),Mati(_Mati), SchurSolveri(_SchurSolveri), PauliVillarsSolvero(_PauliVillarsSolvero),Guesseri(_Guesseri), callback(_callback) { target_resid=resid; maxiter =_maxiter; }; void operator() (const FermionFieldo &src,FermionFieldo &sol5) { std::cout << GridLogMessage<< " ************************************************" << std::endl; std::cout << GridLogMessage<< " MADWF-like algorithm " << std::endl; std::cout << GridLogMessage<< " ************************************************" << std::endl; FermionFieldi c0i(Mati.GaugeGrid()); // 4d FermionFieldi y0i(Mati.GaugeGrid()); // 4d FermionFieldo c0 (Mato.GaugeGrid()); // 4d FermionFieldo y0 (Mato.GaugeGrid()); // 4d FermionFieldo A(Mato.FermionGrid()); // Temporary outer FermionFieldo B(Mato.FermionGrid()); // Temporary outer FermionFieldo b(Mato.FermionGrid()); // 5d source FermionFieldo c(Mato.FermionGrid()); // PVinv source; reused so store FermionFieldo defect(Mato.FermionGrid()); // 5d source FermionFieldi ci(Mati.FermionGrid()); FermionFieldi yi(Mati.FermionGrid()); FermionFieldi xi(Mati.FermionGrid()); FermionFieldi srci(Mati.FermionGrid()); FermionFieldi Ai(Mati.FermionGrid()); RealD m=Mati.Mass(); /////////////////////////////////////// //Import source, include Dminus factors /////////////////////////////////////// GridBase *src_grid = src.Grid(); assert( (src_grid == Mato.GaugeGrid()) || (src_grid == Mato.FermionGrid())); if ( src_grid == Mato.GaugeGrid() ) { Mato.ImportPhysicalFermionSource(src,b); } else { b=src; } std::cout << GridLogMessage << " src " <