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