Grid 0.7.0
DomainWallEOFAFermionImplementation.h
Go to the documentation of this file.
1/*************************************************************************************
2
3Grid physics library, www.github.com/paboyle/Grid
4
5Source file: ./lib/qcd/action/fermion/DomainWallEOFAFermion.cc
6
7Copyright (C) 2017
8
9Author: Peter Boyle <pabobyle@ph.ed.ac.uk>
10Author: Peter Boyle <paboyle@ph.ed.ac.uk>
11Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local>
12Author: paboyle <paboyle@ph.ed.ac.uk>
13Author: David Murphy <dmurphy@phys.columbia.edu>
14
15This program is free software; you can redistribute it and/or modify
16it under the terms of the GNU General Public License as published by
17the Free Software Foundation; either version 2 of the License, or
18(at your option) any later version.
19
20This program is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23GNU General Public License for more details.
24
25You should have received a copy of the GNU General Public License along
26with this program; if not, write to the Free Software Foundation, Inc.,
2751 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28
29See the full license in the file "LICENSE" in the top level distribution directory
30*************************************************************************************/
31 /* END LEGAL */
32
33#pragma once
34
38
40
41template<class Impl>
43 GaugeField &_Umu,
44 GridCartesian &FiveDimGrid,
45 GridRedBlackCartesian &FiveDimRedBlackGrid,
46 GridCartesian &FourDimGrid,
47 GridRedBlackCartesian &FourDimRedBlackGrid,
48 RealD _mq1, RealD _mq2, RealD _mq3,
49 RealD _shift, int _pm, RealD _M5, const ImplParams &p) :
50 AbstractEOFAFermion<Impl>(_Umu, FiveDimGrid, FiveDimRedBlackGrid,
51 FourDimGrid, FourDimRedBlackGrid, _mq1, _mq2, _mq3,
52 _shift, _pm, _M5, 1.0, 0.0, p)
53{
54 RealD eps = 1.0;
55 Approx::zolotarev_data *zdata = Approx::higham(eps,this->Ls);
56 assert(zdata->n == this->Ls);
57
58 std::cout << GridLogMessage << "DomainWallEOFAFermion with Ls=" << this->Ls << std::endl;
59 this->SetCoefficientsTanh(zdata, 1.0, 0.0);
60
61 Approx::zolotarev_free(zdata);
62}
63
64/***************************************************************
65 * Additional EOFA operators only called outside the inverter.
66 * Since speed is not essential, simple axpby-style
67 * implementations should be fine.
68 ***************************************************************/
69template<class Impl>
70void DomainWallEOFAFermion<Impl>::Omega(const FermionField& psi, FermionField& Din, int sign, int dag)
71{
72 int Ls = this->Ls;
73
74 Din = Zero();
75 if((sign == 1) && (dag == 0)){ axpby_ssp(Din, 0.0, psi, 1.0, psi, Ls-1, 0); }
76 else if((sign == -1) && (dag == 0)){ axpby_ssp(Din, 0.0, psi, 1.0, psi, 0, 0); }
77 else if((sign == 1 ) && (dag == 1)){ axpby_ssp(Din, 0.0, psi, 1.0, psi, 0, Ls-1); }
78 else if((sign == -1) && (dag == 1)){ axpby_ssp(Din, 0.0, psi, 1.0, psi, 0, 0); }
79}
80
81// This is just the identity for DWF
82template<class Impl>
83void DomainWallEOFAFermion<Impl>::Dtilde(const FermionField& psi, FermionField& chi){ chi = psi; }
84
85// This is just the identity for DWF
86template<class Impl>
87void DomainWallEOFAFermion<Impl>::DtildeInv(const FermionField& psi, FermionField& chi){ chi = psi; }
88
89/*****************************************************************************************************/
90
91template<class Impl>
92void DomainWallEOFAFermion<Impl>::M(const FermionField& psi, FermionField& chi)
93{
94 FermionField Din(psi.Grid());
95
96 this->Meooe5D(psi, Din);
97 this->DW(Din, chi, DaggerNo);
98 axpby(chi, 1.0, 1.0, chi, psi);
99 this->M5D(psi, chi);
100}
101
102template<class Impl>
103void DomainWallEOFAFermion<Impl>::Mdag(const FermionField& psi, FermionField& chi)
104{
105 FermionField Din(psi.Grid());
106
107 this->DW(psi, Din, DaggerYes);
108 this->MeooeDag5D(Din, chi);
109 this->M5Ddag(psi, chi);
110 axpby(chi, 1.0, 1.0, chi, psi);
111}
112
113/********************************************************************
114 * Performance critical fermion operators called inside the inverter
115 ********************************************************************/
116
117template<class Impl>
118void DomainWallEOFAFermion<Impl>::M5D(const FermionField& psi, FermionField& chi)
119{
120 int Ls = this->Ls;
121 int pm = this->pm;
122 RealD shift = this->shift;
123 RealD mq1 = this->mq1;
124 RealD mq2 = this->mq2;
125 RealD mq3 = this->mq3;
126
127 // coefficients for shift operator ( = shift*\gamma_{5}*R_{5}*\Delta_{\pm}(mq2,mq3)*P_{\pm} )
128 Coeff_t shiftp(0.0), shiftm(0.0);
129 if(shift != 0.0){
130 if(pm == 1){ shiftp = shift*(mq3-mq2); }
131 else{ shiftm = -shift*(mq3-mq2); }
132 }
133
134 std::vector<Coeff_t> diag(Ls,1.0);
135 std::vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1] = mq1 + shiftm;
136 std::vector<Coeff_t> lower(Ls,-1.0); lower[0] = mq1 + shiftp;
137
138#if(0)
139 std::cout << GridLogMessage << "DomainWallEOFAFermion::M5D(FF&,FF&):" << std::endl;
140 for(int i=0; i<diag.size(); ++i){
141 std::cout << GridLogMessage << "diag[" << i << "] =" << diag[i] << std::endl;
142 }
143 for(int i=0; i<upper.size(); ++i){
144 std::cout << GridLogMessage << "upper[" << i << "] =" << upper[i] << std::endl;
145 }
146 for(int i=0; i<lower.size(); ++i){
147 std::cout << GridLogMessage << "lower[" << i << "] =" << lower[i] << std::endl;
148 }
149#endif
150
151 this->M5D(psi, chi, chi, lower, diag, upper);
152}
153
154template<class Impl>
155void DomainWallEOFAFermion<Impl>::M5Ddag(const FermionField& psi, FermionField& chi)
156{
157 int Ls = this->Ls;
158 int pm = this->pm;
159 RealD shift = this->shift;
160 RealD mq1 = this->mq1;
161 RealD mq2 = this->mq2;
162 RealD mq3 = this->mq3;
163
164 // coefficients for shift operator ( = shift*\gamma_{5}*R_{5}*\Delta_{\pm}(mq2,mq3)*P_{\pm} )
165 Coeff_t shiftp(0.0), shiftm(0.0);
166 if(shift != 0.0){
167 if(pm == 1){ shiftp = shift*(mq3-mq2); }
168 else{ shiftm = -shift*(mq3-mq2); }
169 }
170
171 std::vector<Coeff_t> diag(Ls,1.0);
172 std::vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1] = mq1 + shiftp;
173 std::vector<Coeff_t> lower(Ls,-1.0); lower[0] = mq1 + shiftm;
174
175 this->M5Ddag(psi, chi, chi, lower, diag, upper);
176}
177
178// half checkerboard operations
179template<class Impl>
180void DomainWallEOFAFermion<Impl>::Mooee(const FermionField& psi, FermionField& chi)
181{
182 int Ls = this->Ls;
183
184 std::vector<Coeff_t> diag = this->bee;
185 std::vector<Coeff_t> upper(Ls);
186 std::vector<Coeff_t> lower(Ls);
187
188 for(int s=0; s<Ls; s++){
189 upper[s] = -this->cee[s];
190 lower[s] = -this->cee[s];
191 }
192 upper[Ls-1] = this->dm;
193 lower[0] = this->dp;
194
195 this->M5D(psi, psi, chi, lower, diag, upper);
196}
197
198template<class Impl>
199void DomainWallEOFAFermion<Impl>::MooeeDag(const FermionField& psi, FermionField& chi)
200{
201 int Ls = this->Ls;
202
203 std::vector<Coeff_t> diag = this->bee;
204 std::vector<Coeff_t> upper(Ls);
205 std::vector<Coeff_t> lower(Ls);
206
207 for(int s=0; s<Ls; s++){
208 upper[s] = -this->cee[s];
209 lower[s] = -this->cee[s];
210 }
211 upper[Ls-1] = this->dp;
212 lower[0] = this->dm;
213
214 this->M5Ddag(psi, psi, chi, lower, diag, upper);
215}
216
217/****************************************************************************************/
218
219//Zolo
220template<class Impl>
221void DomainWallEOFAFermion<Impl>::SetCoefficientsInternal(RealD zolo_hi, std::vector<Coeff_t>& gamma, RealD b, RealD c)
222{
223 int Ls = this->Ls;
224 int pm = this->pm;
225 RealD mq1 = this->mq1;
226 RealD mq2 = this->mq2;
227 RealD mq3 = this->mq3;
228 RealD shift = this->shift;
229
231 // Constants for the preconditioned matrix Cayley form
233 this->bs.resize(Ls);
234 this->cs.resize(Ls);
235 this->aee.resize(Ls);
236 this->aeo.resize(Ls);
237 this->bee.resize(Ls);
238 this->beo.resize(Ls);
239 this->cee.resize(Ls);
240 this->ceo.resize(Ls);
241
242 for(int i=0; i<Ls; ++i){
243 this->bee[i] = 4.0 - this->M5 + 1.0;
244 this->cee[i] = 1.0;
245 }
246
247 for(int i=0; i<Ls; ++i){
248 this->aee[i] = this->cee[i];
249 this->bs[i] = this->beo[i] = 1.0;
250 this->cs[i] = this->ceo[i] = 0.0;
251 }
252
254 // EOFA shift terms
256 if(pm == 1){
257 this->dp = mq1*this->cee[0] + shift*(mq3-mq2);
258 this->dm = mq1*this->cee[Ls-1];
259 } else if(this->pm == -1) {
260 this->dp = mq1*this->cee[0];
261 this->dm = mq1*this->cee[Ls-1] - shift*(mq3-mq2);
262 } else {
263 this->dp = mq1*this->cee[0];
264 this->dm = mq1*this->cee[Ls-1];
265 }
266
268 // LDU decomposition of eeoo
270 this->dee.resize(Ls+1);
271 this->lee.resize(Ls);
272 this->leem.resize(Ls);
273 this->uee.resize(Ls);
274 this->ueem.resize(Ls);
275
276 for(int i=0; i<Ls; ++i){
277
278 if(i < Ls-1){
279
280 this->lee[i] = -this->cee[i+1]/this->bee[i]; // sub-diag entry on the ith column
281
282 this->leem[i] = this->dm/this->bee[i];
283 for(int j=0; j<i; j++){ this->leem[i] *= this->aee[j]/this->bee[j]; }
284
285 this->dee[i] = this->bee[i];
286
287 this->uee[i] = -this->aee[i]/this->bee[i]; // up-diag entry on the ith row
288
289 this->ueem[i] = this->dp / this->bee[0];
290 for(int j=1; j<=i; j++){ this->ueem[i] *= this->cee[j]/this->bee[j]; }
291
292 } else {
293
294 this->lee[i] = 0.0;
295 this->leem[i] = 0.0;
296 this->uee[i] = 0.0;
297 this->ueem[i] = 0.0;
298
299 }
300 }
301
302 {
303 Coeff_t delta_d = 1.0 / this->bee[0];
304 for(int j=1; j<Ls-1; j++){ delta_d *= this->cee[j] / this->bee[j]; }
305 this->dee[Ls-1] = this->bee[Ls-1] + this->cee[0] * this->dm * delta_d;
306 this->dee[Ls] = this->bee[Ls-1] + this->cee[Ls-1] * this->dp * delta_d;
307 }
308}
309
310// Recompute Cayley-form coefficients for different shift
311template<class Impl>
313{
314 this->shift = new_shift;
315 Approx::zolotarev_data *zdata = Approx::higham(1.0, this->Ls);
316 this->SetCoefficientsTanh(zdata, 1.0, 0.0);
317}
318
void axpby(Lattice< vobj > &ret, sobj a, sobj b, const Lattice< vobj > &x, const Lattice< vobj > &y)
void axpby_ssp(Lattice< vobj > &z, Coeff a, const Lattice< vobj > &x, Coeff b, const Lattice< vobj > &y, int s, int sp)
Definition LinalgUtils.h:59
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
AbstractEOFAFermion(GaugeField &_Umu, GridCartesian &FiveDimGrid, GridRedBlackCartesian &FiveDimRedBlackGrid, GridCartesian &FourDimGrid, GridRedBlackCartesian &FourDimRedBlackGrid, RealD _mq1, RealD _mq2, RealD _mq3, RealD _shift, int _pm, RealD _M5, RealD _b, RealD _c, const ImplParams &p=ImplParams())
void Meooe5D(const FermionField &in, FermionField &out)
std::vector< Coeff_t > leem
std::vector< Coeff_t > lee
std::vector< Coeff_t > bee
std::vector< Coeff_t > dee
std::vector< Coeff_t > cs
std::vector< Coeff_t > beo
std::vector< Coeff_t > bs
void MeooeDag5D(const FermionField &in, FermionField &out)
std::vector< Coeff_t > aeo
virtual void SetCoefficientsTanh(Approx::zolotarev_data *zdata, RealD b, RealD c)
std::vector< Coeff_t > ceo
std::vector< Coeff_t > ueem
std::vector< Coeff_t > cee
std::vector< Coeff_t > aee
std::vector< Coeff_t > uee
virtual void M5D(const FermionField &psi, FermionField &chi)
virtual void Dtilde(const FermionField &in, FermionField &out)
virtual void M5Ddag(const FermionField &psi, FermionField &chi)
virtual void M(const FermionField &in, FermionField &out)
virtual void Mooee(const FermionField &in, FermionField &out)
virtual void DtildeInv(const FermionField &in, FermionField &out)
virtual void RefreshShiftCoefficients(RealD new_shift)
void SetCoefficientsInternal(RealD zolo_hi, std::vector< Coeff_t > &gamma, RealD b, RealD c)
virtual void Mdag(const FermionField &in, FermionField &out)
DomainWallEOFAFermion(GaugeField &_Umu, GridCartesian &FiveDimGrid, GridRedBlackCartesian &FiveDimRedBlackGrid, GridCartesian &FourDimGrid, GridRedBlackCartesian &FourDimRedBlackGrid, RealD _mq1, RealD _mq2, RealD _mq3, RealD _shift, int pm, RealD _M5, const ImplParams &p=ImplParams())
virtual void Omega(const FermionField &in, FermionField &out, int sign, int dag)
virtual void MooeeDag(const FermionField &in, FermionField &out)
void DW(const FermionField &in, FermionField &out, int dag)
Definition Simd.h:194