su2hmc
Loading...
Searching...
No Matches
integrate.c
Go to the documentation of this file.
1
5#include <su2hmc.h>
6
7int Gauge_Update(const double d, double *pp, Complex *ut[2],Complex_f *ut_f[2]){
8 /*
9 * @brief Generates new trial fields
10 *
11 * @see cuGauge_Update (CUDA Wrapper)
12 *
13 * @param d: Half lattice spacing
14 * @param pp: Momentum field
15 * @param ut[0]: First colour field
16 * @param ut[1]: Second colour field
17 *
18 * @returns Zero on success, integer error code otherwise
19 */
20 char *funcname = "Gauge_Update";
21#ifdef __NVCC__
22 cuGauge_Update(d,pp,ut[0],ut[1],dimGrid,dimBlock);
23#else
24#pragma omp parallel for simd collapse(2) aligned(pp:AVX)
25 for(int i=0;i<kvol;i++)
26 for(int mu = 0; mu<ndim; mu++){
27 /*
28 * Sticking to what was in the FORTRAN for variable names.
29 * CCC for cosine SSS for sine AAA for...
30 * Re-exponentiating the force field. Can be done analytically in SU(2)
31 * using sine and cosine which is nice
32 */
33
34 double AAA = d*sqrt(pp[i*nadj*ndim+mu]*pp[i*nadj*ndim+mu]\
35 +pp[(i*nadj+1)*ndim+mu]*pp[(i*nadj+1)*ndim+mu]\
36 +pp[(i*nadj+2)*ndim+mu]*pp[(i*nadj+2)*ndim+mu]);
37 double CCC = cos(AAA);
38 double SSS = d*sin(AAA)/AAA;
39 Complex a11 = CCC+I*SSS*pp[(i*nadj+2)*ndim+mu];
40 Complex a12 = pp[(i*nadj+1)*ndim+mu]*SSS + I*SSS*pp[i*nadj*ndim+mu];
41 //b11 and b12 are ut[0] and ut[1] terms, so we'll use ut[1] directly
42 //but use b11 for ut[0] to prevent RAW dependency
43 complex b11 = ut[0][i*ndim+mu];
44 ut[0][i*ndim+mu] = a11*b11-a12*conj(ut[1][i*ndim+mu]);
45 ut[1][i*ndim+mu] = a11*ut[1][i*ndim+mu]+a12*conj(b11);
46 }
47#endif
48 Reunitarise(ut);
49 //Get trial fields from accelerator for halo exchange
50 Trial_Exchange(ut,ut_f);
51 return 0;
52}
53inline int Momentum_Update(const double d, const double *dSdpi, double *pp)
54{
55#ifdef __NVCC__
56 cublasDaxpy(cublas_handle,kmom, &d, dSdpi, 1, pp, 1);
57#elif defined USE_BLAS
58 cblas_daxpy(kmom, d, dSdpi, 1, pp, 1);
59#else
60#pragma omp parallel for simd
61 for(int i=0;i<kmom;i++)
62 pp[i]+=d*dSdpi[i];
63#endif
64}
65int Leapfrog(Complex *ut[2],Complex_f *ut_f[2],Complex *X0,Complex *X1, Complex *Phi,double *dk[2],float *dk_f[2],
66 double *dSdpi,double *pp, int *iu,int *id, Complex *gamval, Complex_f *gamval_f, int *gamin, Complex jqq,
67 float beta, float akappa, int stepl, float dt, double *ancg, int *itot, float proby)
68{
69 //This was originally in the half-step of the FORTRAN code, but it makes more sense to declare
70 //it outside the loop. Since it's always being subtracted we'll define it as negative
71 const double d =-dt*0.5;
72 //Half step forward for p
73 //=======================
74#ifdef _DEBUG
75 printf("Evaluating force on rank %i\n", rank);
76#endif
77 Force(dSdpi, 1, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
78 Momentum_Update(d,dSdpi,pp);
79 //Main loop for classical time evolution
80 //======================================
81 bool end_traj=false; int step =1;
82 // for(int step = 1; step<=stepmax; step++){
83 do{
84#ifdef _DEBUG
85 if(!rank)
86 printf("Step: %d\n", step);
87#endif
88 //The FORTRAN redefines d=dt here, which makes sense if you have a limited line length.
89 //I'll stick to using dt though.
90 //step (i) st(t+dt)=st(t)+p(t+dt/2)*dt;
91 //Note that we are moving from kernel to kernel within the default streams so don't need a Device_Sync here
92 Gauge_Update(dt,pp,ut,ut_f);
93
94 //p(t+3et/2)=p(t+dt/2)-dSds(t+dt)*dt
95 // Force(dSdpi, 0, rescgg);
96 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
97
98 // if(step>=stepl*4.0/5.0 && (step>=stepl*(6.0/5.0) || Par_granf()<proby)){
99 if(step==stepl){
100 //Final trajectory has a half momentum step
101 Momentum_Update(d,dSdpi,pp);
102 *itot+=step;
103 *ancg/=step;
104 end_traj=true;
105 break;
106 }
107 else{
108 //Otherwise, there's a half step at the end and start of each trajectory, so we combine them into one full step.
109 Momentum_Update(-dt,dSdpi,pp);
110 step++;
111 }
112 }while(!end_traj);
113
114 return 0;
115}
116int OMF2(Complex *ut[2],Complex_f *ut_f[2],Complex *X0,Complex *X1, Complex *Phi,double *dk[2],float *dk_f[2],
117 double *dSdpi,double *pp, int *iu,int *id, Complex *gamval, Complex_f *gamval_f, int *gamin, Complex jqq,
118 float beta, float akappa, int stepl, float dt, double *ancg, int *itot, float proby)
119{
120 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));
121 //const double lambda=1.0/6.0;
122 // const double lambda=0.5;
123
124 //Gauge update by half dt
125 const double dU = dt*0.5;
126
127 //Momentum updates by lambda, 2lambda and (1-2lambda) in the middle
128 const double dp= -lambda*dt;
129 const double dp2= 2.0*dp;
130 const double dpm= -(1.0-2.0*lambda)*dt;
131 //Initial step forward for p
132 //=======================
133#ifdef _DEBUG
134 printf("Evaluating force on rank %i\n", rank);
135#endif
136 Force(dSdpi, 1, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
137#ifdef _DEBUG
138 printf("Initial force dSdpi[0]=%e\n", dSdpi[0]);
139#endif
140 //Initial momentum update
141 Momentum_Update(dp,dSdpi,pp);
142#ifdef _DEBUG
143 printf("Initial OMF2 momentum pp[0]=%e\n", pp[0]);
144#endif
145
146 //Main loop for classical time evolution
147 //======================================
148 bool end_traj=false; int step =1;
149 // for(int step = 1; step<=stepmax; step++){
150 do{
151#ifdef _DEBUG
152 if(!rank)
153 printf("Step: %d\n", step);
154#endif
155 //First gauge update
156 Gauge_Update(dU,pp,ut,ut_f);
157
158 //Calculate force for middle momentum update
159 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
160 //Now do the middle momentum update
161 Momentum_Update(dpm,dSdpi,pp);
162#ifdef _DEBUG
163 printf("Middle OMF2 momentum pp[0]=%e\n", pp[0]);
164 #endif
165
166 //Second gauge update
167 Gauge_Update(dU,pp,ut,ut_f);
168
169 //Calculate force for second momentum update
170 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
171
172 //if(step>=stepl*4.0/5.0 && (step>=stepl*(6.0/5.0) || Par_granf()<proby)){
173 if(step==stepl){
174 //Final momentum step
175 Momentum_Update(dp,dSdpi,pp);
176#ifdef _DEBUG
177 printf("Final OMF2 momentum pp[0]=%e\n", pp[0]);
178 #endif
179 *itot+=step;
180 //Two force terms, so an extra factor of two in the average?
181 //Or leave it as it was, to get the average CG iterations per trajectory rather than force
182 *ancg/=step;
183 end_traj=true;
184 break;
185 }
186 else{
187 //Since we apply the momentum at the start and end of a step we instead apply a double step here
188 Momentum_Update(dp2,dSdpi,pp);
189 step++;
190 }
191 }while(!end_traj);
192 return 0;
193}
194int OMF4(Complex *ut[2],Complex_f *ut_f[2],Complex *X0,Complex *X1, Complex *Phi,double *dk[2],float *dk_f[2],
195 double *dSdpi,double *pp, int *iu,int *id, Complex *gamval, Complex_f *gamval_f, int *gamin, Complex jqq,
196 float beta, float akappa, int stepl, float dt, double *ancg, int *itot, float proby)
197{
198 //These values were lifted from openqcd-fastsum, and should probably be tuned for QC2D. They also probably never
199 //will be...
200 const double r1 = 0.08398315262876693;
201 const double r2 = 0.2539785108410595;
202 const double r3 = 0.6822365335719091;
203 const double r4 = -0.03230286765269967;
206 const double dpO= -r1*dt;
207 const double dpO2= 2*dpO;
209 const double dpM= -r3*dt;
211 const double dpI= -(0.5-r1-r3)*dt;
212
215 const double duO = dt*r2;
217 const double duM = dt*r4;
219 const double duI = dt*(1-2*(r2+r4));
220
221 //Initial step forward for p
222 //=======================
223#ifdef _DEBUG
224 printf("Evaluating force on rank %i\n", rank);
225#endif
226 Force(dSdpi, 1, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
227 Momentum_Update(dpO,dSdpi,pp);
228
229 //Main loop for classical time evolution
230 //======================================
231 bool end_traj=false; int step =1;
232 // for(int step = 1; step<=stepmax; step++){
233 do{
234#ifdef _DEBUG
235 if(!rank)
236 printf("Step: %d\n", step);
237#endif
238 //First outer gauge update
239 Gauge_Update(duO,pp,ut,ut_f);
240
241 //Calculate force for first middle momentum update
242 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
243 //Now do the first middle momentum update
244 Momentum_Update(dpM,dSdpi,pp);
245
246 //First middle gauge update
247 Gauge_Update(duM,pp,ut,ut_f);
248
249 //Calculate force for first inner momentum update
250 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
251 //Now do the first inner momentum update
252 Momentum_Update(dpI,dSdpi,pp);
253
254 //Inner gauge update
255 Gauge_Update(duI,pp,ut,ut_f);
256
257 //Calculate force for second inner momentum update
258 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
259 //Now do the second inner momentum update
260 Momentum_Update(dpI,dSdpi,pp);
261
262 //Second middle gauge update
263 Gauge_Update(duM,pp,ut,ut_f);
264
265 //Calculate force for second middle momentum update
266 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
267 //Now do the second middle momentum update
268 Momentum_Update(dpM,dSdpi,pp);
269
270 //Second outer gauge update
271 Gauge_Update(duO,pp,ut,ut_f);
272
273 //Calculate force for outer momentum update
274 Force(dSdpi, 0, rescgg,X0,X1,Phi,ut,ut_f,iu,id,gamval,gamval_f,gamin,dk,dk_f,jqq,akappa,beta,ancg);
275
276 //Outer momentum update depends on if we've finished the trajectory
277 //if(step>=stepl*4.0/5.0 && (step>=stepl*(6.0/5.0) || Par_granf()<proby)){
278 if(step==stepl){
279 //Final momentum step
280 Momentum_Update(dpO,dSdpi,pp);
281 *itot+=step;
282
283 //Four force terms, so an extra factor of four in the average?
284 //Or leave it as it was, to get the average CG iterations per trajectory rather than force
285 *ancg/=step;
286 end_traj=true;
287 break;
288 }
289 else{
290 //Since we apply the momentum at the start and end of a step we instead apply a double step here
291 Momentum_Update(dpO2,dSdpi,pp);
292 step++;
293 }
294 }while(!end_traj);
295 return 0;
296}
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, int *iu, int *id, Complex *gamval, Complex_f *gamval_f, int *gamin, Complex jqq, float beta, float akappa, int stepl, float dt, double *ancg, int *itot, float proby)
OMF second order five step integrator.
Definition integrate.c:116
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, int *iu, int *id, Complex *gamval, Complex_f *gamval_f, int *gamin, Complex jqq, float beta, float akappa, int stepl, float dt, double *ancg, int *itot, 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...
Definition integrate.c:65
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, int *iu, int *id, Complex *gamval, Complex_f *gamval_f, int *gamin, Complex jqq, float beta, float akappa, int stepl, float dt, double *ancg, int *itot, float proby)
OMF fourth order eleven step integrator.
Definition integrate.c:194
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:7
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:53
int rank
The MPI rank.
Definition par_mpi.c:22
int Trial_Exchange(Complex *ut[2], Complex_f *ut_f[2])
Exchanges the trial fields.
Definition par_mpi.c:1178
#define rescgg
Conjugate gradient residue for update.
Definition sizes.h:240
#define kmom
sublattice momentum sites
Definition sizes.h:184
#define nadj
adjacent spatial indices
Definition sizes.h:175
#define kvol
Sublattice volume.
Definition sizes.h:154
#define Complex
Double precision complex number.
Definition sizes.h:58
#define Complex_f
Single precision complex number.
Definition sizes.h:56
#define ndim
Dimensions.
Definition sizes.h:179
Function declarations for most of the routines.
int Force(double *dSdpi, int 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, Complex_f *gamval_f, int *gamin, double *dk[2], float *dk_f[2], Complex_f jqq, float akappa, float beta, double *ancg)
Calculates the force at each intermediate time.
Definition force.c:94
int Reunitarise(Complex *ut[2])
Reunitarises u11t and u12t as in conj(u11t[i])*u11t[i]+conj(u12t[i])*u12t[i]=1.
Definition matrices.c:1012