su2hmc
Loading...
Searching...
No Matches
/github/workspace/main.c
Go to the documentation of this file.
1
42#include <assert.h>
43#include <clover.h>
44#include <matrices.h>
45#ifdef USE_GPU
46#include <cuda_runtime.h>
47cublasHandle_t cublas_handle;
48cublasStatus_t cublas_status;
49cudaMemPool_t mempool;
50//Fix this later
51#endif
71int main(int argc, char *argv[]){
72 //Instead of hard coding the function name so the error messages are easier to implement
73 const char funcname[] = "main";
74
75 Par_begin(argc, argv);
76 //Add error catching code...
77#if(nproc>1)
78 MPI_Comm_rank(comm, &rank);
79 MPI_Comm_size(comm, &size);
80#endif
81
105 float beta = 1.7f;
106 float akappa = 0.1780f;
107#ifdef USE_GPU
108 __managed__
109#endif
110 Complex_f jqq = 0;
111 float fmu = 0.0f; int iread = 0; int istart = 1;
112 int iprint = 1; //How often are measurements made
113 int icheck = 5; //How often are configurations saved
114 int ibound = -1;
115
116 float dt=0.004; float c_sw = 0.0; float delb=0; //Not used?
117 float ajq = 0.0; int stepl = 250; int ntraj = 10;
118 //rank is zero means it must be the "master process"
119 if(!rank){
120 FILE *midout;
121 const char *filename = (argc!=2) ?"midout":argv[1];
122 char *fileop = "r";
123 if( !(midout = fopen(filename, fileop) ) ){
124 fprintf(stderr, "Error %i in %s: Failed to open file %s for %s.\nExiting\n\n",\
125 OPENERROR, funcname, filename, fileop);
126#if(nproc>1)
127 MPI_Abort(comm,OPENERROR);
128#else
129 exit(OPENERROR);
130#endif
131 }
132 //See the README for what each entry means
133 fscanf(midout, "%f %f %f %f %f %f %f %d %d %d %d %d", &dt, &beta, &akappa,\
134 &ajq, &c_sw, &fmu, &delb, &stepl, &ntraj, &istart, &icheck, &iread);
135 fclose(midout);
136 assert(stepl>0); assert(ntraj>0); assert(istart>=0); assert(icheck>0); assert(iread>=0);
137 }
138 //Send inputs to other ranks
139#if(nproc>1)
140 if(c_sw!=0){
141 fprintf(stderr,"Error %i in %s: Multiple MPI Ranks are not currently supported for the clover action.\n"\
142 "This is due to the corner halo terms needed to compute the clover force not being implemented.\n"\
143 "Please recompile for a single MPI rank or run with c_sw=0.\n"\
144 "\nExiting...\n\n",NOIMPL,funcname);
145 MPI_Abort(comm,NOIMPL);
146 exit(NOIMPL);
147 }
148 Par_fcopy(&dt); Par_fcopy(&beta); Par_fcopy(&akappa); Par_fcopy(&ajq);
149 Par_fcopy(&c_sw); Par_fcopy(&fmu); Par_fcopy(&delb); //Not used?
150 Par_icopy(&stepl); Par_icopy(&ntraj); Par_icopy(&istart); Par_icopy(&icheck);
151 Par_icopy(&iread);
152#endif
153 // Thetaq was never used so depreciated. It's position in midout is now c_sw
154 // jqq=ajq*cexp(athq*I);
155 jqq=ajq;
156 //End of input
157#ifdef USE_GPU
158 //CUBLAS Handle
159 cublasCreate(&cublas_handle);
160 //Set up grid and blocks
162 //CUDA device
163 int device=-1;
164 cudaGetDevice(&device);
165 //For asynchronous memory, when CUDA syncs any unused memory in the pool is released back to the OS
166 //unless a threshold is given. We'll base our threshold off of Congradp
167 //12*kvol for the clover and 4*16*kvolHalo for the fermion fields
168 //Factor of 1.5 because we need it in single and double precsion should be plenty without being excessive.
169 //Not everything has a halo so larger halos give us more headroom too.
170 cudaDeviceGetDefaultMemPool(&mempool, device);
171 int threshold=8*kfermHalo*sizeof(Complex);
172 cudaMemPoolSetAttribute(mempool, cudaMemPoolAttrReleaseThreshold, &threshold);
173#endif
174#ifdef _DEBUG
175 printf("jqq=%f+(%f)I\n",creal(jqq),cimag(jqq));
176#endif
177#ifdef _DEBUG
178 seed = 967580161;
179#else
180 seed = time(NULL);
181#endif
182
183 //Gauge, trial and momentum fields
184 //You'll notice that there are two different allocation/free statements
185 //One for CUDA and one for everything else depending on what's
186 //being used
187 /*** Let's take a quick moment to compare this to the analysis code.
188 * The analysis code stores the gauge field as a 4 component real valued vector, whereas the produciton code
189 * used two complex numbers.
190 *
191 * Analysis code: u=(Re(u[0]),Im(u[1]),Re(u[1]),Im(u[0]))
192 * Production code: u[0]=u[0]+I*u[3] u[1]=u[2]+I*u[1]
193 *
194 */
195 Complex *u[2], *ut[2];
196 Complex_f *ut_f[2];
197 double *dk[2], *pp;
198 float *dk_f[2];
199 //Halo index arrays
200 unsigned int *iu, *id;
201 //And clover arrays. These only get assigned if @f$c_\text{SW}>0@f$
202 Complex *sigval; Complex_f *sigval_f; unsigned short *sigin;
203#ifdef USE_GPU
204 //Managed here because it's easier to fill them on CPU
205 cudaMallocManaged((void**)&iu,ndim*kvol*sizeof(int),cudaMemAttachGlobal);
206 cudaMallocManaged((void**)&id,ndim*kvol*sizeof(int),cudaMemAttachGlobal);
207
208 cudaMallocManaged((void **)&dk[0],(kvolHalo)*sizeof(double),cudaMemAttachGlobal);
209 cudaMallocManaged((void **)&dk[1],(kvolHalo)*sizeof(double),cudaMemAttachGlobal);
210#ifdef _DEBUG
211 cudaMallocManaged((void **)&dk_f[0],(kvolHalo)*sizeof(float),cudaMemAttachGlobal);
212 cudaMallocManaged((void **)&dk_f[1],(kvolHalo)*sizeof(float),cudaMemAttachGlobal);
213#else
214 cudaMalloc((void **)&dk_f[0],(kvolHalo)*sizeof(float));
215 cudaMalloc((void **)&dk_f[1],(kvolHalo)*sizeof(float));
216#endif
217
218 unsigned short *gamin; Complex *gamval; Complex_f *gamval_f;
219 cudaMallocManaged((void **)&gamval_f,5*4*sizeof(Complex_f),cudaMemAttachGlobal);
220 cudaMallocManaged((void **)&gamval,5*4*sizeof(Complex),cudaMemAttachGlobal);
221 cudaMallocManaged((void **)&gamin,4*4*sizeof(short),cudaMemAttachGlobal);
222
223 cudaMallocManaged((void **)&u[0],ndim*kvol*sizeof(Complex),cudaMemAttachGlobal);
224 cudaMallocManaged((void **)&u[1],ndim*kvol*sizeof(Complex),cudaMemAttachGlobal);
225 //Needs to be managed as fermionic.c still used them on CPU
226 cudaMallocManaged((void **)&ut[0],ndim*(kvolHalo)*sizeof(Complex),cudaMemAttachGlobal);
227 cudaMallocManaged((void **)&ut[1],ndim*(kvolHalo)*sizeof(Complex),cudaMemAttachGlobal);
228#ifdef _DEBUG
229 cudaMallocManaged((void **)&ut_f[0],ndim*(kvolHalo)*sizeof(Complex_f),cudaMemAttachGlobal);
230 cudaMallocManaged((void **)&ut_f[1],ndim*(kvolHalo)*sizeof(Complex_f),cudaMemAttachGlobal);
231#else
232 cudaMalloc((void **)&ut_f[0],ndim*(kvolHalo)*sizeof(Complex_f));
233 cudaMalloc((void **)&ut_f[1],ndim*(kvolHalo)*sizeof(Complex_f));
234// cudaMalloc((void **)&ut[0],ndim*(kvolHalo)*sizeof(Complex));
235// cudaMalloc((void **)&ut[1],ndim*(kvolHalo)*sizeof(Complex));
236#endif
237#else
238 id = (unsigned int*)aligned_alloc(AVX,ndim*kvol*sizeof(int));
239 iu = (unsigned int*)aligned_alloc(AVX,ndim*kvol*sizeof(int));
240
241 alignas(AVX) unsigned short gamin[16]; alignas(AVX) Complex gamval[20]; alignas(AVX) Complex_f gamval_f[20];
242
243 dk[0] = (double *)aligned_alloc(AVX,(kvolHalo)*sizeof(double));
244 dk[1] = (double *)aligned_alloc(AVX,(kvolHalo)*sizeof(double));
245 dk_f[0] = (float *)aligned_alloc(AVX,(kvolHalo)*sizeof(float));
246 dk_f[1] = (float *)aligned_alloc(AVX,(kvolHalo)*sizeof(float));
247
248 u[0] = (Complex *)aligned_alloc(AVX,ndim*kvol*sizeof(Complex));
249 u[1] = (Complex *)aligned_alloc(AVX,ndim*kvol*sizeof(Complex));
250 ut[0] = (Complex *)aligned_alloc(AVX,ndim*(kvolHalo)*sizeof(Complex));
251 ut[1] = (Complex *)aligned_alloc(AVX,ndim*(kvolHalo)*sizeof(Complex));
252 ut_f[0] = (Complex_f *)aligned_alloc(AVX,ndim*(kvolHalo)*sizeof(Complex_f));
253 ut_f[1] = (Complex_f *)aligned_alloc(AVX,ndim*(kvolHalo)*sizeof(Complex_f));
254#endif
268 Init(istart,ibound,iread,beta,fmu,akappa,ajq,c_sw,u,ut,ut_f,gamval,gamval_f,gamin,dk,dk_f,iu,id);
269 if(c_sw)
270 Init_clover(&sigval,&sigval_f,&sigin,c_sw);
271
273#ifdef USE_GPU
274 //GPU Initialisation stuff
275 Init_CUDA(ut[0],ut[1],gamval,gamval_f,gamin,dk[0],dk[1],iu,id);//&dimBlock,&dimGrid);
276#endif
277 //Send trials to accelerator for reunitarisation
278 Reunitarise(ut);
279 //Get trials back
280#ifdef USE_GPU
281#if(nproc>1) //Memcpy routines need to be strided if there is a halo since the lattice is not contiguous in memory
282 for(unsigned short mu=0;mu<ndim;mu++){
283 cudaMemcpyAsync(u[0]+kvol*mu, ut[0]+kvolHalo*mu, kvol*sizeof(Complex),cudaMemcpyDefault,streams[mu]);
284 cudaMemcpyAsync(u[1]+kvol*mu, ut[1]+kvolHalo*mu, kvol*sizeof(Complex),cudaMemcpyDefault,streams[mu]);
285 }
286#else
287 cudaMemcpyAsync(u[0], ut[0], ndim*kvol*sizeof(Complex),cudaMemcpyDefault,streams[0]);
288 cudaMemcpyAsync(u[1], ut[1], ndim*kvol*sizeof(Complex),cudaMemcpyDefault,streams[1]);
289#endif
290#else
291 for(unsigned short mu=0;mu<ndim;mu++){
292 memcpy(u[0]+kvol*mu, ut[0]+kvolHalo*mu, kvol*sizeof(Complex));
293 memcpy(u[1]+kvol*mu, ut[1]+kvolHalo*mu, kvol*sizeof(Complex));
294 }
295#endif
296#ifdef USE_GPU
298#endif
299#ifdef DIAGNOSTIC
300 double ancg_diag=0;
301 Diagnostics(istart, u, ut, ut_f, iu, id, hu, hd, dk,\
302 dk_f, gamin, gamval, gamval_f, sigval, sigval_f, sigin, jqq, akappa, beta, c_sw,ancg_diag);
303#endif
304
305 //Initial Measurements
306 //====================
307 Trial_Exchange(ut,ut_f);
308 double poly = Polyakov(ut_f);
309#ifdef _DEBUG
310 if(!rank) printf("Initial Polyakov loop evaluated as %e\n", poly);
311#endif
312 double hg, avplaqs, avplaqt;
313 //Halo exchange of the trial fields
314 Average_Plaquette(&hg,&avplaqs,&avplaqt,ut_f,iu,beta);
315 //Trajectory length
316 double traj=stepl*dt;
317 //end trajectory probability
318 double proby = 2.5/stepl;
319 char suffix[FILELEN]="";
320 int buffer; char buff2[7];
321 //Add script for extracting correct mu, j etc.
322 buffer = (int)round(100*beta);
323 sprintf(buff2,"b%03d",buffer);
324 strcat(suffix,buff2);
325 //κ
326 buffer = (int)round(10000*akappa);
327 sprintf(buff2,"k%04d",buffer);
328 strcat(suffix,buff2);
329 //μ
330 buffer = (int)round(1000*fmu);
331 sprintf(buff2,"mu%04d",buffer);
332 strcat(suffix,buff2);
333 //J
334 buffer = (int)round(1000*ajq);
335 sprintf(buff2,"j%03d",buffer);
336 strcat(suffix,buff2);
337 //c_sw
338 if(c_sw){
339 buffer = (int)round(100*c_sw);
340 sprintf(buff2,"c%03d",buffer);
341 strcat(suffix,buff2);
342 }
343 //nx
344 sprintf(buff2,"s%02d",nx);
345 strcat(suffix,buff2);
346 //nt
347 sprintf(buff2,"t%02d",nt);
348 strcat(suffix,buff2);
349 char outname[FILELEN] = "Output."; char *outop="a";
350 strcat(outname,suffix);
351 FILE *output;
352 if(!rank){
353 if(!(output=fopen(outname, outop) )){
354 fprintf(stderr,"Error %i in %s: Failed to open file %s for %s.\nExiting\n\n",OPENERROR,funcname,outname,outop);
355#if(nproc>1)
356 MPI_Abort(comm,OPENERROR);
357#else
358 exit(OPENERROR);
359#endif
360 }
361 printf("hg = %e, <Ps> = %e, <Pt> = %e, <Poly> = %e\n", hg, avplaqs, avplaqt, poly);
362 fprintf(output, "ksize = %i ksizet = %i Nf = %i Halo =%i\nTime step dt = %e Trajectory length = %e\n"\
363 "No. of Trajectories = %i β = %e\nκ = %e μ = %e\nDiquark source = %e Clover coefficient = %e\n"\
364 "Stopping Residuals: Guidance: %e Acceptance: %e, Estimator: %e\nSeed = %ld\n",
365 ksize, ksizet, nf, halo, dt, traj, ntraj, beta, akappa, fmu, ajq, c_sw, rescgg, rescga, respbp, seed);
366#ifdef _DEBUG
367 //Print to terminal during debugging
368 printf("ksize = %i ksizet = %i Nf = %i Halo = %i\nTime step dt = %e Trajectory length = %e\n"\
369 "No. of Trajectories = %i β = %e\nκ = %e μ = %e\nDiquark source = %e Clover coefficient = %e\n"\
370 "Stopping Residuals: Guidance: %e Acceptance: %e, Estimator: %e\nSeed = %ld\n",
371 ksize, ksizet, nf, halo, dt, traj, ntraj, beta, akappa, fmu, ajq, c_sw, rescgg, rescga, respbp, seed);
372#endif
373 }
374 //Initialise for averages
375 //======================
376 double actiona = 0.0; double vel2a = 0.0; double pbpa = 0.0; double endenfa = 0.0; double denfa = 0.0;
377 //Expected canged in Hamiltonian
378 double e_dH=0; double e_dH_e=0;
379 //Expected Metropolis accept probability. Skewed by cases where the hamiltonian decreases.
380 double yav = 0.0; double yyav = 0.0;
381
382 int naccp = 0; int ipbp = 0; int itot = 0;
383
384 //Start of classical evolution
385 //===========================
386 double pbp;
387 Complex qq;
388 double *dSdpi;
389 //Field and related declarations
390 Complex *Phi, *X0, *X1;
391 //Initialise Arrays. Leaving it late for scoping
392 //check the sizes in sizes.h
393#ifdef USE_GPU
394#ifdef _DEBUG
395 cudaMallocManaged((void **)&X0, nf*kferm2*sizeof(Complex),cudaMemAttachGlobal);
396 cudaMallocManaged((void **)&Phi, nf*kferm*sizeof(Complex),cudaMemAttachGlobal);
397 cudaMallocManaged((void **)&dSdpi, kmom*sizeof(double),cudaMemAttachGlobal);
398 cudaMallocManaged((void **)&X1, kferm2Halo*sizeof(Complex),cudaMemAttachGlobal);
399#else
400 cudaMalloc((void **)&X1, kferm2Halo*sizeof(Complex));
401 cudaMalloc((void **)&X0, nf*kferm2*sizeof(Complex));
402 cudaMalloc((void **)&Phi, nf*kferm*sizeof(Complex));
403 cudaMalloc((void **)&dSdpi, kmom*sizeof(double));
404#endif
405
406 cudaMallocManaged((void **)&pp, kmom*sizeof(double),cudaMemAttachGlobal);
408#else
409 Phi= aligned_alloc(AVX,nf*kferm*sizeof(Complex));
410 X0= aligned_alloc(AVX,nf*kferm2*sizeof(Complex));
411 X1= aligned_alloc(AVX,kferm2Halo*sizeof(Complex));
412 dSdpi = aligned_alloc(AVX,kmom*sizeof(double));
413 //pp is the momentum field
414 pp = aligned_alloc(AVX,kmom*sizeof(double));
415#endif
421#if (defined SA3AT)
422 double start_time=0;
423 if(!rank){
424#if(nproc>1)
425 start_time = MPI_Wtime();
426#else
427 start_time = omp_get_wtime();
428#endif
429 }
430#endif
431 double action;
432 //Conjugate Gradient iteration counters
433 double ancg,ancgh,totancg,totancgh;
434 ancg=ancgh=totancg=totancgh=0;
435 for(int itraj = iread+1; itraj <= ntraj+iread; itraj++){
436 //Reset conjugate gradient averages
437 ancg = 0; ancgh = 0;
438#ifdef _DEBUG
439 if(!rank)
440 printf("Starting itraj %i\n", itraj);
441#endif
442 Complex_f *clover[2];
443 if(c_sw)
444 Clover(clover,ut_f,iu,id);
445 for(int na=0; na<nf; na++){
446 //Probably makes sense to declare this outside the loop
447 //but I do like scoping/don't want to break anything else just teat
448 //
449 //How do we optimise this for use in CUDA? Do we use CUDA's PRNG
450 //or stick with MKL and synchronise/copy over the array
451#ifdef USE_GPU
452 Complex_f *R1_f,*R; Complex *R1;
453 cudaMallocManaged((void **)&R,kfermHalo*sizeof(Complex_f),cudaMemAttachGlobal);
454#ifdef _DEBUG
455 cudaMallocManaged((void **)&R1, kferm*sizeof(Complex),cudaMemAttachGlobal);
456 cudaMallocManaged((void **)&R1_f,kferm*sizeof(Complex_f),cudaMemAttachGlobal);
457 cudaMemset(R1_f,0,kferm*sizeof(Complex_f));
458#else
459 cudaMallocAsync((void **)&R1, kferm*sizeof(Complex),streams[1]);
460 cudaMallocAsync((void **)&R1_f,kferm*sizeof(Complex_f),streams[0]);
461 cudaMemsetAsync(R1_f,0,kferm*sizeof(Complex_f),streams[0]);
462#endif
463#else
464 Complex_f *R=aligned_alloc(AVX,kfermHalo*sizeof(Complex_f));
465 Complex *R1= aligned_alloc(AVX,kferm*sizeof(Complex));
466 Complex_f *R1_f=aligned_alloc(AVX,kferm*sizeof(Complex_f));
467 memset(R1_f,0,kferm*sizeof(Complex_f));
468#endif
469 //The FORTRAN code had two Gaussian routines.
470 //gaussp was the normal Box-Muller and gauss0 didn't have 2 inside the square root
471 //Using σ=1/sqrt(2) in these routines has the same effect as gauss0
472#if (defined USE_GPU && defined _DEBUG)
473 //cudaMemPrefetchAsync(R1_f,kferm*sizeof(Complex_f),device,streams[1]);
474#endif
475 //Split into chunks to take into account the halos.
476 for(unsigned short j=0;j<nc*ngorkov;j++)
477 Gauss_c(R+j*kvolHalo,kvol , 0, 1/sqrt(2));
478
479 Dslashd_f(R1_f,R,ut_f,iu,id,gamval_f,gamin,dk_f,jqq,akappa);
480 if(c_sw)
481 ByClover_f(R1_f,R,clover,sigval_f,akappa,sigin,true);
482#ifdef USE_GPU
483 //Make sure the multiplication is finished before freeing its input!!
484 cudaFree(R);//cudaDeviceSynchronise();
485 //cudaFree is blocking so don't need to synchronise
487#ifdef _DEBUG
488 cudaFree(R1_f);
489#else
490 //Stream needs to wait for conversion to complete
492 cudaFreeAsync(R1_f,streams[0]);
493#endif
494 cudaMemcpyAsync(Phi+na*kferm,R1, kferm*sizeof(Complex),cudaMemcpyDefault,streams[1]);
495#else
496 free(R);
497#pragma omp simd aligned(R1_f,R1:AVX)
498 for(int i=0;i<kferm;i++)
499 R1[i]=(Complex)R1_f[i];
500 free(R1_f);
501 memcpy(Phi+na*kferm,R1, kferm*sizeof(Complex));
502 //Up/down partitioning (using only pseudofermions of flavour 1)
503#endif
504 UpDownPart(na, X0, R1);
505#ifdef USE_GPU
506#ifdef _DEBUG
507 cudaFree(R1);
508#else
509 //Stream needs to wait for UpDownPart to complete
511 cudaFreeAsync(R1,streams[1]);
512#endif
513#else
514 free(R1);
515#endif
516 }
517 if(c_sw)
518 Clover_free(clover);
519 //Heatbath
520 //========
521 //We're going to make the most of the new Gauss_d routine to send a flattened array
522 //and do this all in one step.
523#ifdef USE_GPU
524#if(nproc>1)//Strided memcpy
525 for(unsigned short mu=0;mu<ndim;mu++){
526 cudaMemcpyAsync(ut[0]+kvolHalo*mu, u[0]+kvol*mu, kvol*sizeof(Complex),cudaMemcpyDefault,streams[mu]);
527 cudaMemcpyAsync(ut[1]+kvolHalo*mu, u[1]+kvol*mu, kvol*sizeof(Complex),cudaMemcpyDefault,streams[mu]);
528 }
529#else
530 cudaMemcpyAsync(ut[0], u[0], ndim*kvol*sizeof(Complex),cudaMemcpyDefault,streams[0]);
531 cudaMemcpyAsync(ut[1], u[1], ndim*kvol*sizeof(Complex),cudaMemcpyDefault,streams[1]);
532#endif
534#else
535 for(unsigned short mu=0;mu<ndim;mu++){
536 memcpy(ut[0]+kvolHalo*mu, u[0]+kvol*mu, kvol*sizeof(Complex));
537 memcpy(ut[1]+kvolHalo*mu, u[1]+kvol*mu, kvol*sizeof(Complex));
538 }
539#endif
540 Trial_Exchange(ut,ut_f);
541 Gauss_d(pp, kmom, 0, 1);
542
543 //Initialise Trial Fields
544 //pp is random at this point so swapping the order isn't really necessary. But it does ensure that it matches
545 //previous results
546 // Transpose_d(pp,nadj*ndim,kvol);
547 double H0, S0;
548 Hamilton(&H0,&S0,rescga,pp,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,\
549 jqq,akappa,beta,c_sw,&ancgh,itraj);
550#ifdef _DEBUG
551 if(!rank) printf("H0: %e S0: %e\n", H0, S0);
552#endif
553 if(itraj==1)
554 action = S0/gvol;
555
556 //Integration
558#if (defined INT_LPFR && defined INT_OMF2) ||(defined INT_LPFR && defined INT_OMF4)||(defined INT_OMF2 && defined INT_OMF4)
559#error "Only one integrator may be defined"
560#elif defined INT_LPFR
561 Leapfrog(ut,ut_f,X0,X1,Phi,dk,dk_f,dSdpi,pp,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,\
562 jqq,beta,akappa,c_sw,stepl,dt,&ancg,&itot,proby);
563#elif defined INT_OMF2
564 OMF2(ut,ut_f,X0,X1,Phi,dk,dk_f,dSdpi,pp,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,\
565 jqq,beta,akappa,c_sw,stepl,dt,&ancg,&itot,proby);
566#elif defined INT_OMF4
567#warning "OMF4 can be less efficient than OMF2 in certain cases. Use with caution. See http://dx.doi.org/10.1103/PhysRevE.73.036706"
568 OMF4(ut,ut_f,X0,X1,Phi,dk,dk_f,dSdpi,pp,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,\
569 jqq,beta,akappa,c_sw,stepl,dt,&ancg,&itot,proby);
570#else
571#error "No integrator defined. Please define {INT_LPFR.INT_OMF2,INT_OMF4}"
572#endif
573
574 totancg+=ancg;
575 //Monte Carlo step: Accept new fields with the probability of min(1,exp(H0-X0))
576 //Kernel Call needed here?
577 Reunitarise(ut);
578 double H1, S1;
579 Hamilton(&H1,&S1,rescga,pp,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,\
580 jqq,akappa,beta,c_sw,&ancgh,itraj);
581 ancgh/=2.0; //Hamilton is called at start and end of trajectory
582 totancgh+=ancgh;
583#ifdef _DEBUG
584 printf("H0-H1=%f-%f",H0,H1);
585#endif
586 double dH = H0 - H1;
587#ifdef _DEBUG
588 printf("=%f\n",dH);
589#endif
590 double dS = S0 - S1;
591 if(!rank){
592 fprintf(output, "dH = %e dS = %e\n", dH, dS);
593#ifdef _DEBUG
594 printf("dH = %e dS = %e\n", dH, dS);
595#endif
596 }
597 e_dH+=dH; e_dH_e+=dH*dH;
598 double y = exp(dH);
599 yav+=y;
600 yyav+=y*y;
601 //The Monte-Carlo
602 //Always update dH is positive (gone from higher to lower energy)
603 bool acc;
604 if(dH>0 || Par_granf()<=y){
605 //Step is accepted. Set s=st
606 if(!rank)
607 printf("New configuration accepted on trajectory %i.\n", itraj);
608 //Original FORTRAN Comment:
609 //JIS 20100525: write config here to preempt troubles during measurement!
610 //JIS 20100525: remove when all is ok....
611#ifdef USE_GPU
612#if(nproc>1) //strided Memcpy
613 for(unsigned short mu=0;mu<ndim;mu++){
614 cudaMemcpyAsync(u[0]+kvol*mu,ut[0]+kvolHalo*mu,kvol*sizeof(Complex),cudaMemcpyDefault,streams[mu]);
615 cudaMemcpyAsync(u[1]+kvol*mu,ut[1]+kvolHalo*mu,kvol*sizeof(Complex),cudaMemcpyDefault,streams[mu]);
616 }
617#else
618 cudaMemcpyAsync(u[0],ut[0],ndim*kvol*sizeof(Complex),cudaMemcpyDefault,streams[0]);
619 cudaMemcpyAsync(u[1],ut[1],ndim*kvol*sizeof(Complex),cudaMemcpyDefault,streams[1]);
620#endif
621#else
622 for(unsigned short mu=0;mu<ndim;mu++){
623 memcpy(u[0]+kvol*mu,ut[0]+kvolHalo*mu,kvol*sizeof(Complex));
624 memcpy(u[1]+kvol*mu,ut[1]+kvolHalo*mu,kvol*sizeof(Complex));
625 }
626#endif
627 naccp++;
628 //Divide by gvol since we've summed over all lattice sites
629 action=S1/gvol;
630 acc=true;
631 }
632 else{
633 if(!rank)
634 printf("New configuration rejected on trajectory %i.\n", itraj);
635 acc=false;
636 }
637 actiona+=action;
638 double vel2=0.0;
639#ifdef USE_GPU
640 cublasDnrm2(cublas_handle,kmom, pp, 1,&vel2);
641 vel2*=vel2;
643#elif defined USE_BLAS
644 vel2 = cblas_dnrm2(kmom, pp, 1);
645 vel2*=vel2;
646#else
647#pragma unroll
648 for(int i=0; i<kmom; i++)
649 vel2+=pp[i]*pp[i];
650#endif
651#if(nproc>1)
652 Par_dsum(&vel2);
653#endif
654 vel2a+=vel2/(ndim*nadj*gvol);
655
656 if(itraj%iprint==0){
657 //If rejected, copy the previously accepted field in for measurements
658 if(!acc){
659#ifdef USE_GPU
660#if(nproc>1) //Strided Memcpy
661 for(unsigned short mu=0;mu<ndim;mu++){
662 cudaMemcpyAsync(ut[0]+kvolHalo*mu, u[0]+kvol*mu, kvol*sizeof(Complex),cudaMemcpyDefault,streams[mu]);
663 cudaMemcpyAsync(ut[1]+kvolHalo*mu, u[1]+kvol*mu, kvol*sizeof(Complex),cudaMemcpyDefault,streams[mu]);
664 }
665#else
666 cudaMemcpyAsync(ut[0], u[0], ndim*kvol*sizeof(Complex),cudaMemcpyDefault,streams[0]);
667 cudaMemcpyAsync(ut[1], u[1], ndim*kvol*sizeof(Complex),cudaMemcpyDefault,streams[1]);
668#endif
670#else
671 for(unsigned short mu=0;mu<ndim;mu++){
672 memcpy(ut[0]+kvolHalo*mu, u[0]+kvol*mu, kvol*sizeof(Complex));
673 memcpy(ut[1]+kvolHalo*mu, u[1]+kvol*mu, kvol*sizeof(Complex));
674 }
675#endif
676 Trial_Exchange(ut,ut_f);
677 }
678#ifdef _DEBUG
679 if(!rank)
680 printf("Starting measurements\n");
681#endif
682 int itercg=0;
683 double endenf, denf;
684 Complex qbqb;
685 //Stop gap for measurement failure on Kay;
686 //If the Congrad in Measure fails, don't measure the Diquark or PBP-Density observables for
687 //that trajectory
688 int measure_check=0;
689 measure_check = Measure(&pbp,&endenf,&denf,&qq,&qbqb,respbp,&itercg,ut,ut_f,iu,id,\
690 gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,c_sw,Phi);
691#ifdef _DEBUG
692 if(!rank)
693 printf("Finished measurements\n");
694#endif
695 pbpa+=pbp; endenfa+=endenf; denfa+=denf; ipbp++;
696 Average_Plaquette(&hg,&avplaqs,&avplaqt,ut_f,iu,beta);
697 poly = Polyakov(ut_f);
698 //We have four output files, so may as well get the other ranks to help out
699 //and abuse scoping rules while we're at it.
700 //Can use either OpenMP or MPI to do this
701#if (nproc>=4)
702 switch(rank)
703#else
704 if(!rank)
705#pragma omp parallel for
706 for(int i=0; i<4; i++)
707 switch(i)
708#endif
709 {
710 case(0):
711 //Output code... Some files weren't opened in the main loop of the FORTRAN code
712 //That will need to be looked into for the C version
713 //It would explain the weird names like fort.1X that looked like they were somehow
714 //FORTRAN related...
715 fprintf(output, "Measure (CG) %i Update (CG) %.3f Hamiltonian (CG) %.3f\n", itercg, ancg, ancgh);
716 fflush(output);
717 break;
718 case(1):
719 {
720 FILE *fortout;
721 char fortname[FILELEN] = "fermi.";
722 strcat(fortname,suffix);
723 const char *fortop= (itraj==1) ? "w" : "a";
724 if(!(fortout=fopen(fortname, fortop) )){
725 fprintf(stderr, "Error %i in %s: Failed to open file %s for %s.\nExiting\n\n",\
726 OPENERROR, funcname, fortname, fortop);
727#if(nproc>1)
728 MPI_Abort(comm,OPENERROR);
729#else
730 exit(OPENERROR);
731#endif
732 }
733 if(itraj==1)
734 fprintf(fortout, "pbp\tendenf\tdenf\n");
735 if(measure_check)
736 fprintf(fortout, "%e\t%e\t%e\n", NAN, NAN, NAN);
737 else
738 fprintf(fortout, "%e\t%e\t%e\n", pbp, endenf, denf);
739 fclose(fortout);
740 break;
741 }
742 case(2):
743 //The original code implicitly created these files with the name
744 //fort.XX where XX is the file label
745 //from FORTRAN. This was fort.12
746 {
747 FILE *fortout;
748 char fortname[FILELEN] = "bose.";
749 strcat(fortname,suffix);
750 const char *fortop= (itraj==1) ? "w" : "a";
751 if(!(fortout=fopen(fortname, fortop) )){
752 fprintf(stderr, "Error %i in %s: Failed to open file %s for %s.\nExiting\n\n",\
753 OPENERROR, funcname, fortname, fortop);
754 }
755 if(itraj==1)
756 fprintf(fortout, "avplaqs\tavplaqt\tpoly\n");
757 fprintf(fortout, "%e\t%e\t%e\n", avplaqs, avplaqt, poly);
758 fclose(fortout);
759 break;
760 }
761 case(3):
762 {
763 FILE *fortout;
764 char fortname[FILELEN] = "diq.";
765 strcat(fortname,suffix);
766 const char *fortop= (itraj==1) ? "w" : "a";
767 if(!(fortout=fopen(fortname, fortop) )){
768 fprintf(stderr, "Error %i in %s: Failed to open file %s for %s.\nExiting\n\n",\
769 OPENERROR, funcname, fortname, fortop);
770#if(nproc>1)
771 MPI_Abort(comm,OPENERROR);
772#else
773 exit(OPENERROR);
774#endif
775 }
776 if(itraj==1)
777 fprintf(fortout, "Re(qq)\n");
778 if(measure_check)
779 fprintf(fortout, "%e\n", NAN);
780 else
781 fprintf(fortout, "%e\n", creal(qq));
782 fclose(fortout);
783 break;
784 }
785 default: break;
786 }
787 }
788 if(itraj%icheck==0){
789 Par_swrite(itraj,icheck,beta,fmu,akappa,ajq,c_sw,u[0],u[1]);
790 }
791 if(!rank)
792 fflush(output);
793 }
794#if (defined SA3AT)
795 double elapsed = 0;
796 if(!rank){
797#if(nproc>1)
798 elapsed = MPI_Wtime()-start_time;
799#else
800 elapsed = omp_get_wtime()-start_time;
801#endif
802 }
803#endif
804 //End of main loop
805 //Free arrays
806#ifdef USE_GPU
807 //Make a routine that does this for us
808 cudaFree(dk[0]); cudaFree(dk[1]); cudaFree(dSdpi); cudaFree(pp);
809 cudaFree(Phi); cudaFree(ut[0]); cudaFree(ut[1]);
810 cudaFree(X0); cudaFree(X1); cudaFree(u[0]); cudaFree(u[1]);
811 cudaFree(id); cudaFree(iu);
812 cudaFree(dk_f[0]); cudaFree(dk_f[1]); cudaFree(ut_f[0]); cudaFree(ut_f[1]);
813 cudaFree(gamin); cudaFree(gamval); cudaFree(gamval_f);
814 if(c_sw){
815 cudaFree(sigval); cudaFree(sigval_f); cudaFree(sigin);
816 }
817 cublasDestroy(cublas_handle);
818#else
819 free(dk[0]); free(dk[1]);free(dSdpi); free(pp);
820 free(Phi); free(ut[0]); free(ut[1]);
821 free(X0); free(X1); free(u[0]); free(u[1]);
822 free(id); free(iu);
823 free(dk_f[0]); free(dk_f[1]); free(ut_f[0]); free(ut_f[1]);
824 if(c_sw){
825 free(sigval); free(sigval_f); free(sigin);
826 }
827#endif
828 free(hd); free(hu); free(pcoord);
829#ifdef __RANLUX__
830 gsl_rng_free(ranlux_instd);
831#endif
832#if (defined SA3AT)
833 if(!rank){
834 FILE *sa3at = fopen("Bench_times.csv", "a");
835#ifdef USE_GPU
836 char version[256];
837 int cuversion; cudaRuntimeGetVersion(&cuversion);
838 sprintf(version,"CUDA %d\tBlock: (%d,%d,%d)\tGrid: (%d,%d,%d)\n%s\n",cuversion,\
839 dimBlock.x,dimBlock.y,dimBlock.z,dimGrid.x,dimGrid.y,dimGrid.z,__VERSION__);
840#else
841 char *version=__VERSION__;
842#endif
843 fprintf(sa3at, "%s\nβ%0.3f κ:%0.4f μ:%0.4f j:%0.3f s:%i t:%i kvol:%ld\n"
844 "npx:%i npt:%i nthread:%i ncore:%i time:%f traj_time:%f\n\n",\
845 version,beta,akappa,fmu,ajq,nx,nt,kvol,npx,npt,nthreads,npx*npy*npz*npt*nthreads,elapsed,elapsed/ntraj);
846 fclose(sa3at);
847 }
848#endif
849 //Get averages for final output
850 actiona/=ntraj; vel2a/=ntraj; pbpa/=ipbp; endenfa/=ipbp; denfa/=ipbp;
851 totancg/=ntraj; totancgh/=ntraj;
852 e_dH/=ntraj; e_dH_e=sqrt((e_dH_e/ntraj-e_dH*e_dH)/(ntraj-1));
853 yav/=ntraj; yyav=sqrt((yyav/ntraj - yav*yav)/(ntraj-1));
854 float traj_cost=totancg/dt;
855 double atraj=dt*itot/ntraj;
856
857 if(!rank){
858 fprintf(output, "Averages for the last %i trajectories\n"\
859 "Number of acceptances: %i\tAverage Trajectory Length = %e\n"\
860 "<dH>=%e+/-%e\t<exp(dH)>=%e+/-%e\tTrajectory cost=N_cg/dt =%e\n"\
861 "Average number of congrad iter guidance: %.3f acceptance %.3f\n"\
862 "psibarpsi = %e\n"\
863 "Mean Square Velocity = %e\tAction Per Site = %e\n"\
864 "Energy Density = %e\tNumber Density %e\n\n\n",\
865 ntraj, naccp, atraj, e_dH,e_dH_e, yav, yyav, traj_cost, totancg, totancgh, pbpa, vel2a, actiona, endenfa, denfa);
866 fclose(output);
867 }
868#if(nproc>1)
869 //Ensure writing is done before finalising just in case finalise segfaults and crashes the other ranks mid-write
870 MPI_Barrier(comm);
871 MPI_Finalise();
872#endif
873 fflush(stdout);
874 return 0;
875}
Routines needed for Clover improved wilson fermions.
unsigned int * hd
Down halo indices.
Definition coord.c:11
unsigned int * hu
Up halo indices.
Definition coord.c:11
#define OPENERROR
Error opening file.
Definition errorcodes.h:32
#define NOIMPL
Not implemented.
Definition errorcodes.h:165
double Polyakov(Complex_f *ut[2])
Calculate the Polyakov loop (no prizes for guessing that one...).
Definition bosonic.c:74
int Average_Plaquette(double *hg, double *avplaqs, double *avplaqt, Complex_f *ut[2], unsigned int *iu, float beta)
Calculates the gauge action using new (how new?) lookup table Follows a routine called qedplaq in som...
Definition bosonic.c:14
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...
Definition clover.c:336
void Clover_free(Complex_f *clover[nc])
Free's memory used for clover terms and leaves.
Definition clover.c:750
int Init_clover(Complex **sigval, Complex_f **sigval_f, unsigned short **sigin, float c_sw)
Initialise values needed for the clover terms.
Definition clover.c:705
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.
Definition clover.c:203
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.
Definition matrices.c:544
int Measure(double *pbp, double *endenf, double *denf, Complex *qq, Complex *qbqb, double res, int *itercg, Complex *ut[2], Complex_f *ut_f[2], 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, Complex *Phi)
Calculate fermion expectation values via a noisy estimator.
Definition fermionic.c:7
void blockInit(int x, int y, int z, int t, dim3 *dimBlock, dim3 *dimGrid)
Initialises the CUDA grid and block size for a given lattice.
Definition cusu2hmc.cu:205
void Init_CUDA(Complex *u11t, Complex *u12t, Complex gamval[20], Complex_f gamval_f[20], unsigned short gamin[16], double *dk4m, double *dk4p, unsigned int *iu, unsigned int *id)
Initialise CUDA cuInit was taken already by CUDA (unsurprisingly).
Definition cusu2hmc.cu:248
int Init(const int istart, const int ibound, const int iread, const float beta, const float fmu, const float akappa, const Complex_f ajq, const float c_sw, Complex *u[2], Complex *ut[2], Complex_f *ut_f[2], Complex gamval[20], Complex_f gamval_f[20], unsigned short gamin[16], double *dk[2], float *dk_f[2], unsigned int *iu, unsigned int *id)
Initialises the system.
Definition su2hmc.c:10
int UpDownPart(const unsigned int na, Complex *X0, Complex *R1)
Up/Down partitioning of the pseudofermion field.
Definition su2hmc.c:327
int Reunitarise(Complex *ut[2])
Reunitarises u11t and u12t as in conj(u11t[i])*u11t[i]+conj(u12t[i])*u12t[i]=1.
Definition su2hmc.c:342
void cuComplex_convert(Complex_f *a, Complex *b, const unsigned int len, const bool dtof, dim3 dimBlock, dim3 dimGrid)
takes an array of complex float and double precision numbers and converts the precision
Definition cusu2hmc.cu:284
int OMF2(Complex *ut[2], Complex_f *ut_f[2], Complex *X0, Complex *X1, Complex *Phi, double *dk[2], float *dk_f[2], double *dSdpi, double *pp, 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, const Complex jqq, const float beta, const float akappa, const float c_sw, const int stepl, const float dt, double *ancg, int *itot, const float proby)
OMF second order five step integrator.
Definition integrate.c:141
int Leapfrog(Complex *ut[2], Complex_f *ut_f[2], Complex *X0, Complex *X1, Complex *Phi, double *dk[2], float *dk_f[2], double *dSdpi, double *pp, 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, const Complex jqq, const float beta, const float akappa, const float c_sw, const int stepl, const float dt, double *ancg, int *itot, const float proby)
Leapfrog integrator. Each trajectory step takes the form of p->p+dt/2,u->u+dt,p->p+dt/2 In practice t...
int OMF4(Complex *ut[2], Complex_f *ut_f[2], Complex *X0, Complex *X1, Complex *Phi, double *dk[2], float *dk_f[2], double *dSdpi, double *pp, 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, const Complex jqq, const float beta, const float akappa, const float c_sw, const int stepl, const float dt, double *ancg, int *itot, const float proby)
OMF fourth order eleven step integrator.
int Par_fcopy(float *fval)
Broadcasts a float to the other processes.
int Par_begin(int argc, char *argv[])
Initialises the MPI configuration.
Definition par_mpi.c:24
int Par_swrite(const int itraj, const int icheck, const float beta, const float fmu, const float akappa, const Complex_f ajq, const float c_sw, Complex *u11, Complex *u12)
Copies u11 and u12 into arrays without halos which then get written to output.
Definition par_mpi.c:324
int Par_icopy(int *ival)
Broadcasts an integer to the other processes.
int Trial_Exchange(Complex *ut[2], Complex_f *ut_f[2])
Exchanges the trial fields.
Definition par_mpi.c:1043
int Par_dsum(double *dval)
Performs a reduction on a double dval to get a sum which is then distributed to all ranks.
int Hamilton(double *h, double *s, double res2, double *pp, Complex *X0, Complex *X1, Complex *Phi, Complex *ud[2], Complex_f *ut[2], 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 beta, float c_sw, double *ancgh, int traj)
Calculate the Hamiltonian.
Definition su2hmc.c:168
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...
Definition random.c:136
int Gauss_d(double *ps, unsigned int n, const double mu, const double sigma)
Generates a vector of normally distributed random double precision numbers using the Box-Muller Metho...
Definition random.c:170
double Par_granf()
Generates a random double which is then sent to the other ranks.
Definition random.c:87
int main(int argc, char *argv[])
Definition main.c:71
Matrix multiplication and related declarations.
int size
The number of MPI ranks in total.
Definition par_mpi.c:20
int rank
The MPI rank.
Definition par_mpi.c:20
#define MPI_Finalise()
Avoid any accidents with US/UK spelling.
Definition par_mpi.h:32
int * pcoord
The processor grid.
Definition par_mpi.c:17
unsigned long seed
RANLUX seed.
Definition random.c:18
gsl_rng * ranlux_instd
RANLUX instance.
Definition random.c:16
#define AVX
Alignment of arrays. 64 for AVX-512, 32 for AVX/AVX2. 16 for SSE. Since AVX is standard on modern x86...
Definition sizes.h:279
#define nc
Colours.
Definition sizes.h:182
#define rescgg
Conjugate gradient residue for update.
Definition sizes.h:251
#define nt
Lattice temporal extent. This also corresponds to the inverse temperature.
Definition sizes.h:92
#define kmom
sublattice momentum sites
Definition sizes.h:193
#define nx
Lattice x extent.
Definition sizes.h:72
cudaMemPool_t mempool
Memory pool for Async allocations.
Definition main.c:49
#define ngorkov
Gor'kov indices.
Definition sizes.h:190
#define ksizet
Sublattice t extent.
Definition sizes.h:158
#define kferm2Halo
Dirac lattice and halo.
Definition sizes.h:238
#define npx
Processor grid x extent. This must be a divisor of nx.
Definition sizes.h:103
#define nadj
adjacent spatial indices
Definition sizes.h:184
#define kvol
Sublattice volume.
Definition sizes.h:163
#define Complex
Double precision complex number.
Definition sizes.h:64
#define kferm
sublattice size including Gor'kov indices
Definition sizes.h:195
#define rescga
Conjugate gradient residue for acceptance.
Definition sizes.h:253
#define npz
Processor grid z extent.
Definition sizes.h:122
#define nthreads
Number of threads for OpenMP, which can be overwritten at runtime.
Definition sizes.h:144
#define ksize
Sublattice spatial extent for a cubic lattice.
Definition sizes.h:155
#define nf
Fermion flavours (double it).
Definition sizes.h:160
cublasStatus_t cublas_status
Status of cuBLAS for error reporting.
Definition main.c:48
#define cudaDeviceSynchronise()
Get rid of that bastardised yankee English.
Definition sizes.h:53
#define respbp
Conjugate gradient residue for .
Definition sizes.h:249
#define gvol
Lattice volume.
Definition sizes.h:98
#define FILELEN
Default file name length.
Definition sizes.h:68
cublasHandle_t cublas_handle
Handle for cuBLAS.
Definition main.c:47
#define halo
Total Halo size.
Definition sizes.h:231
#define Complex_f
Single precision complex number.
Definition sizes.h:62
dim3 dimGrid
Default grid size. First component is normally nt. Second and third depend whatever is needed to get ...
Definition cusu2hmc.cu:27
#define npy
Processor grid y extent.
Definition sizes.h:114
#define ndim
Dimensions.
Definition sizes.h:188
#define kferm2
sublattice size including Dirac indices
Definition sizes.h:197
#define npt
Processor grid t extent.
Definition sizes.h:130
#define kvolHalo
Subvolume + halo size.
Definition sizes.h:234
#define kfermHalo
Gor'kov lattice and halo.
Definition sizes.h:236
#define nz
Lattice z extent. We normally use cubic lattices so this is the same as nx.
Definition sizes.h:86
#define ny
Lattice y extent. We normally use cubic lattices so this is the same as nx.
Definition sizes.h:80
dim3 dimBlock
Default block size. Usually 128.
Definition cusu2hmc.cu:25
cudaStream_t streams[ndirac *ndim *nadj]
An array of concurrent GPU streams to keep it busy.
Definition cusu2hmc.cu:29
#define creal(z)
Extract Real Component using C standard notation.
#define cimag(z)
Extract Imaginary Component using C standard notation.