Grid 0.7.0
OneFlavourRational.h
Go to the documentation of this file.
1 /*************************************************************************************
2
3 Grid physics library, www.github.com/paboyle/Grid
4
5 Source file: ./lib/qcd/action/pseudofermion/OneFlavourRational.h
6
7 Copyright (C) 2015
8
9Author: Peter Boyle <paboyle@ph.ed.ac.uk>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License along
22 with this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25 See the full license in the file "LICENSE" in the top level distribution directory
26 *************************************************************************************/
27 /* END LEGAL */
28#ifndef QCD_PSEUDOFERMION_ONE_FLAVOUR_RATIONAL_H
29#define QCD_PSEUDOFERMION_ONE_FLAVOUR_RATIONAL_H
30
32
34 // One flavour rational
36
37 // S_f = chi^dag * N(M^dag*M)/D(M^dag*M) * chi
38 //
39 // Here, M is some operator
40 // N and D makeup the rat. poly
41 //
42
43 template<class Impl>
44 class OneFlavourRationalPseudoFermionAction : public Action<typename Impl::GaugeField> {
45 public:
47
50
55
56 private:
57
58 FermionOperator<Impl> & FermOp;// the basic operator
59
60 // NOT using "Nroots"; IroIro is -- perhaps later, but this wasn't good for us historically
61 // and hasenbusch works better
62
63 FermionField Phi; // the pseudo fermion field for this trajectory
64
65 public:
66
68 Params & p
69 ) : FermOp(Op), Phi(Op.FermionGrid()), param(p)
70 {
71 AlgRemez remez(param.lo,param.hi,param.precision);
72
73 // MdagM^(+- 1/2)
74 std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
75 remez.generateApprox(param.degree,1,2);
76 PowerHalf.Init(remez,param.tolerance,false);
77 PowerNegHalf.Init(remez,param.tolerance,true);
78
79 // MdagM^(+- 1/4)
80 std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/4)"<<std::endl;
81 remez.generateApprox(param.degree,1,4);
82 PowerQuarter.Init(remez,param.tolerance,false);
83 PowerNegQuarter.Init(remez,param.tolerance,true);
84 };
85
86 virtual std::string action_name(){return "OneFlavourRationalPseudoFermionAction";}
87
88 virtual std::string LogParameters(){
89 std::stringstream sstream;
90 sstream << GridLogMessage << "["<<action_name()<<"] Low :" << param.lo << std::endl;
91 sstream << GridLogMessage << "["<<action_name()<<"] High :" << param.hi << std::endl;
92 sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter << std::endl;
93 sstream << GridLogMessage << "["<<action_name()<<"] Tolerance :" << param.tolerance << std::endl;
94 sstream << GridLogMessage << "["<<action_name()<<"] Degree :" << param.degree << std::endl;
95 sstream << GridLogMessage << "["<<action_name()<<"] Precision :" << param.precision << std::endl;
96 return sstream.str();
97 }
98
99
100
101 virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) {
102
103
104 // P(phi) = e^{- phi^dag (MdagM)^-1/2 phi}
105 // = e^{- phi^dag (MdagM)^-1/4 (MdagM)^-1/4 phi}
106 // Phi = Mdag^{1/4} eta
107 // P(eta) = e^{- eta^dag eta}
108 //
109 // e^{x^2/2 sig^2} => sig^2 = 0.5.
110 //
111 // So eta should be of width sig = 1/sqrt(2).
112
113 RealD scale = std::sqrt(0.5);
114
115 FermionField eta(FermOp.FermionGrid());
116
117 gaussian(pRNG,eta);
118
119 FermOp.ImportGauge(U);
120
121 // mutishift CG
124 msCG(MdagMOp,eta,Phi);
125
126 Phi=Phi*scale;
127
128 };
129
131 // S = phi^dag (Mdag M)^-1/2 phi
133 virtual RealD S(const GaugeField &U) {
134
135 FermOp.ImportGauge(U);
136
137 FermionField Y(FermOp.FermionGrid());
138
140
142
143 msCG(MdagMOp,Phi,Y);
144
145 auto grid = FermOp.FermionGrid();
146 auto r=rand();
147 grid->Broadcast(0,r);
148 if ( (r%param.BoundsCheckFreq)==0 ) {
149 FermionField gauss(FermOp.FermionGrid());
150 gauss = Phi;
151 HighBoundCheck(MdagMOp,gauss,param.hi);
152 InverseSqrtBoundsCheck(param.MaxIter,param.tolerance*100,MdagMOp,gauss,PowerNegHalf);
153 }
154
155
156 RealD action = norm2(Y);
157 std::cout << GridLogMessage << "Pseudofermion action FIXME -- is -1/4 solve or -1/2 solve faster??? "<<action<<std::endl;
158 return action;
159 };
160
162 // Need
163 // dS_f/dU = chi^dag d[N/D] chi
164 //
165 // N/D is expressed as partial fraction expansion:
166 //
167 // a0 + \sum_k ak/(M^dagM + bk)
168 //
169 // d[N/D] is then
170 //
171 // \sum_k -ak [M^dagM+bk]^{-1} [ dM^dag M + M^dag dM ] [M^dag M + bk]^{-1}
172 //
173 // Need
174 // Mf Phi_k = [MdagM+bk]^{-1} Phi
175 // Mf Phi = \sum_k ak [MdagM+bk]^{-1} Phi
176 //
177 // With these building blocks
178 //
179 // dS/dU = \sum_k -ak Mf Phi_k^dag [ dM^dag M + M^dag dM ] Mf Phi_k
180 // S = innerprodReal(Phi,Mf Phi);
182 virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
183
184 const int Npole = PowerNegHalf.poles.size();
185
186 std::vector<FermionField> MPhi_k (Npole,FermOp.FermionGrid());
187
188 FermionField X(FermOp.FermionGrid());
189 FermionField Y(FermOp.FermionGrid());
190
191 GaugeField tmp(FermOp.GaugeGrid());
192
193 FermOp.ImportGauge(U);
194
196
198
199 msCG(MdagMOp,Phi,MPhi_k);
200
201 dSdU = Zero();
202 for(int k=0;k<Npole;k++){
203
204 RealD ak = PowerNegHalf.residues[k];
205
206 X = MPhi_k[k];
207
208 FermOp.M(X,Y);
209
210 FermOp.MDeriv(tmp , Y, X,DaggerNo ); dSdU=dSdU+ak*tmp;
211 FermOp.MDeriv(tmp , X, Y,DaggerYes); dSdU=dSdU+ak*tmp;
212
213 }
214
215 //dSdU = Ta(dSdU);
216
217 };
218 };
219
221
222#endif
void InverseSqrtBoundsCheck(int MaxIter, double tol, LinearOperatorBase< Field > &HermOp, Field &GaussNoise, MultiShiftFunction &PowerNegHalf)
Definition Bounds.h:42
void HighBoundCheck(LinearOperatorBase< Field > &HermOp, Field &Phi, RealD hi)
Definition Bounds.h:6
RealD norm2(const Lattice< vobj > &arg)
void gaussian(GridParallelRNG &rng, Lattice< vobj > &l)
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
static constexpr int DaggerYes
Definition QCD.h:70
static constexpr int DaggerNo
Definition QCD.h:69
double RealD
Definition Simd.h:61
static INTERNAL_PRECISION U
Definition Zolotarev.cc:230
Base class for all actions.
Definition ActionBase.h:64
double generateApprox(int num_degree, int den_degree, unsigned long power_num, unsigned long power_den, int a_len, double *a_param, int *a_pow)
Definition Remez.cc:114
virtual std::string LogParameters()
Print the parameters of the action.
virtual RealD S(const GaugeField &U)
Evaluate this action with the given gauge field.
virtual std::string action_name()
Report the name of the action.
virtual void deriv(const GaugeField &U, GaugeField &dSdU)
virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG &pRNG)
Refresh pseudofermion fields.
OneFlavourRationalPseudoFermionAction(FermionOperator< Impl > &Op, Params &p)
Definition Simd.h:194