Grid 0.7.0
GeneralEvenOddRationalRatio.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/GeneralEvenOddRationalRatio.h
6
7 Copyright (C) 2015
8
9 Author: Christopher Kelly <ckelly@bnl.gov>
10 Author: Peter Boyle <paboyle@ph.ed.ac.uk>
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License along
23 with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
26 See the full license in the file "LICENSE" in the top level distribution directory
27 *************************************************************************************/
28 /* END LEGAL */
29#ifndef QCD_PSEUDOFERMION_GENERAL_EVEN_ODD_RATIONAL_RATIO_H
30#define QCD_PSEUDOFERMION_GENERAL_EVEN_ODD_RATIONAL_RATIO_H
31
33
35 // Generic rational approximation for ratios of operators
37
38 /* S_f = -log( det( [M^dag M]/[V^dag V] )^{1/inv_pow} )
39 = chi^dag ( [M^dag M]/[V^dag V] )^{-1/inv_pow} chi\
40 = chi^dag ( [V^dag V]^{-1/2} [M^dag M] [V^dag V]^{-1/2} )^{-1/inv_pow} chi\
41 = chi^dag [V^dag V]^{1/(2*inv_pow)} [M^dag M]^{-1/inv_pow} [V^dag V]^{1/(2*inv_pow)} chi\
42
43 S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
44
45 BIG WARNING:
46 Here V^dag V is referred to in this code as the "numerator" operator and M^dag M is the *denominator* operator.
47 this refers to their position in the pseudofermion action, which is the *inverse* of what appears in the determinant
48 Thus for DWF the numerator operator is the Pauli-Villars operator
49
50 Here P/Q \sim R_{1/(2*inv_pow)} ~ (V^dagV)^{1/(2*inv_pow)}
51 Here N/D \sim R_{-1/inv_pow} ~ (M^dagM)^{-1/inv_pow}
52 */
53
54 template<class Impl>
55 class GeneralEvenOddRatioRationalPseudoFermionAction : public Action<typename Impl::GaugeField> {
56 public:
57
59
63 //For action evaluation
64 MultiShiftFunction ApproxPowerAction ; //rational approx for X^{1/inv_pow}
65 MultiShiftFunction ApproxNegPowerAction; //rational approx for X^{-1/inv_pow}
66 MultiShiftFunction ApproxHalfPowerAction; //rational approx for X^{1/(2*inv_pow)}
67 MultiShiftFunction ApproxNegHalfPowerAction; //rational approx for X^{-1/(2*inv_pow)}
68
69 //For the MD integration
70 MultiShiftFunction ApproxPowerMD ; //rational approx for X^{1/inv_pow}
71 MultiShiftFunction ApproxNegPowerMD; //rational approx for X^{-1/inv_pow}
72 MultiShiftFunction ApproxHalfPowerMD; //rational approx for X^{1/(2*inv_pow)}
73 MultiShiftFunction ApproxNegHalfPowerMD; //rational approx for X^{-1/(2*inv_pow)}
74
75 private:
76
77 FermionOperator<Impl> & NumOp;// the basic operator
78 FermionOperator<Impl> & DenOp;// the basic operator
79 FermionField PhiEven; // the pseudo fermion field for this trajectory
80 FermionField PhiOdd; // the pseudo fermion field for this trajectory
81
82 //Generate the approximation to x^{1/inv_pow} (->approx) and x^{-1/inv_pow} (-> approx_inv) by an approx_degree degree rational approximation
83 //CG_tolerance is used to issue a warning if the approximation error is larger than the tolerance of the CG and is otherwise just stored in the MultiShiftFunction for use by the multi-shift
84 static void generateApprox(MultiShiftFunction &approx, MultiShiftFunction &approx_inv, int inv_pow, int approx_degree, double CG_tolerance, AlgRemez &remez){
85 std::cout<<GridLogMessage << "Generating degree "<< approx_degree<<" approximation for x^(1/" << inv_pow << ")"<<std::endl;
86 double error = remez.generateApprox(approx_degree,1,inv_pow);
87 if(error > CG_tolerance)
88 std::cout<<GridLogMessage << "WARNING: Remez approximation has a larger error " << error << " than the CG tolerance " << CG_tolerance << "! Try increasing the number of poles" << std::endl;
89
90 approx.Init(remez, CG_tolerance,false);
91 approx_inv.Init(remez, CG_tolerance,true);
92 }
93
94
95 protected:
96 static constexpr bool Numerator = true;
97 static constexpr bool Denominator = false;
98
99 //Allow derived classes to override the multishift CG
100 virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionField &in, FermionField &out){
101 SchurDifferentiableOperator<Impl> schurOp(numerator ? NumOp : DenOp);
102 ConjugateGradientMultiShift<FermionField> msCG(MaxIter, approx);
103 msCG(schurOp,in, out);
104 }
105 virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionField &in, std::vector<FermionField> &out_elems, FermionField &out){
106 SchurDifferentiableOperator<Impl> schurOp(numerator ? NumOp : DenOp);
107 ConjugateGradientMultiShift<FermionField> msCG(MaxIter, approx);
108 msCG(schurOp,in, out_elems, out);
109 }
110 //Allow derived classes to override the gauge import
111 virtual void ImportGauge(const GaugeField &U){
112 NumOp.ImportGauge(U);
113 DenOp.ImportGauge(U);
114 }
115
116 public:
117
118 // allow non-uniform tolerances
119 void SetTolerances(std::vector<RealD> action_tolerance,std::vector<RealD> md_tolerance)
120 {
121 assert(action_tolerance.size()==ApproxPowerAction.tolerances.size());
122 assert( md_tolerance.size()==ApproxPowerMD.tolerances.size());
123
124 // Fix up the tolerances
125 for(int i=0;i<ApproxPowerAction.tolerances.size();i++){
126 ApproxPowerAction.tolerances[i] = action_tolerance[i];
127 ApproxNegPowerAction.tolerances[i] = action_tolerance[i];
128 ApproxHalfPowerAction.tolerances[i] = action_tolerance[i];
129 ApproxNegHalfPowerAction.tolerances[i]= action_tolerance[i];
130 }
131 for(int i=0;i<ApproxPowerMD.tolerances.size();i++){
132 ApproxPowerMD.tolerances[i] = md_tolerance[i];
133 ApproxNegPowerMD.tolerances[i] = md_tolerance[i];
134 ApproxHalfPowerMD.tolerances[i] = md_tolerance[i];
135 ApproxNegHalfPowerMD.tolerances[i]= md_tolerance[i];
136 }
137
138 // Print out - could deprecate
139 for(int i=0;i<ApproxPowerMD.tolerances.size();i++) {
140 std::cout<<GridLogMessage << " ApproxPowerMD shift["<<i<<"] "
141 <<" pole "<<ApproxPowerMD.poles[i]
142 <<" residue "<<ApproxPowerMD.residues[i]
143 <<" tol "<<ApproxPowerMD.tolerances[i]<<std::endl;
144 }
145 /*
146 for(int i=0;i<ApproxNegPowerMD.tolerances.size();i++) {
147 std::cout<<GridLogMessage << " ApproxNegPowerMD shift["<<i<<"] "
148 <<" pole "<<ApproxNegPowerMD.poles[i]
149 <<" residue "<<ApproxNegPowerMD.residues[i]
150 <<" tol "<<ApproxNegPowerMD.tolerances[i]<<std::endl;
151 }
152 for(int i=0;i<ApproxHalfPowerMD.tolerances.size();i++) {
153 std::cout<<GridLogMessage << " ApproxHalfPowerMD shift["<<i<<"] "
154 <<" pole "<<ApproxHalfPowerMD.poles[i]
155 <<" residue "<<ApproxHalfPowerMD.residues[i]
156 <<" tol "<<ApproxHalfPowerMD.tolerances[i]<<std::endl;
157 }
158 for(int i=0;i<ApproxNegHalfPowerMD.tolerances.size();i++) {
159 std::cout<<GridLogMessage << " ApproxNegHalfPowerMD shift["<<i<<"] "
160 <<" pole "<<ApproxNegHalfPowerMD.poles[i]
161 <<" residue "<<ApproxNegHalfPowerMD.residues[i]
162 <<" tol "<<ApproxNegHalfPowerMD.tolerances[i]<<std::endl;
163 }
164 */
165
166 }
167
169 FermionOperator<Impl> &_DenOp,
170 const Params & p
171 ) :
172 NumOp(_NumOp),
173 DenOp(_DenOp),
174 PhiOdd (_NumOp.FermionRedBlackGrid()),
175 PhiEven(_NumOp.FermionRedBlackGrid()),
176 param(p)
177 {
178 std::cout<<GridLogMessage << action_name() << " initialize: starting" << std::endl;
179 AlgRemez remez(param.lo,param.hi,param.precision);
180
181 //Generate approximations for action eval
182 generateApprox(ApproxPowerAction, ApproxNegPowerAction, param.inv_pow, param.action_degree, param.action_tolerance, remez);
183 generateApprox(ApproxHalfPowerAction, ApproxNegHalfPowerAction, 2*param.inv_pow, param.action_degree, param.action_tolerance, remez);
184
185 //Generate approximations for MD
186 if(param.md_degree != param.action_degree){ //note the CG tolerance is unrelated to the stopping condition of the Remez algorithm
187 generateApprox(ApproxPowerMD, ApproxNegPowerMD, param.inv_pow, param.md_degree, param.md_tolerance, remez);
188 generateApprox(ApproxHalfPowerMD, ApproxNegHalfPowerMD, 2*param.inv_pow, param.md_degree, param.md_tolerance, remez);
189 }else{
190 std::cout<<GridLogMessage << "Using same rational approximations for MD as for action evaluation" << std::endl;
193 for(int i=0;i<ApproxPowerMD.tolerances.size();i++)
194 ApproxNegPowerMD.tolerances[i] = ApproxPowerMD.tolerances[i] = param.md_tolerance; //used for multishift
195
198 for(int i=0;i<ApproxPowerMD.tolerances.size();i++)
199 ApproxNegHalfPowerMD.tolerances[i] = ApproxHalfPowerMD.tolerances[i] = param.md_tolerance;
200 }
201
202 std::vector<RealD> action_tolerance(ApproxHalfPowerAction.tolerances.size(),param.action_tolerance);
203 std::vector<RealD> md_tolerance (ApproxHalfPowerMD.tolerances.size(),param.md_tolerance);
204
205 SetTolerances(action_tolerance, md_tolerance);
206
207 std::cout<<GridLogMessage << action_name() << " initialize: complete" << std::endl;
208 };
209
210 virtual std::string action_name(){return "GeneralEvenOddRatioRationalPseudoFermionAction";}
211
212 virtual std::string LogParameters(){
213 std::stringstream sstream;
214 sstream << GridLogMessage << "["<<action_name()<<"] Power : 1/" << param.inv_pow << std::endl;
215 sstream << GridLogMessage << "["<<action_name()<<"] Low :" << param.lo << std::endl;
216 sstream << GridLogMessage << "["<<action_name()<<"] High :" << param.hi << std::endl;
217 sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter << std::endl;
218 sstream << GridLogMessage << "["<<action_name()<<"] Tolerance (Action) :" << param.action_tolerance << std::endl;
219 sstream << GridLogMessage << "["<<action_name()<<"] Degree (Action) :" << param.action_degree << std::endl;
220 sstream << GridLogMessage << "["<<action_name()<<"] Tolerance (MD) :" << param.md_tolerance << std::endl;
221 sstream << GridLogMessage << "["<<action_name()<<"] Degree (MD) :" << param.md_degree << std::endl;
222 sstream << GridLogMessage << "["<<action_name()<<"] Precision :" << param.precision << std::endl;
223 return sstream.str();
224 }
225
226 //Access the fermion field
227 const FermionField &getPhiOdd() const{ return PhiOdd; }
228
229 virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) {
230 std::cout<<GridLogMessage << action_name() << " refresh: starting" << std::endl;
231 FermionField eta(NumOp.FermionGrid());
232
233 // P(eta) \propto e^{- eta^dag eta}
234 //
235 // The gaussian function draws from P(x) \propto e^{- x^2 / 2 } [i.e. sigma=1]
236 // Thus eta = x/sqrt{2} = x * sqrt(1/2)
237 RealD scale = std::sqrt(0.5);
238 gaussian(pRNG,eta); eta=eta*scale;
239
240 refresh(U,eta);
241 }
242
243 //Allow for manual specification of random field for testing
244 void refresh(const GaugeField &U, const FermionField &eta) {
245
246 // S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
247 //
248 // P(phi) = e^{- phi^dag (VdagV)^1/(2*inv_pow) (MdagM)^-1/inv_pow (VdagV)^1/(2*inv_pow) phi}
249 // = e^{- phi^dag (VdagV)^1/(2*inv_pow) (MdagM)^-1/(2*inv_pow) (MdagM)^-1/(2*inv_pow) (VdagV)^1/(2*inv_pow) phi}
250 //
251 // Phi = (VdagV)^-1/(2*inv_pow) Mdag^{1/(2*inv_pow)} eta
252
253 std::cout<<GridLogMessage << action_name() << " refresh: starting" << std::endl;
254
255 FermionField etaOdd (NumOp.FermionRedBlackGrid());
256 FermionField etaEven(NumOp.FermionRedBlackGrid());
257 FermionField tmp(NumOp.FermionRedBlackGrid());
258
259 pickCheckerboard(Even,etaEven,eta);
260 pickCheckerboard(Odd,etaOdd,eta);
261
262 ImportGauge(U);
263
264 // MdagM^1/(2*inv_pow) eta
265 std::cout<<GridLogMessage << action_name() << " refresh: doing (M^dag M)^{1/" << 2*param.inv_pow << "} eta" << std::endl;
267
268 // VdagV^-1/(2*inv_pow) MdagM^1/(2*inv_pow) eta
269 std::cout<<GridLogMessage << action_name() << " refresh: doing (V^dag V)^{-1/" << 2*param.inv_pow << "} ( (M^dag M)^{1/" << 2*param.inv_pow << "} eta)" << std::endl;
271
272 assert(NumOp.ConstEE() == 1);
273 assert(DenOp.ConstEE() == 1);
274 PhiEven = Zero();
275
276 RefreshAction = norm2( etaOdd );
277 std::cout<<GridLogMessage << action_name() << " refresh: action is " << RefreshAction << std::endl;
278 };
279
281 // S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
283 virtual RealD Sinitial(const GaugeField &U) {
284 std::cout << GridLogMessage << "Returning stored two flavour refresh action "<<RefreshAction<<std::endl;
285 return RefreshAction;
286 }
287
288 virtual RealD S(const GaugeField &U) {
289 std::cout<<GridLogMessage << action_name() << " compute action: starting" << std::endl;
290 ImportGauge(U);
291
292 FermionField X(NumOp.FermionRedBlackGrid());
293 FermionField Y(NumOp.FermionRedBlackGrid());
294
295 // VdagV^1/(2*inv_pow) Phi
296 std::cout<<GridLogMessage << action_name() << " compute action: doing (V^dag V)^{1/" << 2*param.inv_pow << "} Phi" << std::endl;
298
299 // MdagM^-1/(2*inv_pow) VdagV^1/(2*inv_pow) Phi
300 std::cout<<GridLogMessage << action_name() << " compute action: doing (M^dag M)^{-1/" << 2*param.inv_pow << "} ( (V^dag V)^{1/" << 2*param.inv_pow << "} Phi)" << std::endl;
302
303 // Randomly apply rational bounds checks.
304 int rcheck = rand();
305 auto grid = NumOp.FermionGrid();
306 auto r=rand();
307 grid->Broadcast(0,r);
308
309 if ( param.BoundsCheckFreq != 0 && (r % param.BoundsCheckFreq)==0 ) {
310 std::cout<<GridLogMessage << action_name() << " compute action: doing bounds check" << std::endl;
311 FermionField gauss(NumOp.FermionRedBlackGrid());
312 gauss = PhiOdd;
314 std::cout<<GridLogMessage << action_name() << " compute action: checking high bounds" << std::endl;
315 HighBoundCheck(MdagM,gauss,param.hi);
316 std::cout<<GridLogMessage << action_name() << " compute action: full approximation" << std::endl;
317 InversePowerBoundsCheck(param.inv_pow,param.MaxIter,param.action_tolerance*100,MdagM,gauss,ApproxNegPowerAction);
318 std::cout<<GridLogMessage << action_name() << " compute action: bounds check complete" << std::endl;
319 }
320
321 // Phidag VdagV^1/(2*inv_pow) MdagM^-1/(2*inv_pow) MdagM^-1/(2*inv_pow) VdagV^1/(2*inv_pow) Phi
322 RealD action = norm2(Y);
323 std::cout<<GridLogMessage << action_name() << " compute action: complete" << std::endl;
324
325 return action;
326 };
327
328 // S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
329 //
330 // Here, M is some 5D operator and V is the Pauli-Villars field
331 // N and D makeup the rat. poly of the M term and P and & makeup the rat.poly of the denom term
332 //
333 // Need
334 // dS_f/dU = chi^dag d[P/Q] N/D P/Q chi
335 // + chi^dag P/Q d[N/D] P/Q chi
336 // + chi^dag P/Q N/D d[P/Q] chi
337 //
338 // P/Q is expressed as partial fraction expansion:
339 //
340 // a0 + \sum_k ak/(V^dagV + bk)
341 //
342 // d[P/Q] is then
343 //
344 // \sum_k -ak [V^dagV+bk]^{-1} [ dV^dag V + V^dag dV ] [V^dag V + bk]^{-1}
345 //
346 // and similar for N/D.
347 //
348 // Need
349 // MpvPhi_k = [Vdag V + bk]^{-1} chi
350 // MpvPhi = {a0 + \sum_k ak [Vdag V + bk]^{-1} }chi
351 //
352 // MfMpvPhi_k = [MdagM+bk]^{-1} MpvPhi
353 // MfMpvPhi = {a0 + \sum_k ak [Mdag M + bk]^{-1} } MpvPhi
354 //
355 // MpvMfMpvPhi_k = [Vdag V + bk]^{-1} MfMpvchi
356 //
357
358 virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
359 std::cout<<GridLogMessage << action_name() << " deriv: starting" << std::endl;
360 const int n_f = ApproxNegPowerMD.poles.size();
361 const int n_pv = ApproxHalfPowerMD.poles.size();
362
363 std::vector<FermionField> MpvPhi_k (n_pv,NumOp.FermionRedBlackGrid());
364 std::vector<FermionField> MpvMfMpvPhi_k(n_pv,NumOp.FermionRedBlackGrid());
365 std::vector<FermionField> MfMpvPhi_k (n_f ,NumOp.FermionRedBlackGrid());
366
367 FermionField MpvPhi(NumOp.FermionRedBlackGrid());
368 FermionField MfMpvPhi(NumOp.FermionRedBlackGrid());
369 FermionField MpvMfMpvPhi(NumOp.FermionRedBlackGrid());
370 FermionField Y(NumOp.FermionRedBlackGrid());
371
372 GaugeField tmp(NumOp.GaugeGrid());
373
374 ImportGauge(U);
375
376 std::cout<<GridLogMessage << action_name() << " deriv: doing (V^dag V)^{1/" << 2*param.inv_pow << "} Phi" << std::endl;
377 multiShiftInverse(Numerator, ApproxHalfPowerMD, param.MaxIter, PhiOdd,MpvPhi_k,MpvPhi);
378
379 std::cout<<GridLogMessage << action_name() << " deriv: doing (M^dag M)^{-1/" << param.inv_pow << "} ( (V^dag V)^{1/" << 2*param.inv_pow << "} Phi)" << std::endl;
380 multiShiftInverse(Denominator, ApproxNegPowerMD, param.MaxIter, MpvPhi,MfMpvPhi_k,MfMpvPhi);
381
382 std::cout<<GridLogMessage << action_name() << " deriv: doing (V^dag V)^{1/" << 2*param.inv_pow << "} ( (M^dag M)^{-1/" << param.inv_pow << "} (V^dag V)^{1/" << 2*param.inv_pow << "} Phi)" << std::endl;
383 multiShiftInverse(Numerator, ApproxHalfPowerMD, param.MaxIter, MfMpvPhi,MpvMfMpvPhi_k,MpvMfMpvPhi);
384
385
388
389
390 RealD ak;
391
392 dSdU = Zero();
393
394 // With these building blocks
395 //
396 // dS/dU =
397 // \sum_k -ak MfMpvPhi_k^dag [ dM^dag M + M^dag dM ] MfMpvPhi_k (1)
398 // + \sum_k -ak MpvMfMpvPhi_k^\dag [ dV^dag V + V^dag dV ] MpvPhi_k (2)
399 // -ak MpvPhi_k^dag [ dV^dag V + V^dag dV ] MpvMfMpvPhi_k (3)
400
401 //(1)
402 std::cout<<GridLogMessage << action_name() << " deriv: doing dS/dU part (1)" << std::endl;
403 for(int k=0;k<n_f;k++){
404 ak = ApproxNegPowerMD.residues[k];
405 MdagM.Mpc(MfMpvPhi_k[k],Y);
406 MdagM.MpcDagDeriv(tmp , MfMpvPhi_k[k], Y ); dSdU=dSdU+ak*tmp;
407 MdagM.MpcDeriv(tmp , Y, MfMpvPhi_k[k] ); dSdU=dSdU+ak*tmp;
408 }
409
410 //(2)
411 //(3)
412 std::cout<<GridLogMessage << action_name() << " deriv: doing dS/dU part (2)+(3)" << std::endl;
413 for(int k=0;k<n_pv;k++){
414
415 ak = ApproxHalfPowerMD.residues[k];
416
417 VdagV.Mpc(MpvPhi_k[k],Y);
418 VdagV.MpcDagDeriv(tmp,MpvMfMpvPhi_k[k],Y); dSdU=dSdU+ak*tmp;
419 VdagV.MpcDeriv (tmp,Y,MpvMfMpvPhi_k[k]); dSdU=dSdU+ak*tmp;
420
421 VdagV.Mpc(MpvMfMpvPhi_k[k],Y); // V as we take Ydag
422 VdagV.MpcDeriv (tmp,Y, MpvPhi_k[k]); dSdU=dSdU+ak*tmp;
423 VdagV.MpcDagDeriv(tmp,MpvPhi_k[k], Y); dSdU=dSdU+ak*tmp;
424
425 }
426
427 //dSdU = Ta(dSdU);
428 std::cout<<GridLogMessage << action_name() << " deriv: complete" << std::endl;
429 };
430 };
431
433
434#endif
void InversePowerBoundsCheck(int inv_pow, int MaxIter, double tol, LinearOperatorBase< Field > &HermOp, Field &GaussNoise, MultiShiftFunction &ApproxNegPow)
Definition Bounds.h:82
void HighBoundCheck(LinearOperatorBase< Field > &HermOp, Field &Phi, RealD hi)
Definition Bounds.h:6
static const int Even
static const int Odd
RealD norm2(const Lattice< vobj > &arg)
void gaussian(GridParallelRNG &rng, Lattice< vobj > &l)
void pickCheckerboard(int cb, Lattice< vobj > &half, const Lattice< vobj > &full)
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
uint32_t Integer
Definition Simd.h:58
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
void refresh(const GaugeField &U, const FermionField &eta)
virtual std::string LogParameters()
Print the parameters of the action.
void SetTolerances(std::vector< RealD > action_tolerance, std::vector< RealD > md_tolerance)
virtual std::string action_name()
Report the name of the action.
virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionField &in, FermionField &out)
virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionField &in, std::vector< FermionField > &out_elems, FermionField &out)
GeneralEvenOddRatioRationalPseudoFermionAction(FermionOperator< Impl > &_NumOp, FermionOperator< Impl > &_DenOp, const Params &p)
virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG &pRNG)
Refresh pseudofermion fields.
virtual RealD Sinitial(const GaugeField &U)
Get the action at the start of the trajectory.
virtual void deriv(const GaugeField &U, GaugeField &dSdU)
static void generateApprox(MultiShiftFunction &approx, MultiShiftFunction &approx_inv, int inv_pow, int approx_degree, double CG_tolerance, AlgRemez &remez)
virtual RealD S(const GaugeField &U)
Evaluate this action with the given gauge field.
void Init(AlgRemez &remez, double tol, bool inverse)
virtual void Mpc(const Field &in, Field &out)
void MpcDagDeriv(GaugeField &Force, const FermionField &U, const FermionField &V)
void MpcDeriv(GaugeField &Force, const FermionField &U, const FermionField &V)
Definition Simd.h:194