su2hmc
Loading...
Searching...
No Matches
integrate.c
Go to the documentation of this file.
1
8#include <su2hmc.h>
9#include <matrices.h>
19void Force_debug(double ave_dSdpi[3],double *dSdpi){
20#ifdef USE_GPU
21 ave_dSdpi[0]=cureduce_sum_d(dSdpi,kvol*ndim,0);
22 ave_dSdpi[1]=cureduce_sum_d(dSdpi+kvol*ndim,kvol*ndim,1);
23 ave_dSdpi[2]=cureduce_sum_d(dSdpi+2*kvol*ndim,kvol*ndim,2);
25#else
26 ave_dSdpi[0]=0; ave_dSdpi[1]=0; ave_dSdpi[2]=0;
27 for(unsigned int i=0;i<kvol*ndim;i++){
28 ave_dSdpi[0]+=dSdpi[i];
29 ave_dSdpi[1]+=dSdpi[i+kvol*ndim];
30 ave_dSdpi[2]+=dSdpi[i+2*kvol*ndim];
31 }
32#endif
33 ave_dSdpi[0]/=(ndim*kvol); ave_dSdpi[1]/=(ndim*kvol); ave_dSdpi[2]/=(ndim*kvol);
34 return;
35}
36
37int Gauge_Update(const double d, double *pp, Complex *ut[2],Complex_f *ut_f[2]){
38 char funcname[] = "Gauge_Update";
39#ifdef USE_GPU
41#else
42#pragma omp parallel for simd collapse(2) aligned(pp:AVX)
43 for(unsigned int i=0;i<kvol;i++)
44 for(unsigned short mu = 0; mu<ndim; mu++){
45 /*
46 * Sticking to what was in the FORTRAN for variable names.
47 * CCC for cosine SSS for sine AAA for...
48 * Re-exponentiating the force field. Can be done analytically in SU(2)
49 * using sine and cosine which is nice
50 */
51 const unsigned int ind = i+kvol*mu;
52 double AAA = d*sqrt(pp[ind]*pp[ind]\
53 +pp[i+kvol*(1*ndim+mu)]*pp[i+kvol*(1*ndim+mu)]\
54 +pp[i+kvol*(2*ndim+mu)]*pp[i+kvol*(2*ndim+mu)]);
55 double CCC = cos(AAA);
56 double SSS = d*sin(AAA)/AAA;
57 Complex a11 = CCC+I*SSS*pp[i+kvol*(2*ndim+mu)];
58 Complex a12 = pp[i+kvol*(1*ndim+mu)]*SSS + I*SSS*pp[ind];
59 //b11 and b12 are ut[0] and ut[1] terms, so we'll use ut[1] directly
60 //but use b11 for ut[0] to prevent RAW dependency
61 Complex b11 = ut[0][i+kvolHalo*mu];
62 ut[0][i+kvolHalo*mu] = a11*b11-a12*conj(ut[1][i+kvolHalo*mu]);
63 ut[1][i+kvolHalo*mu] = a11*ut[1][i+kvolHalo*mu]+a12*conj(b11);
64 }
65#endif
66 Reunitarise(ut);
67 //Get trial fields from accelerator for halo exchange
68 Trial_Exchange(ut,ut_f);
69 return 0;
70}
71inline int Momentum_Update(const double d, const double *dSdpi, double *pp)
72{
73 const char funcname[] = "Momentum_Update";
74#ifdef USE_GPU
75 cublasDaxpy(cublas_handle,kmom, &d, dSdpi, 1, pp, 1);
77#elif defined USE_BLAS
78 cblas_daxpy(kmom, d, dSdpi, 1, pp, 1);
79#else
80#pragma omp parallel for simd
81 for(int i=0;i<kmom;i++)
82 pp[i]+=d*dSdpi[i];
83#endif
84 return 0;
85}
86#if defined INT_LPFR
87int Leapfrog(Complex *ut[2],Complex_f *ut_f[2],Complex *X0,Complex *X1, Complex *Phi,double *dk[2],float *dk_f[2],
88 double *dSdpi,double *pp, unsigned int *iu,unsigned int *id, Complex gamval[20], Complex_f gamval_f[20], const unsigned short gamin[16],
89 Complex *sigval, Complex_f *sigval_f, unsigned short *sigin, const Complex jqq, const float beta, const float akappa,
90 const float c_sw, const int stepl, const float dt, double *ancg, int *itot, const float proby)
91{
92 const char funcname[] = "Leapfrog";
93 //This was originally in the half-step of the FORTRAN code, but it makes more sense to declare
94 //it outside the loop. Since it's always being subtracted we'll define it as negative
95 const double d =-dt*0.5;
96 //Half step forward for p
97 //=======================
98#ifdef _DEBUG
99 printf("Evaluating force on rank %i\n", rank);
100#endif
101 Force(dSdpi, 1, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
102 Momentum_Update(d,dSdpi,pp);
103 //Main loop for classical time evolution
104 //======================================
105 bool end_traj=false; int step =1;
106 // for(int step = 1; step<=stepmax; step++){
107 do{
108#ifdef _DEBUG
109 if(!rank)
110 printf("Step: %d\n", step);
111#endif
112 //The FORTRAN redefines d=dt here, which makes sense if you have a limited line length.
113 //I'll stick to using dt though.
114 //step (i) st(t+dt)=st(t)+p(t+dt/2)*dt;
115 //Note that we are moving from kernel to kernel within the default streams so don't need a Device_Sync here
116 Gauge_Update(dt,pp,ut,ut_f);
117
118 //p(t+3et/2)=p(t+dt/2)-dSds(t+dt)*dt
119 // Force(dSdpi, 0, rescgg);
120 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
121
122 // if(step>=stepl*4.0/5.0 && (step>=stepl*(6.0/5.0) || Par_granf()<proby)){
123 if(step==stepl){
124 //Final trajectory has a half momentum step
125 Momentum_Update(d,dSdpi,pp);
126 *itot+=step;
127 *ancg/=step;
128 end_traj=true;
129 break;
130 }
131 else{
132 //Otherwise, there's a half step at the end and start of each trajectory, so we combine them into one full step.
133 Momentum_Update(-dt,dSdpi,pp);
134 step++;
135 }
136 }while(!end_traj);
137
138 return 0;
139 }
140#elif defined INT_OMF2
141 int OMF2(Complex *ut[2],Complex_f *ut_f[2],Complex *X0,Complex *X1, Complex *Phi,double *dk[2],float *dk_f[2],
142 double *dSdpi,double *pp, unsigned int *iu,unsigned int *id, Complex gamval[20], Complex_f gamval_f[20], const unsigned short gamin[16],
143 Complex *sigval, Complex_f *sigval_f, unsigned short *sigin, const Complex jqq, const float beta, const float akappa,
144 const float c_sw, const int stepl, const float dt, double *ancg, int *itot, const float proby)
145 {
146 const char funcname[] = "OMF2";
147 const double lambda=0.5-(pow(2.0*sqrt(326.0)+36.0,1.0/3.0)/12.0)+1.0/(6*pow(2.0*sqrt(326.0) + 36.0,1.0/3.0));
148 //const double lambda=1.0/6.0;
149 // const double lambda=0.5;
150
151 //Gauge update by half dt
152 const double dU = dt*0.5;
153
154 //Momentum updates by lambda, 2lambda and (1-2lambda) in the middle
155 const double dp= -lambda*dt;
156 const double dp2= 2.0*dp;
157 const double dpm= -(1.0-2.0*lambda)*dt;
158 //Initial step forward for p
159 //=======================
160#ifdef _DEBUG
161 if(!rank){
162 double ave_dSdpi[3];
163 Force_debug(ave_dSdpi,dSdpi);
164 printf("Before evaluating force on rank %i, dSdpi[0] %e dSdpi[1] %e dSdpi[2] %e\n", rank,ave_dSdpi[0],ave_dSdpi[1],ave_dSdpi[2]);
165 double ave_pp[3];
166 Force_debug(ave_pp,pp);
167 printf("Average momentum pp[0] %e pp[1] %e pp[2] %e\n", ave_pp[0],ave_pp[1],ave_pp[2]);
168 }
169#endif
170 Force(dSdpi, 1, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
171#ifdef _DEBUG
172 if(!rank){
173 double ave_dSdpi[3];
174 Force_debug(ave_dSdpi,dSdpi);
175 printf("Average force on rank %i, dSdpi[0] %e dSdpi[1] %e dSdpi[2] %e\n", rank,ave_dSdpi[0],ave_dSdpi[1],ave_dSdpi[2]);
176 }
177#endif
178 //Initial momentum update
179 Momentum_Update(dp,dSdpi,pp);
180#ifdef _DEBUG
181 if(!rank){
182 double ave_pp[3];
183 Force_debug(ave_pp,pp);
184 printf("Average initial momentum on rank %i, pp[0] %e pp[1] %e pp[2] %e\n", rank,ave_pp[0],ave_pp[1],ave_pp[2]);
185 }
186#endif
187
188 //Main loop for classical time evolution
189 //======================================
190 bool end_traj=false; int step =1;
191 // for(int step = 1; step<=stepmax; step++){
192 do{
193#ifdef _DEBUG
194 if(!rank)
195 printf("Step: %d\n", step);
196#endif
197 //First gauge update
198 Gauge_Update(dU,pp,ut,ut_f);
199
200 //Calculate force for middle momentum update
201 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
202#ifdef _DEBUG
203 if(!rank){
204 double ave_dSdpi[3];
205 Force_debug(ave_dSdpi,dSdpi);
206 printf("First force update on rank %i, dSdpi[0] %e dSdpi[1] %e dSdpi[2] %e\n", rank,ave_dSdpi[0],ave_dSdpi[1],ave_dSdpi[2]);
207 }
208#endif
209 //Now do the middle momentum update
210 Momentum_Update(dpm,dSdpi,pp);
211#ifdef _DEBUG
212 if(!rank){
213 double ave_pp[3];
214 Force_debug(ave_pp,pp);
215 printf("Average middle momentum on rank %i, pp[0] %e pp[1] %e pp[2] %e\n", rank,ave_pp[0],ave_pp[1],ave_pp[2]);
216 }
217#endif
218
219 //Second gauge update
220 Gauge_Update(dU,pp,ut,ut_f);
221
222 //Calculate force for second momentum update
223 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
224#ifdef _DEBUG
225 if(!rank){
226 double ave_dSdpi[3];
227 Force_debug(ave_dSdpi,dSdpi);
228 printf("Second force update on rank %i, dSdpi[0] %e dSdpi[1] %e dSdpi[2] %e\n", rank,ave_dSdpi[0],ave_dSdpi[1],ave_dSdpi[2]);
229 }
230#endif
231
232 //if(step>=stepl*4.0/5.0 && (step>=stepl*(6.0/5.0) || Par_granf()<proby)){
233 if(step==stepl){
234 //Final momentum step
235 Momentum_Update(dp,dSdpi,pp);
236#ifdef _DEBUG
237 if(!rank){
238 double ave_pp[3];
239 Force_debug(ave_pp,pp);
240 printf("Average final momentum on rank %i, pp[0] %e pp[1] %e pp[2] %e\n", rank,ave_pp[0],ave_pp[1],ave_pp[2]);
241 }
242#endif
243 *itot+=step;
244 //Two force terms, so an extra factor of two in the average?
245 //Or leave it as it was, to get the average CG iterations per trajectory rather than force
246 *ancg/=step;
247 end_traj=true;
248 break;
249 }
250 else{
251 //Since we apply the momentum at the start and end of a step we instead apply a double step here
252 Momentum_Update(dp2,dSdpi,pp);
253#ifdef _DEBUG
254 if(!rank){
255 double ave_pp[3];
256 Force_debug(ave_pp,pp);
257 printf("Average intermediate momentum on rank %i, pp[0] %e pp[1] %e pp[2] %e\n", rank,ave_pp[0],ave_pp[1],ave_pp[2]);
258 }
259#endif
260 step++;
261 }
262 }while(!end_traj);
263 return 0;
264 }
265#elif defined INT_OMF4
266#warning "OMF4 can be less efficient than OMF2 in certain cases. Use with caution. See http://dx.doi.org/10.1103/PhysRevE.73.036706"
267 int OMF4(Complex *ut[2],Complex_f *ut_f[2],Complex *X0,Complex *X1, Complex *Phi,double *dk[2],float *dk_f[2],
268 double *dSdpi,double *pp, unsigned int *iu,unsigned int *id, Complex gamval[20], Complex_f gamval_f[20], const unsigned short gamin[16],
269 Complex *sigval, Complex_f *sigval_f, unsigned short *sigin, const Complex jqq, const float beta, const float akappa,
270 const float c_sw, const int stepl, const float dt, double *ancg, int *itot, const float proby)
271 {
272 const char funcname[] = "OMF4";
273 //These values were lifted from openqcd-fastsum,
274 const double theta = 0.08398315262876693;
275 const double rho = 0.2539785108410595;
276 const double lambda = 0.6822365335719091;
277 const double vartheta = -0.03230286765269967;
278
281 const double dpO= -theta*dt;
282 const double dpO2= 2*dpO;
284 const double dpM= -lambda*dt;
286 const double dpI= -(0.5-theta-lambda)*dt;
287
290 const double duO = dt*rho;
292 const double duM = dt*vartheta;
294 const double duI = dt*(1-2*(rho+vartheta));
295
296 //Initial step forward for p
297 //=======================
298#ifdef _DEBUG
299 printf("Evaluating force on rank %i\n", rank);
300#endif
301 Force(dSdpi, 1, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
302 Momentum_Update(dpO,dSdpi,pp);
303
304 //Main loop for classical time evolution
305 //======================================
306 bool end_traj=false; int step =1;
307 // for(int step = 1; step<=stepmax; step++){
308 do{
309#ifdef _DEBUG
310 if(!rank)
311 printf("Step: %d\n", step);
312#endif
313 //First outer gauge update
314 Gauge_Update(duO,pp,ut,ut_f);
315
316 //Calculate force for first middle momentum update
317 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
318 //Now do the first middle momentum update
319 Momentum_Update(dpM,dSdpi,pp);
320
321 //First middle gauge update
322 Gauge_Update(duM,pp,ut,ut_f);
323
324 //Calculate force for first inner momentum update
325 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
326 //Now do the first inner momentum update
327 Momentum_Update(dpI,dSdpi,pp);
328
329 //Inner gauge update
330 Gauge_Update(duI,pp,ut,ut_f);
331
332 //Calculate force for second inner momentum update
333 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
334 //Now do the second inner momentum update
335 Momentum_Update(dpI,dSdpi,pp);
336
337 //Second middle gauge update
338 Gauge_Update(duM,pp,ut,ut_f);
339
340 //Calculate force for second middle momentum update
341 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
342 //Now do the second middle momentum update
343 Momentum_Update(dpM,dSdpi,pp);
344
345 //Second outer gauge update
346 Gauge_Update(duO,pp,ut,ut_f);
347
348 //Calculate force for outer momentum update
349 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,sigval,sigval_f,sigin,dk,dk_f,jqq,akappa,beta,c_sw,ancg);
350
351 //Outer momentum update depends on if we've finished the trajectory
352 //if(step>=stepl*4.0/5.0 && (step>=stepl*(6.0/5.0) || Par_granf()<proby)){
353 if(step==stepl){
354 //Final momentum step
355 Momentum_Update(dpO,dSdpi,pp);
356 *itot+=step;
357
358 //Four force terms, so an extra factor of four in the average?
359 //Or leave it as it was, to get the average CG iterations per trajectory rather than force
360 *ancg/=step;
361 end_traj=true;
362 break;
363 }
364 else{
365 //Since we apply the momentum at the start and end of a step we instead apply a double step here
366 Momentum_Update(dpO2,dSdpi,pp);
367 step++;
368 }
369 }while(!end_traj);
370 return 0;
371 }
372#endif
void Force_debug(double ave_dSdpi[3], double *dSdpi)
Gets average for each generator of the Lie algebra.
Definition integrate.c:19
double cureduce_sum_d(double *input, const unsigned int n, const unsigned short stream)
Sum all terms in an array of doubles.
__device__ __forceinline__ T conj(const T &z)
Complex Conjugation.
Definition cusu2hmc.cu:33
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 cuGauge_Update(const double d, double *pp, Complex *ut[2], dim3 dimGrid, dim3 dimBlock)
CUDA wrapper for the gauge update during the integration step of the HMC.
Definition cusu2hmc.cu:298
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 Gauge_Update(const double d, double *pp, Complex *ut[2], Complex_f *ut_f[2])
Gauge update for the integration step of the HMC.
Definition integrate.c:37
int Momentum_Update(const double d, const double *dSdpi, double *pp)
Wrapper for the momentum update during the integration step of the HMC.
Definition integrate.c:71
int Force(double *dSdpi, const bool iflag, double res1, Complex *X0, Complex *X1, Complex *Phi, 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], const Complex_f jqq, const float akappa, const float beta, const float c_sw, double *ancg)
Calculates the force at each intermediate time.
Definition force.c:228
int Trial_Exchange(Complex *ut[2], Complex_f *ut_f[2])
Exchanges the trial fields.
Definition par_mpi.c:1043
Matrix multiplication and related declarations.
int rank
The MPI rank.
Definition par_mpi.c:20
#define rescgg
Conjugate gradient residue for update.
Definition sizes.h:251
#define kmom
sublattice momentum sites
Definition sizes.h:193
#define kvol
Sublattice volume.
Definition sizes.h:163
#define Complex
Double precision complex number.
Definition sizes.h:64
#define cudaDeviceSynchronise()
Get rid of that bastardised yankee English.
Definition sizes.h:53
cublasHandle_t cublas_handle
Handle for cuBLAS.
Definition main.c:47
#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 ndim
Dimensions.
Definition sizes.h:188
#define kvolHalo
Subvolume + halo size.
Definition sizes.h:234
dim3 dimBlock
Default block size. Usually 128.
Definition cusu2hmc.cu:25
Function declarations for most of the routines.
#define I
Define I in double precision using C standard notation.