29 a[0] = T(-a[1].imag(), -a[1].real());
30 a[1] = T( tmp.imag(), tmp.real());
39 a[0] = T(-a[0].imag(), a[0].real());
40 a[1] = T(-a[1].imag(), a[1].real());
61 a[0] = T(-a[1].imag(), a[1].real());
62 a[1] = T(-tmp.imag(), tmp.real());
70 a[0] = T(-a[0].imag(), a[0].real());
71 a[1] = T( a[1].imag(), -a[1].real());
91 __device__
void Half_Leaf(complex<T> Leaves[
nc], complex<T> *u11t, complex<T> *u12t, complex<T> a[
nc],
unsigned int *iu,\
92 unsigned int *
id,
const unsigned int i,
const unsigned short mu,
const unsigned short nu,
const unsigned short leaf){
94 unsigned int ind;
unsigned int double_ind=
id[nu*
kvol+ind];
110 double_ind=iu[nu*
kvol+ind];
113 Leaves[1]=-a[0]*u12t[double_ind+
kvolHalo*mu]+a[1]*u11t[double_ind+
kvolHalo*mu];
132 double_ind=
id[nu*
kvol+ind];
136 Leaves[1]=-a[0]*u12t[double_ind+
kvolHalo*nu]+a[1]*u11t[double_ind+
kvolHalo*nu];
152 template <
typename T>
153 __device__
void Leaf(complex<T> *u11t, complex<T> *u12t, complex<T> Leaves[
nc],\
154 unsigned int *iu,
unsigned int *
id,
unsigned int i,
const unsigned short mu,\
155 const unsigned short nu,
const unsigned short leaf){
157 Half_Leaf(Leaves,u11t,u12t,a,iu,
id,i,mu,nu,leaf);
158 unsigned int ind,double_ind;
188 double_ind=iu[mu*
kvol+ind];
201 double_ind=
id[mu*
kvol+ind];
223 template <
typename T>
224 __device__
void cuGLeft(T out[4],
const T G[2],
const T X[4]){
225 out[0]=G[0]*X[0]+G[1]*X[2];
226 out[1]=G[0]*X[1]+G[1]*X[3];
227 out[2]=-
conj(G[1])*X[0]+
conj(G[0])*X[2];
228 out[3]=-
conj(G[1])*X[1]+
conj(G[0])*X[3];
239 template <
typename T>
240 __device__
void cuGRight(T out[4],
const T G[2],
const T X[4]){
241 out[0]=G[0]*X[0]-
conj(G[1])*X[1];
242 out[1]=G[1]*X[0]+
conj(G[0])*X[1];
243 out[2]=G[0]*X[2]-
conj(G[1])*X[3];
244 out[3]=G[1]*X[2]+
conj(G[0])*X[3];
256 template <
typename T>
257 __device__
void cuGSandwich(T out[4],T tmp[4],
const T Gl[2],
const T X[4],
const T Gr[2]){
274 Z[1]=Xmn.
offd[ind]; Z[2]=
conj(Z[1]);
281 using namespace Device;
293 template <
typename T>
294 __global__
void Half_Leaves(complex<T> *hLeaves0,complex<T> *hLeaves1,complex<T> *u11t,complex<T> *u12t,\
295 unsigned int *iu,
unsigned int *
id,
const unsigned short mu,
const unsigned short nu){
296 const volatile int gsize = gridDim.x*gridDim.y*gridDim.z;
297 const volatile int bsize = blockDim.x*blockDim.y*blockDim.z;
298 const volatile int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
299 const volatile int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
300 const volatile int gthreadId= blockId * bsize+bthreadId;
302 complex<T> Leaves[
nc], a[
nc];
303 for(
unsigned short leaf=0;leaf<
ndim;leaf++)
304 for(
unsigned int i=gthreadId;i<
kvol;i+=gsize*bsize){
305 Half_Leaf(Leaves,u11t,u12t,a,iu,
id,i,mu,nu,leaf);
306 hLeaves0[i+
kvol*leaf]=Leaves[0]; hLeaves1[i+
kvol*leaf]=Leaves[1];
322 template <
typename T>
323 __global__
void Full_Clover(complex<T> *clover1, complex<T> *clover2,\
324 complex<T> *u11t, complex<T> *u12t,
unsigned int *iu,
unsigned int *
id,
int mu,
int nu){
325 const volatile int gsize = gridDim.x*gridDim.y*gridDim.z;
326 const volatile int bsize = blockDim.x*blockDim.y*blockDim.z;
327 const volatile int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
328 const volatile int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
329 const volatile int gthreadId= blockId * bsize+bthreadId;
331 complex<T> Leaves[2];
332 for(
unsigned int i=gthreadId;i<
kvol;i+=gsize*bsize){
333 clover1[i]=0;clover2[i]=0;
334 for(
unsigned short leaf=0;leaf<
ndim;leaf++)
337 Leaf(u11t,u12t,Leaves,iu,
id,i,mu,nu,leaf);
338 clover1[i]+=Leaves[0]; clover2[i]+=Leaves[1];
346 clover1[i]=clover1[i].imag(); clover1[i]*=(1.0f/4.0f);
350 clover2[i]+=clover2[i]; clover2[i]*=(-
I_f/8.0f);
368 template <
typename T>
370 const complex<T> *sigval,
const unsigned short *sigin,
const unsigned short clov){
371 const char funcname[] =
"Xmunu";
372 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
373 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
374 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
375 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
376 const unsigned int gthreadId= blockId * bsize+bthreadId;
378 for(
unsigned int i=gthreadId;i<
kvol;i+=gsize*bsize){
382 for(
unsigned short idirac=0; idirac<
ndirac*
nc; idirac+=
nc){
383 const unsigned short sind = sigin[clov*
ndirac+(idirac>>1)]<<1;
384 const complex<T> sig = sigval[clov*
ndirac+(idirac>>1)];
385 for(
unsigned short c1=0;c1<
nc;c1++){
387 const complex<T> X1s = X1[i+
kvolHalo*(sind+c1)];
388 const complex<T> X2s = X2[i+
kvolHalo*(sind+c1)];
389 for(
unsigned short c2=0;c2<
nc;c2++){
394 const complex<T> X1c =
conj(X1[i+
kvolHalo*(idirac+c2)]);
395 const complex<T> X2c =
conj(X2[i+
kvolHalo*(idirac+c2)]);
397 Xmn.
diag[c1]+=(T)(sig*(X2s*X1c+X1s*X2c)).real();
399 Xmn.
offd+=sig*(X2s*X1c+X1s*X2c);
404 for(
unsigned short c=0;c<
nc;c++)
426 template <
typename T>
428 const complex<T> *sigval,
const unsigned short *sigin,
const unsigned int *iu,\
429 const unsigned int *
id,
const float akappa,
const unsigned short mu,
const unsigned short nu){
430 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
431 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
432 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
433 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
434 const unsigned int gthreadId= blockId * bsize+bthreadId;
437 for(
unsigned int i=gthreadId;i<
kvol;i+=gsize*bsize){
442 complex<T> W0[2]; complex<T> W1[2]; complex<T> W6[2];
445 unsigned int ind =
id[i+
kvol*nu];
457 complex<T> Zbuff1[
nc*
nc];complex<T> Zbuff2[
nc*
nc];
461 W6[0]=W0[0]*W1[0]-W0[1]*
conj(W1[1]); W6[1]=W0[0]*W1[1]+W0[1]*
conj(W1[0]);
471 for(
unsigned short c=0;c<
nc*
nc;c++)
472 Zbuff1[c]+=Zbuff2[c];
482 for(
unsigned short c=0;c<
nc*
nc;c++)
501 W7[0]=W0[0]*W1[0]-W0[1]*
conj(W1[1]); W7[1]=W0[0]*W1[1]+W0[1]*
conj(W1[0]);
509 for(
unsigned short c=0;c<
nc*
nc;c++)
510 Zbuff1[c]+=Zbuff2[c];
519 for(
unsigned short c=0;c<
nc*
nc;c++)
522 W0[0]=W7[0]*W4[0]-W7[1]*
conj(W4[1]); W0[1]=W7[0]*W4[1]+W7[1]*
conj(W4[0]);
523 W1[0]=W5[0]*W6[0]-W5[1]*
conj(W6[1]); W1[1]=W5[0]*W6[1]+W5[1]*
conj(W6[0]);
525 W0[0]-=W1[0]; W0[1]-=W1[1];
532 for(
unsigned short c=0;c<
nc*
nc;c++)
541 for(
unsigned short c=0;c<
nc*
nc;c++){
548 for(
unsigned short gen=0;gen<
nadj;gen++){
549 W1[0]=W0[0]; W1[1]=W0[1];
553 float dSdpis=
creal(Zbuff1[0])+
creal(Zbuff1[3]);
556 dSdpi[i+
kvol*(gen*
ndim+mu)] -=akappa*dSdpis/4.0f;
558 dSdpi[i+
kvol*(gen*
ndim+mu)] +=akappa*dSdpis/4.0f;
580 template <
typename T>
581 __global__
void ByClover(complex<T> *phi, complex<T> *r, complex<T> *clover1, complex<T> *clover2, complex<T> *sigval,
const float akappa,
unsigned short *sigin,
bool dag){
582 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
583 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
584 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
585 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
586 const unsigned int gthreadId= blockId * bsize+bthreadId;
588 for(
unsigned int i=gthreadId;i<
kvol;i+=bsize*gsize){
592 for(
unsigned short igorkov=0; igorkov<
ngorkov; igorkov++)
593 for(
unsigned short c=0; c<
nc; c++){
597 complex<T> clov_s[
nc];
599 for(
unsigned short clov=0;clov<6;clov++){
600 clov_s[0]=clover1[clov*
kvol+i]; clov_s[1]=clover2[clov*
kvol+i];
601 for(
unsigned short igorkov=0; igorkov<
ngorkov; igorkov++){
603 const unsigned short idirac = igorkov&3;
604 const unsigned short sind = (igorkov<4) ? sigin[clov*
ndirac+idirac] : sigin[clov*
ndirac+idirac]+4;
606 for(
unsigned short c=0; c<
nc; c++)
609 phi_s[igorkov][0]+=sigval[clov*
ndirac+idirac]*(
creal(clov_s[0])*r_s[0]+clov_s[1]*r_s[1]);
611 phi_s[igorkov][1]+=sigval[clov*
ndirac+idirac]*(
conj(clov_s[1])*r_s[0]-
creal(clov_s[0])*r_s[1]);
615 for(
unsigned short igorkov=0; igorkov<
ngorkov; igorkov++)
616 for(
unsigned short c=0; c<
nc; c++){
621 phi[i+
kvol*(
nc*igorkov+c)]+=akappa*phi_s[igorkov][c];
623 phi[i+
kvolHalo*(
nc*igorkov+c)]+=akappa*phi_s[igorkov][c];
643 template <
typename T>
644 __global__
void HbyClover(complex<T> *phi, complex<T> *r, complex<T> *clover1, complex<T> *clover2,complex<T> *sigval,
const float akappa,
unsigned short *sigin,
bool dag){
645 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
646 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
647 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
648 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
649 const unsigned int gthreadId= blockId * bsize+bthreadId;
651 for(
unsigned int i=gthreadId;i<
kvol;i+=bsize*gsize){
655 for(
unsigned short idirac=0; idirac<
ndirac*
nc; idirac+=
nc)
656 for(
unsigned short c=0; c<
nc; c++){
659 complex<T> r_s[
nc]; complex<T> clov_s[
nc];
661 for(
unsigned short clov=0;clov<6;clov++){
662 clov_s[0]=clover1[clov*
kvol+i]; clov_s[1]=clover2[clov*
kvol+i];
663 for(
unsigned short idirac=0; idirac<
ndirac*
nc; idirac+=
nc){
664 const unsigned short sind = sigin[clov*
ndirac+(idirac>>1)] << (
nc-1);
666 for(
unsigned short c=0; c<
nc; c++){
670 const complex<T> sig=sigval[clov*
ndirac+(idirac>>1)];
671 phi_s[idirac+0]+=sig*(
creal(clov_s[0])*r_s[0]+clov_s[1]*r_s[1]);
673 phi_s[idirac+1]+=sig*(
conj(clov_s[1])*r_s[0]-
creal(clov_s[0])*r_s[1]);
677 for(
unsigned short idirac=0; idirac<
ndirac*
nc; idirac+=
nc)
678 for(
unsigned short c=0; c<
nc; c++)
683 phi[i+
kvol*(c+idirac)]+=akappa*phi_s[idirac+c];
685 phi[i+
kvolHalo*(c+idirac)]+=akappa*phi_s[idirac+c];
695 const char funcname[]=
"cuClover";
697 cudaMallocManaged((
void **)&clover[0],6*
kvol*
sizeof(
Complex_f),cudaMemAttachGlobal);
698 cudaMallocManaged((
void **)&clover[1],6*
kvol*
sizeof(
Complex_f),cudaMemAttachGlobal);
703 for(
unsigned short mu=0;mu<
ndim-1;mu++)
704 for(
unsigned short nu=mu+1;nu<
ndim;nu++)
707 unsigned short clov = (mu==0) ? nu-1 :mu+nu;
711 ut[0],ut[1],iu,id,mu,nu);
730 const unsigned short mu,
const unsigned short nu){
732 unsigned short clov = (mu==0) ? nu-1 : mu+nu;
737 const unsigned short *sigin,
const unsigned int *iu,
const unsigned int *
id,
const float akappa){
738 const char funcname[]=
"Clov_Force";
740 const unsigned short nclov = (
ndim-1)*(
ndim-2);
744 for(
unsigned short mu=0;mu<
ndim-1;mu++)
745 for(
unsigned short nu=mu;nu<
ndim;nu++)
748 unsigned short clov = (mu==0) ? nu-1 : mu+nu;
750 cudaMallocAsync((
void **)&Xmn[clov].diag,
nc*
kvol*
sizeof(
float),
streams[clov]);
751 cudaMallocAsync((
void **)&Xmn[clov].offd,
nc*
kvol*
sizeof(complex<float>),
streams[clov]);
756 for(
unsigned short mu=0;mu<
ndim;mu++)
757 for(
unsigned short nu=0;nu<
ndim;nu++)
759 unsigned short clov=0;
761 clov = (mu==0) ? nu-1 : mu+nu;
763 clov = (nu==0) ? mu-1 : mu+nu;
766 sigval,sigin,iu,id,akappa,mu,nu);
770 for(
unsigned short clov=0;clov<nclov;clov++){
771 cudaFreeAsync(Xmn[clov].diag,NULL); cudaFreeAsync(Xmn[clov].offd,NULL);
Routines needed for Clover improved wilson fermions.
__device__ void GetBilinear(Complex_f Z[nc *nc], Bilinear_a Xmn, unsigned int ind)
Loads the compacted bilinear form into a complex valued matrix.
__global__ void Clov_Force(double *dSdpi, const complex< T > *u11t, const complex< T > *u12t, Bilinear_a Xmn, const complex< T > *sigval, const unsigned short *sigin, const unsigned int *iu, const unsigned int *id, const float akappa, const unsigned short mu, const unsigned short nu)
cuGets the clover contribution to the force
__device__ void cuByGenLeft(T a[nc], const unsigned short gen)
Multiply leaf (or part of one) by generator from left.
__device__ void cuByGenRight(T a[nc], const unsigned short gen)
Multiply leaf (or part of one) by generator from right.
__device__ void cuGSandwich(T out[4], T tmp[4], const T Gl[2], const T X[4], const T Gr[2])
Multiplies by a gauge field from the left and the right.
int cuClov_Force(double *dSdpi, Complex_f *ut[nc], Complex_f *X1, Complex_f *X2, const Complex_f *sigval, const unsigned short *sigin, const unsigned int *iu, const unsigned int *id, const float akappa)
CUDA wrapper for Clover_Force.
__device__ void cuGLeft(T out[4], const T G[2], const T X[4])
Multiplies by a gauge field from the left.
__device__ void cuGRight(T out[4], const T G[2], const T X[4])
Multiplies by a gauge field from the right.
__global__ void cuCalcXmunu(Bilinear_a Xmunu, const complex< T > *X1, const complex< T > *X2, const complex< T > *sigval, const unsigned short *sigin, const unsigned short clov)
Gets for the clover force.
void cuHbyClover(Complex *phi, Complex *r, Complex *clover[nc], Complex *sigval, const float akappa, unsigned short *sigin, bool dag)
CUDA wrapper for HbyClover.
void cuByClover_f(Complex_f *phi, Complex_f *r, Complex_f *clover[nc], Complex_f *sigval, const float akappa, unsigned short *sigin, bool dag)
CUDA wrapper for ByClover_f.
__global__ void ByClover(complex< T > *phi, complex< T > *r, complex< T > *clover1, complex< T > *clover2, complex< T > *sigval, const float akappa, unsigned short *sigin, bool dag)
Clover analogue of the Dslash operation. This version acts on all flavours similar to Dslash and Dsla...
void cuHbyClover_f(Complex_f *phi, Complex_f *r, Complex_f *clover[nc], Complex_f *sigval, const float akappa, unsigned short *sigin, bool dag)
CUDA wrapper for HbyClover_f.
void cuByClover(Complex *phi, Complex *r, Complex *clover[nc], Complex *sigval, const float akappa, unsigned short *sigin, bool dag)
CUDA wrapper for ByClover.
__global__ void HbyClover(complex< T > *phi, complex< T > *r, complex< T > *clover1, complex< T > *clover2, complex< T > *sigval, const float akappa, unsigned short *sigin, bool dag)
Clover analogue of the Hdslash operation. The H in front is for half, as we only act on the fermions ...
int cuClover(Complex_f *clover[nc], Complex_f *ut[nc], unsigned int *iu, unsigned int *id)
CUDA wrapper for calculating the clovers in all directions at all sites .
__device__ void Leaf(complex< T > *u11t, complex< T > *u12t, complex< T > Leaves[nc], unsigned int *iu, unsigned int *id, unsigned int i, const unsigned short mu, const unsigned short nu, const unsigned short leaf)
Calculates a leaf for a clover term.
__global__ void Half_Leaves(complex< T > *hLeaves0, complex< T > *hLeaves1, complex< T > *u11t, complex< T > *u12t, unsigned int *iu, unsigned int *id, const unsigned short mu, const unsigned short nu)
Calculates the products of the first two links in a plaquette.
__global__ void Full_Clover(complex< T > *clover1, complex< T > *clover2, complex< T > *u11t, complex< T > *u12t, unsigned int *iu, unsigned int *id, int mu, int nu)
Calculates the clovers in all directions at all sites .
__device__ void Half_Leaf(complex< T > Leaves[nc], complex< T > *u11t, complex< T > *u12t, complex< T > a[nc], unsigned int *iu, unsigned int *id, const unsigned int i, const unsigned short mu, const unsigned short nu, const unsigned short leaf)
Calculates the first half of the leaf for a clover term. We split it so that the force term can reuse...
__device__ __forceinline__ T conj(const T &z)
Complex Conjugation.
#define ngorkov
Gor'kov indices.
#define nadj
adjacent spatial indices
#define kvol
Sublattice volume.
#define Complex
Double precision complex number.
#define ndirac
Dirac indices.
#define cudaDeviceSynchronise()
Get rid of that bastardised yankee English.
#define Complex_f
Single precision complex number.
#define kvolHalo
Subvolume + halo size.
Structure of arrays for Hermitian bilinear in memory.
Complex_f * offd
Complex valued off-diagonal terms. We only need to store one of these to get the other in .
float * diag
Real valued diagonal terms.
Hermitian bilinear on the local stack.
float diag[2]
Real valued diagonal terms.
Complex_f offd
Complex valued off-diagonal terms. We only need to store one of these to get the other in .
cudaStream_t streams[ndirac *ndim *nadj]
An array of concurrent GPU streams to keep it busy.
#define creal(z)
Extract Real Component using C standard notation.
#define I_f
Define I in single precision.