Grid 0.7.0
GparityWilsonImpl.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/FermionOperatorImpl.h
6
7Copyright (C) 2015
8
9Author: Peter Boyle <pabobyle@ph.ed.ac.uk>
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License along
22with this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25See the full license in the file "LICENSE" in the top level distribution
26directory
27*************************************************************************************/
28 /* END LEGAL */
29#pragma once
30
32
33/*
34 Policy implementation for G-parity boundary conditions
35
36 Rather than treating the gauge field as a flavored field, the Grid implementation of G-parity treats the gauge field as a regular
37 field with complex conjugate boundary conditions. In order to ensure the second flavor interacts with the conjugate links and the first
38 with the regular links we overload the functionality of doubleStore, whose purpose is to store the gauge field and the barrel-shifted gauge field
39 to avoid communicating links when applying the Dirac operator, such that the double-stored field contains also a flavor index which maps to
40 either the link or the conjugate link. This flavored field is then used by multLink to apply the correct link to a spinor.
41
42 Here the first Nd-1 directions are treated as "spatial", and a twist value of 1 indicates G-parity BCs in that direction.
43 mu=Nd-1 is assumed to be the time direction and a twist value of 1 indicates antiperiodic BCs
44 */
45template <class S, class Representation = FundamentalRepresentation, class Options=CoeffReal>
46class GparityWilsonImpl : public ConjugateGaugeImpl<GaugeImplTypes<S, Representation::Dimension> > {
47public:
48
49 static const int Dimension = Representation::Dimension;
50 static const bool isFundamental = Representation::isFundamental;
51 static const int Nhcs = Options::Nhcs;
52 static const bool LsVectorised=false;
53 static const bool isGparity=true;
54
57
58 typedef typename Options::_Coeff_t Coeff_t;
59 typedef typename Options::template PrecisionMapper<Simd>::LowerPrecVector SimdL;
60
61 template <typename vtype> using iImplSpinor = iVector<iVector<iVector<vtype, Dimension>, Ns>, Ngp>;
62 template <typename vtype> using iImplPropagator = iMatrix<iMatrix<iMatrix<vtype, Dimension>, Ns>, Ngp>;
66
72
76
81
83
85
86 // provide the multiply by link that is differentiated between Gparity (with
87 // flavour index) and non-Gparity
88 template<class _Spinor>
89 static accelerator_inline void multLink(_Spinor &phi,
91 const _Spinor &chi,
92 int mu)
93 {
94 assert(0);
95 }
96
97 template<class _Spinor>
98 static accelerator_inline void multLink(_Spinor &phi,
100 const _Spinor &chi,
101 int mu,
102 StencilEntry *SE,
103 StencilView &St)
104 {
105 int direction = St._directions[mu];
106 int distance = St._distances[mu];
107 int ptype = St._permute_type[mu];
108 int sl = St._simd_layout[direction];
109 Coordinate icoor;
110
111#ifdef GRID_SIMT
112 const int Nsimd =SiteDoubledGaugeField::Nsimd();
113 int s = acceleratorSIMTlane(Nsimd);
114 St.iCoorFromIindex(icoor,s);
115
116 int mmu = mu % Nd;
117
118 auto UU0=coalescedRead(U(0)(mu));
119 auto UU1=coalescedRead(U(1)(mu));
120
121 //Decide whether we do a G-parity flavor twist
122 //Note: this assumes (but does not check) that sl==1 || sl==2 i.e. max 2 SIMD lanes in G-parity dir
123 //It also assumes (but does not check) that abs(distance) == 1
124 int permute_lane = (sl==1)
125 || ((distance== 1)&&(icoor[direction]==1))
126 || ((distance==-1)&&(icoor[direction]==0));
127
128 permute_lane = permute_lane && SE->_around_the_world && St.parameters.twists[mmu] && mmu < Nd-1; //only if we are going around the world in a spatial direction
129
130 //Apply the links
131 int f_upper = permute_lane ? 1 : 0;
132 int f_lower = !f_upper;
133
134 mult(&phi(0),&UU0,&chi(f_upper));
135 mult(&phi(1),&UU1,&chi(f_lower));
136
137#else
138 typedef _Spinor vobj;
139 typedef typename SiteHalfSpinor::scalar_object sobj;
140 typedef typename SiteHalfSpinor::vector_type vector_type;
141
142 vobj vtmp;
143 sobj stmp;
144
145 const int Nsimd =vector_type::Nsimd();
146
147 // Fixme X.Y.Z.T hardcode in stencil
148 int mmu = mu % Nd;
149
150 // assert our assumptions
151 assert((distance == 1) || (distance == -1)); // nearest neighbour stencil hard code
152 assert((sl == 1) || (sl == 2));
153
154 //If this site is an global boundary site, perform the G-parity flavor twist
155 if ( mmu < Nd-1 && SE->_around_the_world && St.parameters.twists[mmu] ) {
156 if ( sl == 2 ) {
157 //Only do the twist for lanes on the edge of the physical node
158 ExtractBuffer<sobj> vals(Nsimd);
159
160 extract(chi,vals);
161 for(int s=0;s<Nsimd;s++){
162
163 St.iCoorFromIindex(icoor,s);
164
165 assert((icoor[direction]==0)||(icoor[direction]==1));
166
167 int permute_lane;
168 if ( distance == 1) {
169 permute_lane = icoor[direction]?1:0;
170 } else {
171 permute_lane = icoor[direction]?0:1;
172 }
173
174 if ( permute_lane ) {
175 stmp(0) = vals[s](1);
176 stmp(1) = vals[s](0);
177 vals[s] = stmp;
178 }
179 }
180 merge(vtmp,vals);
181
182 } else {
183 vtmp(0) = chi(1);
184 vtmp(1) = chi(0);
185 }
186 mult(&phi(0),&U(0)(mu),&vtmp(0));
187 mult(&phi(1),&U(1)(mu),&vtmp(1));
188
189 } else {
190 mult(&phi(0),&U(0)(mu),&chi(0));
191 mult(&phi(1),&U(1)(mu),&chi(1));
192 }
193#endif
194 }
195
196
197 template<class _SpinorField>
198 inline void multLinkField(_SpinorField & out,
199 const DoubledGaugeField &Umu,
200 const _SpinorField & phi,
201 int mu)
202 {
203 assert(0);
204 }
205
206 template <class ref>
207 static accelerator_inline void loadLinkElement(Simd &reg, ref &memory)
208 {
209 reg = memory;
210 }
211
212
213 //Poke 'poke_f0' onto flavor 0 and 'poke_f1' onto flavor 1 in direction mu of the doubled gauge field Uds
214 inline void pokeGparityDoubledGaugeField(DoubledGaugeField &Uds, const GaugeLinkField &poke_f0, const GaugeLinkField &poke_f1, const int mu){
215 autoView(poke_f0_v, poke_f0, CpuRead);
216 autoView(poke_f1_v, poke_f1, CpuRead);
217 autoView(Uds_v, Uds, CpuWrite);
218 thread_foreach(ss,poke_f0_v,{
219 Uds_v[ss](0)(mu) = poke_f0_v[ss]();
220 Uds_v[ss](1)(mu) = poke_f1_v[ss]();
221 });
222 }
223
224
225 inline void DoubleStore(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu)
226 {
227 conformable(Uds.Grid(),GaugeGrid);
228 conformable(Umu.Grid(),GaugeGrid);
229
230 GaugeLinkField Utmp (GaugeGrid);
231 GaugeLinkField U (GaugeGrid);
232 GaugeLinkField Uconj(GaugeGrid);
233
234 Lattice<iScalar<vInteger> > coor(GaugeGrid);
235
236 //Here the first Nd-1 directions are treated as "spatial", and a twist value of 1 indicates G-parity BCs in that direction.
237 //mu=Nd-1 is assumed to be the time direction and a twist value of 1 indicates antiperiodic BCs
238 for(int mu=0;mu<Nd-1;mu++){
239
240 if( Params.twists[mu] ){
241 LatticeCoordinate(coor,mu);
242 }
243
244 U = PeekIndex<LorentzIndex>(Umu,mu);
245 Uconj = conjugate(U);
246
247 // Implement the isospin rotation sign on the boundary between f=1 and f=0
248 // This phase could come from a simple bc 1,1,-1,1 ..
249 int neglink = GaugeGrid->GlobalDimensions()[mu]-1;
250 if ( Params.twists[mu] ) {
251 Uconj = where(coor==neglink,-Uconj,Uconj);
252 }
253
254 {
255 autoView( U_v , U, CpuRead);
256 autoView( Uconj_v , Uconj, CpuRead);
257 autoView( Uds_v , Uds, CpuWrite);
258 autoView( Utmp_v, Utmp, CpuWrite);
259 thread_foreach(ss,U_v,{
260 Uds_v[ss](0)(mu) = U_v[ss]();
261 Uds_v[ss](1)(mu) = Uconj_v[ss]();
262 });
263 }
264
265 U = adj(Cshift(U ,mu,-1)); // correct except for spanning the boundary
266 Uconj = adj(Cshift(Uconj,mu,-1));
267
268 Utmp = U;
269 if ( Params.twists[mu] ) {
270 Utmp = where(coor==0,Uconj,Utmp);
271 }
272
273 {
274 autoView( Uds_v , Uds, CpuWrite);
275 autoView( Utmp_v, Utmp, CpuWrite);
276 thread_foreach(ss,Utmp_v,{
277 Uds_v[ss](0)(mu+4) = Utmp_v[ss]();
278 });
279 }
280 Utmp = Uconj;
281 if ( Params.twists[mu] ) {
282 Utmp = where(coor==0,U,Utmp);
283 }
284
285 {
286 autoView( Uds_v , Uds, CpuWrite);
287 autoView( Utmp_v, Utmp, CpuWrite);
288 thread_foreach(ss,Utmp_v,{
289 Uds_v[ss](1)(mu+4) = Utmp_v[ss]();
290 });
291 }
292 }
293
294 { //periodic / antiperiodic temporal BCs
295 int mu = Nd-1;
296 int L = GaugeGrid->GlobalDimensions()[mu];
297 int Lmu = L - 1;
298
299 LatticeCoordinate(coor, mu);
300
301 U = PeekIndex<LorentzIndex>(Umu, mu); //Get t-directed links
302
303 GaugeLinkField *Upoke = &U;
304
305 if(Params.twists[mu]){ //antiperiodic
306 Utmp = where(coor == Lmu, -U, U);
307 Upoke = &Utmp;
308 }
309
310 Uconj = conjugate(*Upoke); //second flavor interacts with conjugate links
311 pokeGparityDoubledGaugeField(Uds, *Upoke, Uconj, mu);
312
313 //Get the barrel-shifted field
314 Utmp = adj(Cshift(U, mu, -1)); //is a forward shift!
315 Upoke = &Utmp;
316
317 if(Params.twists[mu]){
318 U = where(coor == 0, -Utmp, Utmp); //boundary phase
319 Upoke = &U;
320 }
321
322 Uconj = conjugate(*Upoke);
323 pokeGparityDoubledGaugeField(Uds, *Upoke, Uconj, mu + 4);
324 }
325 }
326
327 inline void InsertForce4D(GaugeField &mat, FermionField &Btilde, FermionField &A, int mu) {
328
329 // DhopDir provides U or Uconj depending on coor/flavour.
330 GaugeLinkField link(mat.Grid());
331 // use lorentz for flavour as hack.
332 auto tmp = TraceIndex<SpinIndex>(outerProduct(Btilde, A));
333
334 {
335 autoView( link_v , link, CpuWrite);
336 autoView( tmp_v , tmp, CpuRead);
337 thread_foreach(ss,tmp_v,{
338 link_v[ss]() = tmp_v[ss](0, 0) + conjugate(tmp_v[ss](1, 1));
339 });
340 }
341 PokeIndex<LorentzIndex>(mat, link, mu);
342 return;
343 }
344
345 inline void outerProductImpl(PropagatorField &mat, const FermionField &Btilde, const FermionField &A){
346 //mat = outerProduct(Btilde, A);
347 assert(0);
348 }
349
350 inline void TraceSpinImpl(GaugeLinkField &mat, PropagatorField&P) {
351 assert(0);
352 /*
353 auto tmp = TraceIndex<SpinIndex>(P);
354 parallel_for(auto ss = tmp.begin(); ss < tmp.end(); ss++) {
355 mat[ss]() = tmp[ss](0, 0) + conjugate(tmp[ss](1, 1));
356 }
357 */
358 }
359
360 inline void extractLinkField(std::vector<GaugeLinkField> &mat, DoubledGaugeField &Uds){
361 assert(0);
362 }
363
364 inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField &Atilde, int mu) {
365 int Ls=Btilde.Grid()->_fdimensions[0];
366
367 {
368 GridBase *GaugeGrid = mat.Grid();
369 Lattice<iScalar<vInteger> > coor(GaugeGrid);
370
371 if( Params.twists[mu] ){
372 LatticeCoordinate(coor,mu);
373 }
374
375 autoView( mat_v , mat, AcceleratorWrite);
376 autoView( Btilde_v , Btilde, AcceleratorRead);
377 autoView( Atilde_v , Atilde, AcceleratorRead);
378 accelerator_for(sss,mat.Grid()->oSites(), FermionField::vector_type::Nsimd(),{
379 int sU=sss;
380 typedef decltype(coalescedRead(mat_v[sU](mu)() )) ColorMatrixType;
381 ColorMatrixType sum;
382 zeroit(sum);
383 for(int s=0;s<Ls;s++){
384 int sF = s+Ls*sU;
385 for(int spn=0;spn<Ns;spn++){ //sum over spin
386 //Flavor 0
387 auto bb = coalescedRead(Btilde_v[sF](0)(spn) ); //color vector
388 auto aa = coalescedRead(Atilde_v[sF](0)(spn) );
389 sum = sum + outerProduct(bb,aa);
390
391 //Flavor 1
392 bb = coalescedRead(Btilde_v[sF](1)(spn) );
393 aa = coalescedRead(Atilde_v[sF](1)(spn) );
394 sum = sum + conjugate(outerProduct(bb,aa));
395 }
396 }
397 coalescedWrite(mat_v[sU](mu)(), sum);
398 });
399 }
400 }
401
402
403
404
405
406};
407
411
412//typedef GparityWilsonImpl<vComplex , FundamentalRepresentation,CoeffRealHalfComms> GparityWilsonImplRL; // Real.. whichever prec
413//typedef GparityWilsonImpl<vComplexF, FundamentalRepresentation,CoeffRealHalfComms> GparityWilsonImplFH; // Float
414//typedef GparityWilsonImpl<vComplexD, FundamentalRepresentation,CoeffRealHalfComms> GparityWilsonImplDF; // Double
415
accelerator_inline int acceleratorSIMTlane(int Nsimd)
#define accelerator_inline
#define accelerator_for(iterator, num, nsimd,...)
AcceleratorVector< int, MaxDims > Coordinate
Definition Coordinate.h:95
auto Cshift(const Expression &expr, int dim, int shift) -> decltype(closure(expr))
Definition Cshift.h:55
GparityWilsonImpl< vComplex, FundamentalRepresentation, CoeffReal > GparityWilsonImplR
GparityWilsonImpl< vComplexF, FundamentalRepresentation, CoeffReal > GparityWilsonImplF
GparityWilsonImpl< vComplexD, FundamentalRepresentation, CoeffReal > GparityWilsonImplD
void mult(Lattice< obj1 > &ret, const Lattice< obj2 > &lhs, const Lattice< obj3 > &rhs)
void conformable(const Lattice< obj1 > &lhs, const Lattice< obj2 > &rhs)
void LatticeCoordinate(Lattice< iobj > &l, int mu)
auto outerProduct(const Lattice< ll > &lhs, const Lattice< rr > &rhs) -> Lattice< decltype(outerProduct(ll(), rr()))>
void PokeIndex(Lattice< vobj > &lhs, const Lattice< decltype(peekIndex< Index >(vobj(), 0))> &rhs, int i)
auto PeekIndex(const Lattice< vobj > &lhs, int i) -> Lattice< decltype(peekIndex< Index >(vobj(), i))>
Lattice< vobj > conjugate(const Lattice< vobj > &lhs)
Lattice< vobj > adj(const Lattice< vobj > &lhs)
vobj::scalar_object sum(const vobj *arg, Integer osites)
auto TraceIndex(const Lattice< vobj > &lhs) -> Lattice< decltype(traceIndex< Index >(vobj()))>
#define autoView(l_v, l, mode)
@ AcceleratorRead
@ CpuRead
@ AcceleratorWrite
@ CpuWrite
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
static constexpr int Nhs
Definition QCD.h:53
static constexpr int Ns
Definition QCD.h:51
static constexpr int Nd
Definition QCD.h:52
static constexpr int Nds
Definition QCD.h:54
static constexpr int Ngp
Definition QCD.h:55
accelerator_inline void coalescedWrite(vobj &__restrict__ vec, const vobj &__restrict__ extracted, int lane=0)
Definition Tensor_SIMT.h:87
accelerator_inline vobj coalescedRead(const vobj &__restrict__ vec, int lane=0)
Definition Tensor_SIMT.h:61
AcceleratorVector< __T,GRID_MAX_SIMD > ExtractBuffer
accelerator void extract(const vobj &vec, ExtractBuffer< sobj > &extracted)
accelerator void merge(vobj &vec, ExtractBuffer< sobj > &extracted)
#define thread_foreach(i, container,...)
Definition Threads.h:67
WilsonCompressorTemplate< HCS, HS, S, WilsonProjector > WilsonCompressor
static INTERNAL_PRECISION U
Definition Zolotarev.cc:230
StencilVector _permute_type
Definition Stencil.h:126
accelerator_inline void iCoorFromIindex(Coordinate &coor, int lane) const
Definition Stencil.h:167
StencilVector _directions
Definition Stencil.h:111
StencilVector _distances
Definition Stencil.h:112
static accelerator_inline void multLink(_Spinor &phi, const SiteDoubledGaugeField &U, const _Spinor &chi, int mu)
ConjugateGaugeImpl< GaugeImplTypes< S, Dimension > > Gimpl
void outerProductImpl(PropagatorField &mat, const FermionField &Btilde, const FermionField &A)
void DoubleStore(GridBase *GaugeGrid, DoubledGaugeField &Uds, const GaugeField &Umu)
Options::_Coeff_t Coeff_t
Lattice< SitePropagator > PropagatorField
void extractLinkField(std::vector< GaugeLinkField > &mat, DoubledGaugeField &Uds)
void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField &Atilde, int mu)
iVector< iVector< iVector< vtype, Dimension >, Ns >, Ngp > iImplSpinor
Lattice< SiteSpinor > FermionField
void pokeGparityDoubledGaugeField(DoubledGaugeField &Uds, const GaugeLinkField &poke_f0, const GaugeLinkField &poke_f1, const int mu)
iMatrix< iMatrix< iMatrix< vtype, Dimension >, Ns >, Ngp > iImplPropagator
WilsonStencil< SiteSpinor, SiteHalfSpinor, ImplParams > StencilImpl
iImplDoubledGaugeField< Simd > SiteDoubledGaugeField
void InsertForce4D(GaugeField &mat, FermionField &Btilde, FermionField &A, int mu)
StencilImpl::View_type StencilView
void TraceSpinImpl(GaugeLinkField &mat, PropagatorField &P)
iVector< iVector< iScalar< iMatrix< vtype, Dimension > >, Nds >, Ngp > iImplDoubledGaugeField
iImplHalfSpinor< Simd > SiteHalfSpinor
iVector< iVector< iVector< vtype, Dimension >, Nhs >, Ngp > iImplHalfSpinor
Options::template PrecisionMapper< Simd >::LowerPrecVector SimdL
Lattice< SiteDoubledGaugeField > DoubledGaugeField
iImplHalfCommSpinor< SimdL > SiteHalfCommSpinor
iImplPropagator< Simd > SitePropagator
iVector< iVector< iVector< vtype, Dimension >, Nhcs >, Ngp > iImplHalfCommSpinor
WilsonCompressor< SiteHalfCommSpinor, SiteHalfSpinor, SiteSpinor > Compressor
static accelerator_inline void multLink(_Spinor &phi, const SiteDoubledGaugeField &U, const _Spinor &chi, int mu, StencilEntry *SE, StencilView &St)
INHERIT_GIMPL_TYPES(Gimpl)
GparityWilsonImplParams ImplParams
GparityWilsonImpl(const ImplParams &p=ImplParams())
iImplSpinor< Simd > SiteSpinor
void multLinkField(_SpinorField &out, const DoubledGaugeField &Umu, const _SpinorField &phi, int mu)
static accelerator_inline void loadLinkElement(Simd &reg, ref &memory)
const Coordinate & GlobalDimensions(void)
Coordinate _fdimensions
GridBase * Grid(void) const
uint8_t _around_the_world
Definition Stencil.h:94