Grid 0.7.0
CayleyFermion5DImplementation.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/fermion/CayleyFermion5D.cc
6
7 Copyright (C) 2015
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>
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License along
25 with this program; if not, write to the Free Software Foundation, Inc.,
26 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27
28 See the full license in the file "LICENSE" in the top level distribution directory
29*************************************************************************************/
30/* END LEGAL */
31
35
37
38template<class Impl>
40 GridCartesian &FiveDimGrid,
41 GridRedBlackCartesian &FiveDimRedBlackGrid,
42 GridCartesian &FourDimGrid,
43 GridRedBlackCartesian &FourDimRedBlackGrid,
44 RealD _mass,RealD _M5,const ImplParams &p) :
45 WilsonFermion5D<Impl>(_Umu,
46 FiveDimGrid,
47 FiveDimRedBlackGrid,
48 FourDimGrid,
49 FourDimRedBlackGrid,_M5,p),
50 mass_plus(_mass), mass_minus(_mass)
51{
52 // qmu defaults to zero size;
54
55///////////////////////////////////////////////////////////////
56// Physical surface field utilities
58template<class Impl>
59void CayleyFermion5D<Impl>::ExportPhysicalFermionSolution(const FermionField &solution5d,FermionField &exported4d)
60{
61 int Ls = this->Ls;
62 FermionField tmp(this->FermionGrid());
63 tmp = solution5d;
64 conformable(solution5d.Grid(),this->FermionGrid());
65 conformable(exported4d.Grid(),this->GaugeGrid());
66 axpby_ssp_pminus(tmp, 0., solution5d, 1., solution5d, 0, 0);
67 axpby_ssp_pplus (tmp, 1., tmp , 1., solution5d, 0, Ls-1);
68 ExtractSlice(exported4d, tmp, 0, 0);
69}
70template<class Impl>
71void CayleyFermion5D<Impl>::P(const FermionField &psi, FermionField &chi)
72{
73 int Ls= this->Ls;
74 chi=Zero();
75 for(int s=0;s<Ls;s++){
76 axpby_ssp_pminus(chi,1.0,chi,1.0,psi,s,s);
77 axpby_ssp_pplus (chi,1.0,chi,1.0,psi,s,(s+1)%Ls);
78 }
79}
80template<class Impl>
81void CayleyFermion5D<Impl>::Pdag(const FermionField &psi, FermionField &chi)
82{
83 int Ls= this->Ls;
84 chi=Zero();
85 for(int s=0;s<Ls;s++){
86 axpby_ssp_pminus(chi,1.0,chi,1.0,psi,s,s);
87 axpby_ssp_pplus (chi,1.0,chi,1.0,psi,s,(s-1+Ls)%Ls);
88 }
89}
90template<class Impl>
91void CayleyFermion5D<Impl>::ExportPhysicalFermionSource(const FermionField &solution5d,FermionField &exported4d)
92{
93 int Ls = this->Ls;
94 FermionField tmp(this->FermionGrid());
95 tmp = solution5d;
96 conformable(solution5d.Grid(),this->FermionGrid());
97 conformable(exported4d.Grid(),this->GaugeGrid());
98 axpby_ssp_pplus (tmp, 0., solution5d, 1., solution5d, 0, 0);
99 axpby_ssp_pminus(tmp, 1., tmp , 1., solution5d, 0, Ls-1);
100 ExtractSlice(exported4d, tmp, 0, 0);
101}
102template<class Impl>
103void CayleyFermion5D<Impl>::ImportUnphysicalFermion(const FermionField &input4d,FermionField &imported5d)
104{
105 int Ls = this->Ls;
106 FermionField tmp(this->FermionGrid());
107 conformable(imported5d.Grid(),this->FermionGrid());
108 conformable(input4d.Grid() ,this->GaugeGrid());
110 InsertSlice(input4d, tmp, 0 , 0);
111 InsertSlice(input4d, tmp, Ls-1, 0);
112 axpby_ssp_pplus (tmp, 0., tmp, 1., tmp, 0, 0);
113 axpby_ssp_pminus(tmp, 0., tmp, 1., tmp, Ls-1, Ls-1);
114 imported5d=tmp;
117template<class Impl>
118void CayleyFermion5D<Impl>::ImportPhysicalFermionSource(const FermionField &input4d,FermionField &imported5d)
119{
120 int Ls = this->Ls;
121 FermionField tmp(this->FermionGrid());
122 conformable(imported5d.Grid(),this->FermionGrid());
123 conformable(input4d.Grid() ,this->GaugeGrid());
124 tmp = Zero();
125 InsertSlice(input4d, tmp, 0 , 0);
126 InsertSlice(input4d, tmp, Ls-1, 0);
127 axpby_ssp_pplus (tmp, 0., tmp, 1., tmp, 0, 0);
128 axpby_ssp_pminus(tmp, 0., tmp, 1., tmp, Ls-1, Ls-1);
129 Dminus(tmp,imported5d);
131template<class Impl>
132void CayleyFermion5D<Impl>::Dminus(const FermionField &psi, FermionField &chi)
133{
134 int Ls=this->Ls;
135
136 FermionField tmp_f(this->FermionGrid());
137 this->DW(psi,tmp_f,DaggerNo);
138
139 for(int s=0;s<Ls;s++){
140 axpby_ssp(chi,Coeff_t(1.0),psi,-cs[s],tmp_f,s,s);// chi = (1-c[s] D_W) psi
141 }
142}
143template<class Impl>
144void CayleyFermion5D<Impl>::DminusDag(const FermionField &psi, FermionField &chi)
145{
146 int Ls=this->Ls;
147
148 FermionField tmp_f(this->FermionGrid());
149 this->DW(psi,tmp_f,DaggerYes);
150
151 for(int s=0;s<Ls;s++){
152 axpby_ssp(chi,Coeff_t(1.0),psi,conjugate(-cs[s]),tmp_f,s,s);// chi = (1-c[s] D_W) psi
153 }
154}
155
156template<class Impl>
157void CayleyFermion5D<Impl>::M5D (const FermionField &psi, FermionField &chi)
158{
159 int Ls=this->Ls;
160 std::vector<Coeff_t> diag (Ls,1.0);
161 std::vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1]=mass_minus;
162 std::vector<Coeff_t> lower(Ls,-1.0); lower[0] =mass_plus;
163 M5D(psi,chi,chi,lower,diag,upper);
164}
165template<class Impl>
166void CayleyFermion5D<Impl>::Meooe5D (const FermionField &psi, FermionField &Din)
167{
168 int Ls=this->Ls;
169 std::vector<Coeff_t> diag = bs;
170 std::vector<Coeff_t> upper= cs;
171 std::vector<Coeff_t> lower= cs;
172 upper[Ls-1]=-mass_minus*upper[Ls-1];
173 lower[0] =-mass_plus*lower[0];
174 M5D(psi,psi,Din,lower,diag,upper);
175}
176// FIXME Redunant with the above routine; check this and eliminate
177template<class Impl> void CayleyFermion5D<Impl>::Meo5D (const FermionField &psi, FermionField &chi)
178{
179 int Ls=this->Ls;
180 std::vector<Coeff_t> diag = beo;
181 std::vector<Coeff_t> upper(Ls);
182 std::vector<Coeff_t> lower(Ls);
183 for(int i=0;i<Ls;i++) {
184 upper[i]=-ceo[i];
185 lower[i]=-ceo[i];
186 }
187 upper[Ls-1]=-mass_minus*upper[Ls-1];
188 lower[0] =-mass_plus*lower[0];
189 M5D(psi,psi,chi,lower,diag,upper);
191template<class Impl>
192void CayleyFermion5D<Impl>::Mooee (const FermionField &psi, FermionField &chi)
193{
194 int Ls=this->Ls;
195 std::vector<Coeff_t> diag = bee;
196 std::vector<Coeff_t> upper(Ls);
197 std::vector<Coeff_t> lower(Ls);
198 for(int i=0;i<Ls;i++) {
199 upper[i]=-cee[i];
200 lower[i]=-cee[i];
201 }
202 upper[Ls-1]=-mass_minus*upper[Ls-1];
203 lower[0] =-mass_plus*lower[0];
204 M5D(psi,psi,chi,lower,diag,upper);
206template<class Impl>
207void CayleyFermion5D<Impl>::MooeeDag (const FermionField &psi, FermionField &chi)
208{
209 int Ls=this->Ls;
210 std::vector<Coeff_t> diag = bee;
211 std::vector<Coeff_t> upper(Ls);
212 std::vector<Coeff_t> lower(Ls);
213
214 for (int s=0;s<Ls;s++){
215 // Assemble the 5d matrix
216 if ( s==0 ) {
217 upper[s] = -cee[s+1] ;
218 lower[s] = mass_minus*cee[Ls-1];
219 } else if ( s==(Ls-1)) {
220 upper[s] = mass_plus*cee[0];
221 lower[s] = -cee[s-1];
222 } else {
223 upper[s]=-cee[s+1];
224 lower[s]=-cee[s-1];
225 }
226 }
227 // Conjugate the terms
228 for (int s=0;s<Ls;s++){
229 diag[s] =conjugate(diag[s]);
230 upper[s]=conjugate(upper[s]);
231 lower[s]=conjugate(lower[s]);
232 }
233 M5Ddag(psi,psi,chi,lower,diag,upper);
234}
235
236template<class Impl>
237void CayleyFermion5D<Impl>::M5Ddag (const FermionField &psi, FermionField &chi)
238{
239 int Ls=this->Ls;
240 std::vector<Coeff_t> diag(Ls,1.0);
241 std::vector<Coeff_t> upper(Ls,-1.0);
242 std::vector<Coeff_t> lower(Ls,-1.0);
243 upper[Ls-1]=-mass_plus*upper[Ls-1];
244 lower[0] =-mass_minus*lower[0];
245 M5Ddag(psi,chi,chi,lower,diag,upper);
246}
247
248template<class Impl>
249void CayleyFermion5D<Impl>::MeooeDag5D (const FermionField &psi, FermionField &Din)
250{
251 int Ls=this->Ls;
252 std::vector<Coeff_t> diag =bs;
253 std::vector<Coeff_t> upper=cs;
254 std::vector<Coeff_t> lower=cs;
255
256 for (int s=0;s<Ls;s++){
257 if ( s== 0 ) {
258 upper[s] = cs[s+1];
259 lower[s] =-mass_minus*cs[Ls-1];
260 } else if ( s==(Ls-1) ) {
261 upper[s] =-mass_plus*cs[0];
262 lower[s] = cs[s-1];
263 } else {
264 upper[s] = cs[s+1];
265 lower[s] = cs[s-1];
266 }
267 upper[s] = conjugate(upper[s]);
268 lower[s] = conjugate(lower[s]);
269 diag[s] = conjugate(diag[s]);
270 }
271 M5Ddag(psi,psi,Din,lower,diag,upper);
272}
273
274template<class Impl>
275void CayleyFermion5D<Impl>::addQmu(const FermionField &psi,FermionField &chi, int dag)
276{
277 if ( qmu.size() ) {
278
279 Gamma::Algebra Gmu [] = {
280 Gamma::Algebra::GammaX,
281 Gamma::Algebra::GammaY,
282 Gamma::Algebra::GammaZ,
283 Gamma::Algebra::GammaT
284 };
285 std::vector<ComplexD> coeff(Nd);
286 ComplexD ci(0,1);
287
288 assert(qmu.size()==Nd);
289
290 for(int mu=0;mu<Nd;mu++){
291 coeff[mu] = ci*qmu[mu];
292 if ( dag ) coeff[mu] = conjugate(coeff[mu]);
293 }
294
295 chi = chi + Gamma(Gmu[0])*psi*coeff[0];
296 for(int mu=1;mu<Nd;mu++){
297 chi = chi + Gamma(Gmu[mu])*psi*coeff[mu];
298 }
299 }
300}
301
302template<class Impl>
303void CayleyFermion5D<Impl>::M (const FermionField &psi, FermionField &chi)
304{
305 FermionField Din(psi.Grid());
306
307 // Assemble Din
308 Meooe5D(psi,Din);
309
310 this->DW(Din,chi,DaggerNo);
311
312 // add i q_mu gamma_mu here
313 addQmu(Din,chi,DaggerNo);
314
315 // ((b D_W + D_w hop terms +1) on s-diag
316 axpby(chi,1.0,1.0,chi,psi);
317
318 M5D(psi,chi);
319}
320
321template<class Impl>
322void CayleyFermion5D<Impl>::Mdag (const FermionField &psi, FermionField &chi)
323{
324 // Under adjoint
325 //D1+ D1- P- -> D1+^dag P+ D2-^dag
326 //D2- P+ D2+ P-D1-^dag D2+dag
327
328 FermionField Din(psi.Grid());
329 // Apply Dw
330 this->DW(psi,Din,DaggerYes);
331
332 // add -i conj(q_mu) gamma_mu here ... if qmu is real, gammm_5 hermitian, otherwise not.
333 addQmu(psi,Din,DaggerYes);
334
335 MeooeDag5D(Din,chi);
336
337 M5Ddag(psi,chi);
338 // ((b D_W + D_w hop terms +1) on s-diag
339 axpby (chi,1.0,1.0,chi,psi);
340}
341
342// half checkerboard operations
343template<class Impl>
344void CayleyFermion5D<Impl>::Meooe (const FermionField &psi, FermionField &chi)
345{
346 Meooe5D(psi,this->tmp());
347
348 if ( psi.Checkerboard() == Odd ) {
349 this->DhopEO(this->tmp(),chi,DaggerNo);
350 } else {
351 this->DhopOE(this->tmp(),chi,DaggerNo);
352 }
353}
354
355template<class Impl>
356void CayleyFermion5D<Impl>::MeooeDag (const FermionField &psi, FermionField &chi)
357{
358 // Apply 4d dslash
359 if ( psi.Checkerboard() == Odd ) {
360 this->DhopEO(psi,this->tmp(),DaggerYes);
361 } else {
362 this->DhopOE(psi,this->tmp(),DaggerYes);
363 }
364 MeooeDag5D(this->tmp(),chi);
365}
366
367template<class Impl>
368void CayleyFermion5D<Impl>::Mdir (const FermionField &psi, FermionField &chi,int dir,int disp)
369{
370 FermionField tmp(psi.Grid());
371 Meo5D(psi,tmp);
372 this->DhopDir(tmp,chi,dir,disp);
373}
374template<class Impl>
375void CayleyFermion5D<Impl>::MdirAll(const FermionField &psi, std::vector<FermionField> &out)
376{
377 FermionField tmp(psi.Grid());
378 Meo5D(psi,tmp);
379 this->DhopDirAll(tmp,out);
380}
381
382// force terms; five routines; default to Dhop on diagonal
383template<class Impl>
384void CayleyFermion5D<Impl>::MDeriv (GaugeField &mat,const FermionField &U,const FermionField &V,int dag)
385{
386 FermionField Din(V.Grid());
387
388 if ( dag == DaggerNo ) {
389 // U d/du [D_w D5] V = U d/du DW D5 V
390 Meooe5D(V,Din);
391 this->DhopDeriv(mat,U,Din,dag);
392 } else {
393 // U d/du [D_w D5]^dag V = U D5^dag d/du DW^dag Y // implicit adj on U in call
394 Meooe5D(U,Din);
395 this->DhopDeriv(mat,Din,V,dag);
396 }
397};
398template<class Impl>
399void CayleyFermion5D<Impl>::MoeDeriv(GaugeField &mat,const FermionField &U,const FermionField &V,int dag)
400{
401 FermionField Din(V.Grid());
402
403 if ( dag == DaggerNo ) {
404 // U d/du [D_w D5] V = U d/du DW D5 V
405 Meooe5D(V,Din);
406 this->DhopDerivOE(mat,U,Din,dag);
407 } else {
408 // U d/du [D_w D5]^dag V = U D5^dag d/du DW^dag Y // implicit adj on U in call
409 Meooe5D(U,Din);
410 this->DhopDerivOE(mat,Din,V,dag);
411 }
412};
413template<class Impl>
414void CayleyFermion5D<Impl>::MeoDeriv(GaugeField &mat,const FermionField &U,const FermionField &V,int dag)
415{
416 FermionField Din(V.Grid());
417
418 if ( dag == DaggerNo ) {
419 // U d/du [D_w D5] V = U d/du DW D5 V
420 Meooe5D(V,Din);
421 this->DhopDerivEO(mat,U,Din,dag);
422 } else {
423 // U d/du [D_w D5]^dag V = U D5^dag d/du DW^dag Y // implicit adj on U in call
424 Meooe5D(U,Din);
425 this->DhopDerivEO(mat,Din,V,dag);
426 }
427};
428
429// Tanh
430template<class Impl>
431void CayleyFermion5D<Impl>::SetCoefficientsTanh(Approx::zolotarev_data *zdata,RealD b,RealD c)
432{
433 std::vector<Coeff_t> gamma(this->Ls);
434 for(int s=0;s<this->Ls;s++) gamma[s] = zdata->gamma[s];
435 SetCoefficientsInternal(1.0,gamma,b,c);
436}
437//Zolo
438template<class Impl>
439void CayleyFermion5D<Impl>::SetCoefficientsZolotarev(RealD zolo_hi,Approx::zolotarev_data *zdata,RealD b,RealD c)
440{
441 std::vector<Coeff_t> gamma(this->Ls);
442 for(int s=0;s<this->Ls;s++) gamma[s] = zdata->gamma[s];
443 SetCoefficientsInternal(zolo_hi,gamma,b,c);
444}
445//Zolo
446template<class Impl>
447void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,std::vector<Coeff_t> & gamma,RealD b,RealD c)
448{
449 int Ls=this->Ls;
450
452 // The Cayley coeffs (unprec)
454 assert(gamma.size()==Ls);
455
456 omega.resize(Ls);
457 bs.resize(Ls);
458 cs.resize(Ls);
459 as.resize(Ls);
460
461 //
462 // Ts = ( [bs+cs]Dw )^-1 ( (bs+cs) Dw )
463 // -(g5 ------- -1 ) ( g5 --------- + 1 )
464 // ( {2+(bs-cs)Dw} ) ( 2+(bs-cs) Dw )
465 //
466 // bs = 1/2( (1/omega_s + 1)*b + (1/omega - 1)*c ) = 1/2( 1/omega(b+c) + (b-c) )
467 // cs = 1/2( (1/omega_s - 1)*b + (1/omega + 1)*c ) = 1/2( 1/omega(b+c) - (b-c) )
468 //
469 // bs+cs = 0.5*( 1/omega(b+c) + (b-c) + 1/omega(b+c) - (b-c) ) = 1/omega(b+c)
470 // bs-cs = 0.5*( 1/omega(b+c) + (b-c) - 1/omega(b+c) + (b-c) ) = b-c
471 //
472 // So
473 //
474 // Ts = ( [b+c]Dw/omega_s )^-1 ( (b+c) Dw /omega_s )
475 // -(g5 ------- -1 ) ( g5 --------- + 1 )
476 // ( {2+(b-c)Dw} ) ( 2+(b-c) Dw )
477 //
478 // Ts = ( [b+c]Dw )^-1 ( (b+c) Dw )
479 // -(g5 ------- -omega_s) ( g5 --------- + omega_s )
480 // ( {2+(b-c)Dw} ) ( 2+(b-c) Dw )
481 //
482
483 double bpc = b+c;
484 double bmc = b-c;
485 _b = b;
486 _c = c;
487 _gamma = gamma; // Save the parameters so we can change mass later.
488 _zolo_hi= zolo_hi;
489 for(int i=0; i < Ls; i++){
490 as[i] = 1.0;
491 omega[i] = _gamma[i]*_zolo_hi; //NB reciprocal relative to Chroma NEF code
492 assert(omega[i]!=Coeff_t(0.0));
493 bs[i] = 0.5*(bpc/omega[i] + bmc);
494 cs[i] = 0.5*(bpc/omega[i] - bmc);
495 }
496
498 // Constants for the preconditioned matrix Cayley form
500 bee.resize(Ls);
501 cee.resize(Ls);
502 beo.resize(Ls);
503 ceo.resize(Ls);
504
505 for(int i=0;i<Ls;i++){
506 bee[i]=as[i]*(bs[i]*(4.0-this->M5) +1.0);
507 assert(bee[i]!=Coeff_t(0.0));
508 cee[i]=as[i]*(1.0-cs[i]*(4.0-this->M5));
509 beo[i]=as[i]*bs[i];
510 ceo[i]=-as[i]*cs[i];
511 }
512 aee.resize(Ls);
513 aeo.resize(Ls);
514 for(int i=0;i<Ls;i++){
515 aee[i]=cee[i];
516 aeo[i]=ceo[i];
517 }
518
520 // LDU decomposition of eeoo
522 dee.resize(Ls);
523 lee.resize(Ls);
524 leem.resize(Ls);
525 uee.resize(Ls);
526 ueem.resize(Ls);
527
528 for(int i=0;i<Ls;i++){
529
530 dee[i] = bee[i];
531
532 if ( i < Ls-1 ) {
533
534 assert(bee[i]!=Coeff_t(0.0));
535 assert(bee[0]!=Coeff_t(0.0));
536
537 lee[i] =-cee[i+1]/bee[i]; // sub-diag entry on the ith column
538
539 leem[i]=mass_minus*cee[Ls-1]/bee[0];
540 for(int j=0;j<i;j++) {
541 assert(bee[j+1]!=Coeff_t(0.0));
542 leem[i]*= aee[j]/bee[j+1];
543 }
544
545 uee[i] =-aee[i]/bee[i]; // up-diag entry on the ith row
546
547 ueem[i]=mass_plus;
548 for(int j=1;j<=i;j++) ueem[i]*= cee[j]/bee[j];
549 ueem[i]*= aee[0]/bee[0];
550
551 } else {
552 lee[i] =0.0;
553 leem[i]=0.0;
554 uee[i] =0.0;
555 ueem[i]=0.0;
556 }
557 }
558
559 {
560 Coeff_t delta_d=mass_minus*cee[Ls-1];
561 for(int j=0;j<Ls-1;j++) {
562 assert(bee[j] != Coeff_t(0.0));
563 delta_d *= cee[j]/bee[j];
564 }
565 dee[Ls-1] += delta_d;
566 }
567
569 // Device buffers
571 d_diag.resize(Ls);
572 d_upper.resize(Ls);
573 d_lower.resize(Ls);
574
575 d_dee.resize(Ls);
576 d_lee.resize(Ls);
577 d_uee.resize(Ls);
578 d_leem.resize(Ls);
579 d_ueem.resize(Ls);
580 // int inv=1;
581 // this->MooeeInternalCompute(0,inv,MatpInv,MatmInv);
582 // this->MooeeInternalCompute(1,inv,MatpInvDag,MatmInvDag);
583}
584
585
586template <class Impl>
587void CayleyFermion5D<Impl>::ContractJ5q(FermionField &q_in,ComplexField &J5q)
588{
589 conformable(this->GaugeGrid(), J5q.Grid());
590 conformable(q_in.Grid(), this->FermionGrid());
591 Gamma G5(Gamma::Algebra::Gamma5);
592 // 4d field
593 int Ls = this->Ls;
594 FermionField psi(this->GaugeGrid());
595 FermionField p_plus (this->GaugeGrid());
596 FermionField p_minus(this->GaugeGrid());
597 FermionField p(this->GaugeGrid());
598
599 ExtractSlice(p_plus , q_in, Ls/2-1 , 0);
600 ExtractSlice(p_minus, q_in, Ls/2 , 0);
601 p_plus = p_plus + G5*p_plus;
602 p_minus= p_minus - G5*p_minus;
603 p=0.5*(p_plus+p_minus);
604 J5q = localInnerProduct(p,p);
605}
606
607template <class Impl>
608void CayleyFermion5D<Impl>::ContractJ5q(PropagatorField &q_in,ComplexField &J5q)
609{
610 conformable(this->GaugeGrid(), J5q.Grid());
611 conformable(q_in.Grid(), this->FermionGrid());
612 Gamma G5(Gamma::Algebra::Gamma5);
613 // 4d field
614 int Ls = this->Ls;
615 PropagatorField psi(this->GaugeGrid());
616 PropagatorField p_plus (this->GaugeGrid());
617 PropagatorField p_minus(this->GaugeGrid());
618 PropagatorField p(this->GaugeGrid());
619
620 ExtractSlice(p_plus , q_in, Ls/2-1 , 0);
621 ExtractSlice(p_minus, q_in, Ls/2 , 0);
622 p_plus = p_plus + G5*p_plus;
623 p_minus= p_minus - G5*p_minus;
624 p=0.5*(p_plus+p_minus);
625 J5q = localInnerProduct(p,p);
626}
627
628#define Pp(Q) (0.5*(Q+g5*Q))
629#define Pm(Q) (0.5*(Q-g5*Q))
630#define Q_4d(Q) (Pm((Q)[0]) + Pp((Q)[Ls-1]))
631#define TopRowWithSource(Q) (phys_src + (1.0-mass)*Q_4d(Q))
632
633template <class Impl>
635 PropagatorField &q_in_2,
636 PropagatorField &q_out,
637 PropagatorField &phys_src,
638 Current curr_type,
639 unsigned int mu)
640{
641
642 assert(mass_plus == mass_minus);
643 RealD mass = mass_plus;
644
645 Gamma::Algebra Gmu [] = {
646 Gamma::Algebra::GammaX,
647 Gamma::Algebra::GammaY,
648 Gamma::Algebra::GammaZ,
649 Gamma::Algebra::GammaT,
650 Gamma::Algebra::Gamma5
651 };
652
653 auto UGrid= this->GaugeGrid();
654 auto FGrid= this->FermionGrid();
655 RealD sgn=1.0;
656 if ( curr_type == Current::Axial ) sgn = -1.0;
657
658 int Ls = this->Ls;
659
660 std::vector<PropagatorField> L_Q(Ls,UGrid);
661 std::vector<PropagatorField> R_Q(Ls,UGrid);
662 for(int s=0;s<Ls;s++){
663 ExtractSlice(L_Q[s], q_in_1, s , 0);
664 ExtractSlice(R_Q[s], q_in_2, s , 0);
665 }
666
667 Gamma g5(Gamma::Algebra::Gamma5);
668 PropagatorField C(UGrid);
669 PropagatorField p5d(UGrid);
670 PropagatorField us_p5d(UGrid);
671 PropagatorField gp5d(UGrid);
672 PropagatorField gus_p5d(UGrid);
673
674 PropagatorField L_TmLsGq0(UGrid);
675 PropagatorField L_TmLsTmp(UGrid);
676 PropagatorField R_TmLsGq0(UGrid);
677 PropagatorField R_TmLsTmp(UGrid);
678 {
679 PropagatorField TermA(UGrid);
680 PropagatorField TermB(UGrid);
681 PropagatorField TermC(UGrid);
682 PropagatorField TermD(UGrid);
683 TermA = (Pp(Q_4d(L_Q)));
684 TermB = (Pm(Q_4d(L_Q)));
685 TermC = (Pm(TopRowWithSource(L_Q)));
686 TermD = (Pp(TopRowWithSource(L_Q)));
687
688 L_TmLsGq0 = (TermD - TermA + TermB);
689 L_TmLsTmp = (TermC - TermB + TermA);
690
691 TermA = (Pp(Q_4d(R_Q)));
692 TermB = (Pm(Q_4d(R_Q)));
693 TermC = (Pm(TopRowWithSource(R_Q)));
694 TermD = (Pp(TopRowWithSource(R_Q)));
695
696 R_TmLsGq0 = (TermD - TermA + TermB);
697 R_TmLsTmp = (TermC - TermB + TermA);
698 }
699
700 std::vector<PropagatorField> R_TmLsGq(Ls,UGrid);
701 std::vector<PropagatorField> L_TmLsGq(Ls,UGrid);
702 for(int s=0;s<Ls;s++){
703 R_TmLsGq[s] = (Pm((R_Q)[(s)]) + Pp((R_Q)[((s)-1+Ls)%Ls]));
704 L_TmLsGq[s] = (Pm((L_Q)[(s)]) + Pp((L_Q)[((s)-1+Ls)%Ls]));
705 }
706
707 Gamma gmu=Gamma(Gmu[mu]);
708
709 q_out = Zero();
710 PropagatorField tmp(UGrid);
711 for(int s=0;s<Ls;s++){
712
713 int sp = (s+1)%Ls;
714 int sr = Ls-1-s;
715 int srp= (sr+1)%Ls;
716
717 // Mobius parameters
718 auto b=this->bs[s];
719 auto c=this->cs[s];
720 auto bpc = 1.0/(b+c); // -0.5 factor in gauge links
721 if (s == 0) {
722 p5d =(b*Pm(L_TmLsGq[Ls-1])+ c*Pp(L_TmLsGq[Ls-1]) + b*Pp(L_TmLsTmp) + c*Pm(L_TmLsTmp ));
723 tmp =(b*Pm(R_TmLsGq0) + c*Pp(R_TmLsGq0 ) + b*Pp(R_TmLsGq[1]) + c*Pm(R_TmLsGq[1]));
724 } else if (s == Ls-1) {
725 p5d =(b*Pm(L_TmLsGq0) + c*Pp(L_TmLsGq0 ) + b*Pp(L_TmLsGq[1]) + c*Pm(L_TmLsGq[1]));
726 tmp =(b*Pm(R_TmLsGq[Ls-1])+ c*Pp(R_TmLsGq[Ls-1]) + b*Pp(R_TmLsTmp) + c*Pm(R_TmLsTmp ));
727 } else {
728 p5d =(b*Pm(L_TmLsGq[sr]) + c*Pp(L_TmLsGq[sr])+ b*Pp(L_TmLsGq[srp])+ c*Pm(L_TmLsGq[srp]));
729 tmp =(b*Pm(R_TmLsGq[s]) + c*Pp(R_TmLsGq[s]) + b*Pp(R_TmLsGq[sp ])+ c*Pm(R_TmLsGq[sp]));
730 }
731 tmp = Cshift(tmp,mu,1);
732 Impl::multLinkField(us_p5d,this->Umu,tmp,mu);
733
734 gp5d=g5*p5d*g5;
735 gus_p5d=gmu*us_p5d;
736
737 C = bpc*(adj(gp5d)*us_p5d);
738 C-= bpc*(adj(gp5d)*gus_p5d);
739
740 if (s == 0) {
741 p5d =(b*Pm(R_TmLsGq0) + c*Pp(R_TmLsGq0 ) + b*Pp(R_TmLsGq[1]) + c*Pm(R_TmLsGq[1]));
742 tmp =(b*Pm(L_TmLsGq[Ls-1])+ c*Pp(L_TmLsGq[Ls-1]) + b*Pp(L_TmLsTmp) + c*Pm(L_TmLsTmp ));
743 } else if (s == Ls-1) {
744 p5d =(b*Pm(R_TmLsGq[Ls-1])+ c*Pp(R_TmLsGq[Ls-1]) + b*Pp(R_TmLsTmp) + c*Pm(R_TmLsTmp ));
745 tmp =(b*Pm(L_TmLsGq0) + c*Pp(L_TmLsGq0 ) + b*Pp(L_TmLsGq[1]) + c*Pm(L_TmLsGq[1]));
746 } else {
747 p5d =(b*Pm(R_TmLsGq[s]) + c*Pp(R_TmLsGq[s]) + b*Pp(R_TmLsGq[sp ])+ c*Pm(R_TmLsGq[sp]));
748 tmp =(b*Pm(L_TmLsGq[sr]) + c*Pp(L_TmLsGq[sr]) + b*Pp(L_TmLsGq[srp])+ c*Pm(L_TmLsGq[srp]));
749 }
750 tmp = Cshift(tmp,mu,1);
751 Impl::multLinkField(us_p5d,this->Umu,tmp,mu);
752
753 gp5d=gmu*p5d;
754 gus_p5d=g5*us_p5d*g5;
755
756 C-= bpc*(adj(gus_p5d)*gp5d);
757 C-= bpc*(adj(gus_p5d)*p5d);
758
759 if (s < Ls/2) q_out += sgn*C;
760 else q_out += C;
761
762 }
763
764}
765
766template <class Impl>
768 PropagatorField &q_out,
769 PropagatorField &phys_src,
770 Current curr_type,
771 unsigned int mu,
772 unsigned int tmin,
773 unsigned int tmax,
774 ComplexField &ph)// Complex phase factor
775{
776 assert(mu>=0);
777 assert(mu<Nd);
778
779 assert(mass_plus == mass_minus);
780 RealD mass = mass_plus;
781
782#if 0
783 int tshift = (mu == Nd-1) ? 1 : 0;
785 // SHAMIR CASE
787 int Ls = this->Ls;
788 auto UGrid= this->GaugeGrid();
789 auto FGrid= this->FermionGrid();
790 Gamma::Algebra Gmu [] = {
791 Gamma::Algebra::GammaX,
792 Gamma::Algebra::GammaY,
793 Gamma::Algebra::GammaZ,
794 Gamma::Algebra::GammaT
795 };
796 Gamma gmu=Gamma(Gmu[mu]);
797
798 PropagatorField L_Q(UGrid);
799 PropagatorField R_Q(UGrid);
800
801 PropagatorField tmp(UGrid);
802 PropagatorField Utmp(UGrid);
803 PropagatorField zz (UGrid); zz=0.0;
804 LatticeInteger lcoor(UGrid); LatticeCoordinate(lcoor,Nd-1);
805 for (int s=0;s<Ls;s++) {
806
807 RealD G_s = (curr_type == Current::Axial ) ? ((s < Ls/2) ? -1 : 1) : 1;
808
809 ExtractSlice(R_Q, q_in, s , 0);
810
811 tmp = Cshift(R_Q,mu,1);
812 Impl::multLinkField(Utmp,this->Umu,tmp,mu);
813 tmp = G_s*( Utmp*ph - gmu*Utmp*ph ); // Forward hop
814 tmp = where((lcoor>=tmin),tmp,zz); // Mask the time
815 tmp = where((lcoor<=tmax),tmp,zz);
816 L_Q = tmp;
817
818 tmp = R_Q*ph;
819 tmp = Cshift(tmp,mu,-1);
820 Impl::multLinkField(Utmp,this->Umu,tmp,mu+Nd);// Adjoint link
821 tmp = -G_s*( Utmp + gmu*Utmp );
822 tmp = where((lcoor>=tmin+tshift),tmp,zz); // Mask the time
823 tmp = where((lcoor<=tmax+tshift),tmp,zz); // Position of current complicated
824 L_Q= L_Q+tmp;
825
826 InsertSlice(L_Q, q_out, s , 0);
827 }
828#endif
829
830 int tshift = (mu == Nd-1) ? 1 : 0;
831 unsigned int LLt = GridDefaultLatt()[Tp];
833 // GENERAL CAYLEY CASE
835 Gamma::Algebra Gmu [] = {
836 Gamma::Algebra::GammaX,
837 Gamma::Algebra::GammaY,
838 Gamma::Algebra::GammaZ,
839 Gamma::Algebra::GammaT,
840 Gamma::Algebra::Gamma5
841 };
842 Gamma gmu=Gamma(Gmu[mu]);
843 Gamma g5(Gamma::Algebra::Gamma5);
844
845 int Ls = this->Ls;
846 auto UGrid= this->GaugeGrid();
847 auto FGrid= this->FermionGrid();
848
849 std::vector<PropagatorField> R_Q(Ls,UGrid);
850 PropagatorField L_Q(UGrid);
851 PropagatorField tmp(UGrid);
852 PropagatorField Utmp(UGrid);
853
854 PropagatorField zz (UGrid); zz=0.0;
855 LatticeInteger lcoor(UGrid); LatticeCoordinate(lcoor,Nd-1);
856
857 for(int s=0;s<Ls;s++){
858 ExtractSlice(R_Q[s], q_in, s , 0);
859 }
860
861 PropagatorField R_TmLsGq0(UGrid);
862 PropagatorField R_TmLsTmp(UGrid);
863 {
864 PropagatorField TermA(UGrid);
865 PropagatorField TermB(UGrid);
866 PropagatorField TermC(UGrid);
867 PropagatorField TermD(UGrid);
868
869 TermA = (Pp(Q_4d(R_Q)));
870 TermB = (Pm(Q_4d(R_Q)));
871 TermC = (Pm(TopRowWithSource(R_Q)));
872 TermD = (Pp(TopRowWithSource(R_Q)));
873
874 R_TmLsGq0 = (TermD - TermA + TermB);
875 R_TmLsTmp = (TermC - TermB + TermA);
876 }
877
878 std::vector<PropagatorField> R_TmLsGq(Ls,UGrid);
879 for(int s=0;s<Ls;s++){
880 R_TmLsGq[s] = (Pm((R_Q)[(s)]) + Pp((R_Q)[((s)-1+Ls)%Ls]));
881 }
882
883 std::vector<RealD> G_s(Ls,1.0);
884 RealD sign = 1.0; // sign flip for vector/tadpole
885 if ( curr_type == Current::Axial ) {
886 for(int s=0;s<Ls/2;s++){
887 G_s[s] = -1.0;
888 }
889 }
890 else if ( curr_type == Current::Tadpole ) {
891 auto b=this->_b;
892 auto c=this->_c;
893 if ( b == 1 && c == 0 ) {
894 sign = -1.0;
895 }
896 else {
897 std::cerr << "Error: Tadpole implementation currently unavailable for non-Shamir actions." << std::endl;
898 assert(b==1 && c==0);
899 }
900 }
901
902 for(int s=0;s<Ls;s++){
903
904 int sp = (s+1)%Ls;
905 // int sr = Ls-1-s;
906 // int srp= (sr+1)%Ls;
907
908 // Mobius parameters
909 auto b=this->bs[s];
910 auto c=this->cs[s];
911 // auto bpc = G_s[s]*1.0/(b+c); // -0.5 factor in gauge links
912
913 if (s == 0) {
914 tmp =(b*Pm(R_TmLsGq0) + c*Pp(R_TmLsGq0 ) + b*Pp(R_TmLsGq[1]) + c*Pm(R_TmLsGq[1]));
915 } else if (s == Ls-1) {
916 tmp =(b*Pm(R_TmLsGq[Ls-1])+ c*Pp(R_TmLsGq[Ls-1]) + b*Pp(R_TmLsTmp) + c*Pm(R_TmLsTmp ));
917 } else {
918 tmp =(b*Pm(R_TmLsGq[s]) + c*Pp(R_TmLsGq[s]) + b*Pp(R_TmLsGq[sp ])+ c*Pm(R_TmLsGq[sp]));
919 }
920
921 tmp = Cshift(tmp,mu,1);
922 Impl::multLinkField(Utmp,this->Umu,tmp,mu);
923 tmp = sign*G_s[s]*( Utmp*ph - gmu*Utmp*ph ); // Forward hop
924 tmp = where((lcoor>=tmin),tmp,zz); // Mask the time
925 L_Q = where((lcoor<=tmax),tmp,zz); // Position of current complicated
926
927 if (s == 0) {
928 tmp =(b*Pm(R_TmLsGq0) + c*Pp(R_TmLsGq0 ) + b*Pp(R_TmLsGq[1]) + c*Pm(R_TmLsGq[1]));
929 } else if (s == Ls-1) {
930 tmp =(b*Pm(R_TmLsGq[Ls-1])+ c*Pp(R_TmLsGq[Ls-1]) + b*Pp(R_TmLsTmp) + c*Pm(R_TmLsTmp ));
931 } else {
932 tmp =(b*Pm(R_TmLsGq[s]) + c*Pp(R_TmLsGq[s]) + b*Pp(R_TmLsGq[sp])+ c*Pm(R_TmLsGq[sp]));
933 }
934 tmp = tmp *ph;
935 tmp = Cshift(tmp,mu,-1);
936 Impl::multLinkField(Utmp,this->Umu,tmp,mu+Nd); // Adjoint link
937 tmp = -G_s[s]*( Utmp + gmu*Utmp );
938 // Mask the time
939 if (tmax == LLt - 1 && tshift == 1){ // quick fix to include timeslice 0 if tmax + tshift is over the last timeslice
940 unsigned int t0 = 0;
941 tmp = where(((lcoor==t0) || (lcoor>=tmin+tshift)),tmp,zz);
942 } else {
943 tmp = where((lcoor>=tmin+tshift),tmp,zz);
944 }
945 L_Q += where((lcoor<=tmax+tshift),tmp,zz); // Position of current complicated
946
947 InsertSlice(L_Q, q_out, s , 0);
948 }
949}
950#undef Pp
951#undef Pm
952#undef Q_4d
953#undef TopRowWithSource
954
955
957
958
static const int Odd
#define TopRowWithSource(Q)
#define Q_4d(Q)
auto Cshift(const Expression &expr, int dim, int shift) -> decltype(closure(expr))
Definition Cshift.h:55
const Coordinate & GridDefaultLatt(void)
Definition Init.cc:107
void axpby(Lattice< vobj > &ret, sobj a, sobj b, const Lattice< vobj > &x, const Lattice< vobj > &y)
void conformable(const Lattice< obj1 > &lhs, const Lattice< obj2 > &rhs)
void LatticeCoordinate(Lattice< iobj > &l, int mu)
auto localInnerProduct(const Lattice< vobj > &lhs, const Lattice< vobj > &rhs) -> Lattice< typename vobj::tensor_reduced >
Lattice< vobj > conjugate(const Lattice< vobj > &lhs)
Lattice< vobj > adj(const Lattice< vobj > &lhs)
void InsertSlice(const Lattice< vobj > &lowDim, Lattice< vobj > &higherDim, int slice, int orthog)
void ExtractSlice(Lattice< vobj > &lowDim, const Lattice< vobj > &higherDim, int slice, int orthog)
void axpby_ssp_pplus(Lattice< vobj > &z, Coeff a, const Lattice< vobj > &x, Coeff b, const Lattice< vobj > &y, int s, int sp)
void axpby_ssp_pminus(Lattice< vobj > &z, Coeff a, const Lattice< vobj > &x, Coeff b, const Lattice< vobj > &y, int s, int sp)
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
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
static constexpr int DaggerYes
Definition QCD.h:70
Lattice< vTInteger > LatticeInteger
Definition QCD.h:364
static constexpr int Nd
Definition QCD.h:52
static constexpr int Tp
Definition QCD.h:44
static constexpr int DaggerNo
Definition QCD.h:69
std::complex< RealD > ComplexD
Definition Simd.h:79
double RealD
Definition Simd.h:61
static INTERNAL_PRECISION U
Definition Zolotarev.cc:230
CayleyFermion5D(GaugeField &_Umu, GridCartesian &FiveDimGrid, GridRedBlackCartesian &FiveDimRedBlackGrid, GridCartesian &FourDimGrid, GridRedBlackCartesian &FourDimRedBlackGrid, RealD _mass, RealD _M5, const ImplParams &p=ImplParams())
void Meooe5D(const FermionField &in, FermionField &out)
virtual void SetCoefficientsInternal(RealD zolo_hi, std::vector< Coeff_t > &gamma, RealD b, RealD c)
std::vector< ComplexD > qmu
std::vector< Coeff_t > leem
virtual void Mdir(const FermionField &in, FermionField &out, int dir, int disp)
std::vector< Coeff_t > as
virtual void MeoDeriv(GaugeField &mat, const FermionField &U, const FermionField &V, int dag)
std::vector< Coeff_t > lee
deviceVector< Coeff_t > d_upper
virtual void SetCoefficientsZolotarev(RealD zolohi, Approx::zolotarev_data *zdata, RealD b, RealD c)
deviceVector< Coeff_t > d_uee
virtual void MoeDeriv(GaugeField &mat, const FermionField &U, const FermionField &V, int dag)
deviceVector< Coeff_t > d_dee
std::vector< Coeff_t > bee
std::vector< Coeff_t > dee
virtual void MDeriv(GaugeField &mat, const FermionField &U, const FermionField &V, int dag)
deviceVector< Coeff_t > d_diag
virtual void ExportPhysicalFermionSource(const FermionField &solution5d, FermionField &exported4d)
virtual void Mdag(const FermionField &in, FermionField &out)
std::vector< Coeff_t > cs
virtual void M5Ddag(const FermionField &psi, FermionField &chi)
virtual void Meo5D(const FermionField &psi, FermionField &chi)
virtual void ImportPhysicalFermionSource(const FermionField &input4d, FermionField &imported5d)
virtual void DminusDag(const FermionField &psi, FermionField &chi)
void addQmu(const FermionField &in, FermionField &out, int dag)
void ContractConservedCurrent(PropagatorField &q_in_1, PropagatorField &q_in_2, PropagatorField &q_out, PropagatorField &phys_src, Current curr_type, unsigned int mu)
virtual void MdirAll(const FermionField &in, std::vector< FermionField > &out)
virtual void Dminus(const FermionField &psi, FermionField &chi)
virtual void MeooeDag(const FermionField &in, FermionField &out)
std::vector< Coeff_t > beo
void P(const FermionField &psi, FermionField &chi)
std::vector< Coeff_t > bs
virtual void M(const FermionField &in, FermionField &out)
void MeooeDag5D(const FermionField &in, FermionField &out)
std::vector< Coeff_t > _gamma
std::vector< Coeff_t > aeo
void ContractJ5q(PropagatorField &q_in, ComplexField &J5q)
virtual void M5D(const FermionField &psi, FermionField &chi)
virtual void ExportPhysicalFermionSolution(const FermionField &solution5d, FermionField &exported4d)
deviceVector< Coeff_t > d_lower
virtual void SetCoefficientsTanh(Approx::zolotarev_data *zdata, RealD b, RealD c)
std::vector< Coeff_t > ceo
void SeqConservedCurrent(PropagatorField &q_in, PropagatorField &q_out, PropagatorField &phys_src, Current curr_type, unsigned int mu, unsigned int tmin, unsigned int tmax, ComplexField &lattice_cmplx)
deviceVector< Coeff_t > d_leem
virtual void Meooe(const FermionField &in, FermionField &out)
deviceVector< Coeff_t > d_lee
virtual void MooeeDag(const FermionField &in, FermionField &out)
std::vector< Coeff_t > ueem
virtual void ImportUnphysicalFermion(const FermionField &solution5d, FermionField &exported4d)
std::vector< Coeff_t > cee
void Pdag(const FermionField &psi, FermionField &chi)
std::vector< Coeff_t > omega
virtual void Mooee(const FermionField &in, FermionField &out)
deviceVector< Coeff_t > d_ueem
std::vector< Coeff_t > aee
std::vector< Coeff_t > uee
Definition Gamma.h:10
GridBase * GaugeGrid(void)
FermionField & tmp(void)
GridBase * FermionGrid(void)
virtual void DhopDerivEO(GaugeField &mat, const FermionField &U, const FermionField &V, int dag)
void DW(const FermionField &in, FermionField &out, int dag)
void DhopDir(const FermionField &in, FermionField &out, int dir, int disp)
void DhopDirAll(const FermionField &in, std::vector< FermionField > &out)
WilsonFermion5D(GaugeField &_Umu, GridCartesian &FiveDimGrid, GridRedBlackCartesian &FiveDimRedBlackGrid, GridCartesian &FourDimGrid, GridRedBlackCartesian &FourDimRedBlackGrid, double _M5, const ImplParams &p=ImplParams())
virtual void DhopDeriv(GaugeField &mat, const FermionField &U, const FermionField &V, int dag)
void DhopEO(const FermionField &in, FermionField &out, int dag)
virtual void DhopDerivOE(GaugeField &mat, const FermionField &U, const FermionField &V, int dag)
DoubledGaugeField Umu
void DhopOE(const FermionField &in, FermionField &out, int dag)
Definition Simd.h:194