Calculate fermion expectation values via a noisy estimator.
Matrix inversion via conjugate gradient algorithm Solves \(MX=X_1\) (Numerical Recipes section 2.10 pp.70-73)
uses NEW lookup tables ** Implemented in Congradp()
11 {
12 const char funcname[] = "Measure";
13
14
15#ifdef USE_GPU
16 int device=-1;
17 cudaGetDevice(&device);
19#ifdef _DEBUG
20 cudaMallocManaged((
void **)&R1,
kferm*
sizeof(
Complex), cudaMemAttachGlobal);
21 cudaMallocManaged((
void **)&R1_f,
kferm*
sizeof(
Complex_f), cudaMemAttachGlobal);
22#else
25#endif
26 cudaMallocManaged((
void **)&x,
kfermHalo*
sizeof(
Complex), cudaMemAttachGlobal);
27 cudaMallocManaged((
void **)&xi,
kferm*
sizeof(
Complex), cudaMemAttachGlobal);
29#else
36#endif
37
41 }
42#ifdef USE_GPU
43#if (nproc>1)
46 }
47#else
48 cudaMemcpyAsync(x, xi,
kferm*
sizeof(
Complex),cudaMemcpyDefault,0);
49#endif
50#else
51#pragma omp parallel for
54 }
55#endif
56
57
58 Dslashd_f(R1_f,xi_f,ut_f,iu,
id,gamval_f,gamin,dk_f,jqq,akappa);
59 if(c_sw){
61 ByClover_f(R1_f,xi_f,clover,sigval_f,akappa,sigin,
true);
62 }
64#ifdef USE_GPU
65 cudaFree(xi_f);
67#ifdef _DEBUG
68 cudaFree(R1_f);
69#else
71#endif
74#else
75 free(xi_f); free(R1_f);
77#endif
79 if(
Congradp(0, res, Phi,R1,ut,ut_f,clover,iu,
id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,c_sw,itercg)==
ITERLIM){
80
81#ifdef USE_GPU
82#ifdef _DEBUG
83 if(c_sw){
84 cudaFree(clover[0]); cudaFree(clover[1]);
85 }
86 cudaFree(R1);
87#else
88 if(c_sw){
89 cudaFreeAsync(clover[0],
streams[1]); cudaFreeAsync(clover[1],
streams[2]);
90 }
92#endif
93 cudaFree(x); cudaFree(xi);
94#else
95 if(c_sw){
96 free(clover[0]); free(clover[1]);
97 }
98 free(x); free(xi); free(R1);
100#endif
101 }
102#ifdef USE_GPU
104#ifdef _DEBUG
105 if(c_sw){
106 cudaFree(clover[0]); cudaFree(clover[1]);
107 }
108 cudaFree(R1);
109#else
110 if(c_sw){
111 cudaFreeAsync(clover[0],
streams[1]); cudaFreeAsync(clover[1],
streams[2]);
112 }
115#endif
117#else
119 if(c_sw){
120 free(clover[0]); free(clover[1]);
121 }
122 free(R1);
123#endif
124 *pbp = 0;
125#ifdef USE_BLAS
127#ifdef USE_GPU
128#if(nproc>1)
129 for(
unsigned short j=0;j<
ngorkov*
nc;j++){
130 buff=0;
133 }
134#else
135 cublasZdotc(
cublas_handle,
kferm,(cuDoubleComplex *)x,1,(cuDoubleComplex *)xi,1,(cuDoubleComplex *)&buff);
137#endif
139#elif defined USE_BLAS
140 for(
unsigned short j=0;j<
ngorkov*
nc;j++){
141 buff=0;
144 }
145#endif
146#else
147#pragma unroll
148 for(
int i=0;i<
kferm;i++)
150#endif
151#if(nproc>1)
153#endif
155
156 *qbqb=*qq=0;
157#if defined USE_BLAS
158 for(
int idirac = 0; idirac<
ndirac; idirac++){
159 int igork=idirac+4;
160
161#pragma unroll
162 for(
int ic = 0; ic<
nc; ic++){
164
165
166
167#ifdef USE_GPU
169#else
171#endif
172 *qbqb+=gamval[4*
ndirac+idirac]*dot;
173#ifdef USE_GPU
175#else
177#endif
178 *qq-=gamval[4*
ndirac+idirac]*dot;
179 }
180 }
181#else
182
183#pragma omp parallel for simd collapse(2) aligned(x,xi:AVX) reduction(+:*qq,*qbqb)
184 for(
int idirac = 0; idirac<
ndirac; idirac++)
185 for(
int i=0; i<
kvol; i++){
186 int igork=idirac+4;
191 }
192#endif
193
194
195#if(nproc>1)
197#endif
198 *qq=(*qq+*qbqb)/(2*
gvol);
200 xu=xd=xuu=xdd=0;
201
202
203#if(npt>1)
205#endif
206
207
208
209
210
211
212
213
214
215 for(unsigned short igorkov=0; igorkov<4; igorkov++){
216 const unsigned short igork1=gamin[3*
ndirac+igorkov];
217
218#pragma omp parallel for simd aligned(dk,x,xi:AVX) reduction(+:xu)
219 for(
unsigned int i = 0; i<
kvol; i++){
220 unsigned int did=
id[3*
kvol+i];
225 conj(ut[0][did+
kvol*3])*(xi[i+
kvol*(igork1)*
nc+1]-xi[i+
kvol*(igorkov)*
nc+1])+\
227 }
228 }
229 for(unsigned short igorkov=0; igorkov<4; igorkov++){
230 const unsigned short igork1=gamin[3*
ndirac+igorkov];
231#pragma omp parallel for simd aligned(dk,x,xi:AVX) reduction(+:xd)
232 for(
unsigned int i = 0; i<
kvol; i++){
233 unsigned int uid=iu[3*
kvol+i];
240 }
241 }
242 for(unsigned short igorkovPP=4; igorkovPP<8; igorkovPP++){
243 const unsigned short igork1PP=4+gamin[3*
ndirac+igorkovPP-4];
244#pragma omp parallel for simd aligned(dk,x,xi:AVX) reduction(+:xuu)
245 for(
unsigned int i = 0; i<
kvol; i++){
246 unsigned int did=
id[3*
kvol+i];
249 ut[1][did+
kvol*3]*(xi[i+
kvol*(igork1PP*
nc+1)]-xi[i+
kvol*(igorkovPP*
nc+1)]) )+\
251 conj(ut[0][did+
kvol*3])*(xi[i+
kvol*(igork1PP)*
nc+1]-xi[i+
kvol*(igorkovPP)*
nc+1])+\
253 }
254 }
255 for(unsigned short igorkovPP=4; igorkovPP<8; igorkovPP++){
256 const unsigned short igork1PP=4+gamin[3*
ndirac+igorkovPP-4];
257#pragma omp parallel for simd aligned(dk,x,xi:AVX) reduction(+:xdd)
258 for(
unsigned int i = 0; i<
kvol; i++){
259 unsigned int uid=iu[3*
kvol+i];
261 conj(ut[0][i+
kvol*3])*(xi[i+
kvol*(igork1PP*
nc)]+xi[i+
kvol*(igorkovPP*
nc)])-\
262 ut[1][i+
kvol*3]*(xi[i+
kvol*(igork1PP*
nc+1)]+xi[i+
kvol*(igorkovPP*
nc+1)]) )+\
265 conj(ut[1][i+
kvol*3])*(xi[i+
kvol*(igorkovPP*
nc)]+xi[i+
kvol*(igork1PP*
nc)]) ) );
266 }
267 }
268 *endenf=
creal(xu-xd-xuu+xdd);
269 *denf=
creal(xu+xd+xuu+xdd);
270
271#if(nproc>1)
273#endif
275
276#ifdef USE_GPU
277 cudaFree(x); cudaFree(xi);
278
279
280
281
282
283#else
284 free(x); free(xi);
285#endif
286 return 0;
287}
#define ITERLIM
Exceeded max number of iterations.
void ByClover_f(Complex_f *phi, Complex_f *r, Complex_f *clover[2], Complex_f *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 Clover(Complex_f *clover[2], Complex_f *ut[2], unsigned int *iu, unsigned int *id)
Calculates the clovers in all directions at all sites.
int Dslashd_f(Complex_f *phi, Complex_f *r, Complex_f *ut[nc], unsigned int *iu, unsigned int *id, Complex_f gamval[20], const unsigned short gamin[16], float *dk[nc], Complex_f jqq, float akappa)
Evaluates in single precision.
int ComplexConvert(Complex_f *a, Complex *b, const unsigned int len, const bool dtof, const unsigned short stride)
takes an array of complex float and double precision numbers and converts the precision
__device__ __forceinline__ T conj(const T &z)
Complex Conjugation.
int Congradp(int na, double res, Complex *Phi, Complex *xi, Complex *ud[2], Complex_f *ut[2], Complex_f *clover_f[nc], unsigned int *iu, unsigned int *id, Complex gamval[20], Complex_f gamval_f[20], const unsigned short gamin[16], Complex *sigval, Complex_f *sigval_f, unsigned short *sigin, double *dk[2], float *dk_f[2], Complex_f jqq, float akappa, float c_sw, int *itercg)
Matrix Inversion via Conjugate Gradient (no up/down flavour partitioning). Solves The matrix multipl...
int ZHalo_swap_dir(Complex *z, int ncpt, int idir, int layer)
Swaps the halos along the axis given by idir in the direction given by layer.
int Par_dsum(double *dval)
Performs a reduction on a double dval to get a sum which is then distributed to all ranks.
int Gauss_c(Complex_f *ps, unsigned int n, const Complex_f mu, const float sigma)
Generates a vector of normally distributed random single precision complex numbers using the Box-Mull...
#define UP
Flag for send up.
#define DOWN
Flag for send down.
#define AVX
Alignment of arrays. 64 for AVX-512, 32 for AVX/AVX2. 16 for SSE. Since AVX is standard on modern x86...
#define ngorkov
Gor'kov indices.
#define kvol
Sublattice volume.
#define Complex
Double precision complex number.
#define kferm
sublattice size including Gor'kov indices
#define ndirac
Dirac indices.
#define cudaDeviceSynchronise()
Get rid of that bastardised yankee English.
#define gvol
Lattice volume.
cublasHandle_t cublas_handle
Handle for cuBLAS.
#define Complex_f
Single precision complex number.
#define kvolHalo
Subvolume + halo size.
#define kfermHalo
Gor'kov lattice and halo.
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.