Bridge++  Ver. 1.1.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hmc_Leapfrog.cpp
Go to the documentation of this file.
1 
14 #include "hmc_Leapfrog.h"
15 
16 #ifdef USE_PARAMETERS_FACTORY
17 #include "parameters_factory.h"
18 #endif
19 
20 //- parameter entries
21 namespace {
22  void append_entry(Parameters& param)
23  {
24  param.Register_double("step_size", 0.0);
25  param.Register_int("number_of_steps", 0);
26  param.Register_int("order_of_exp_iP", 0);
27  param.Register_int("Metropolis_test", 0);
28 
29  param.Register_string("verbose_level", "NULL");
30  }
31 
32 
33 #ifdef USE_PARAMETERS_FACTORY
34  bool init_param = ParametersFactory::Register("HMC.Leapfrog", append_entry);
35 #endif
36 }
37 //- end
38 
39 //- parameters class
41 //- end
42 
43 //====================================================================
45 {
46  const string str_vlevel = params.get_string("verbose_level");
47 
48  m_vl = vout.set_verbose_level(str_vlevel);
49 
50  //- fetch and check input parameters
51  double Estep;
52  int Nmdc, Nprec, Mtpl_test;
53 
54  int err = 0;
55  err += params.fetch_double("step_size", Estep);
56  err += params.fetch_int("number_of_steps", Nmdc);
57  err += params.fetch_int("order_of_exp_iP", Nprec);
58  err += params.fetch_int("Metropolis_test", Mtpl_test);
59 
60  if (err) {
61  vout.crucial(m_vl, "HMC_Leapfrog: fetch error, input parameter not found.\n");
62  abort();
63  }
64 
65 
66  set_parameters(Estep, Nmdc, Nprec, Mtpl_test);
67 }
68 
69 
70 //====================================================================
71 void HMC_Leapfrog::set_parameters(double Estep, int Nmdc, int Nprec, int Mtpl_test)
72 {
73  //- print input parameters
74  vout.general(m_vl, "HMC (single leapfrog) setup.\n");
75  vout.general(m_vl, " Number of actions: %d\n", m_action.size());
76  vout.general(m_vl, " Estep = %10.6f\n", Estep);
77  vout.general(m_vl, " Nmdc = %d\n", Nmdc);
78  vout.general(m_vl, " Nprec = %d\n", Nprec);
79  vout.general(m_vl, " Mtpl_test = %d\n", Mtpl_test);
80 
81  //- range check
82  // NB. Estep,Nmdc,Nprec,Mtpl_test == 0 is allowed.
83 
84  //- store values
85  m_Estep = Estep; // step size (SA)
86  m_Nmdc = Nmdc; // a number of steps (SA)
87  m_Nprec = Nprec; // order of approximation for e^{iP} (SA)
88  m_Mtpl_test = Mtpl_test; // Metropolis test on/off (SA)
89 }
90 
91 
92 //====================================================================
93 double HMC_Leapfrog::update(Field_G& conf_org)
94 {
95  int Nc = CommonParameters::Nc(); //color (SA)
96  int Lvol = CommonParameters::Lvol(); // global volume (SA)
97 
98  Field_G U(conf_org); // set original gauge conf. to U (SA)
99 
100  for (int i = 0; i < m_action.size(); ++i) {
101  m_action[i]->set_config(&U); // set gauge conf. for each action (SA)
102  }
103 
104  int Nin = U.nin(); // 2x(complex) 3(color) x 3(color) part (SA)
105  int Nvol = U.nvol(); // local volume (SA)
106  int Nex = U.nex(); // direction mu (SA)
107 
108  Field_G iP(Nvol, Nex); // define momentum iP for gauge fields (SA)
109 
110 
111  vout.general(m_vl, "HMC (single leapfrog) start.\n");
112 
113  //- Langevin step
114  double H_tot0 = langevin(iP, U); // calculate initial hamiltonian (SA)
115  // H=p^2/s + S_G + all fermion contributions (SA)
116  vout.general(m_vl, " H_tot(init) = %18.8f\n", H_tot0);
117 
118  double plaq0 = m_staple->plaquette(U); // calculate plaquette of old U (SA)
119  vout.general(m_vl, " plaq(init) = %18.8f\n", plaq0);
120 
121  //- initial Hamiltonian
122  // H_tot0 = calc_Hamiltonian(iP,U);
123 
124  //- molecular dynamical integration
125  integrate(iP, U); // MD step (SA)
126 
127  //- final Hamiltonian
128  double H_tot1 = calc_Hamiltonian(iP, U); // calculate final hamiltonian (SA)
129  vout.general(m_vl, " H_tot(fin) = %18.8f\n", H_tot1);
130 
131  double plaq1 = m_staple->plaquette(U); // calculate plaquette of new U (SA)
132  vout.general(m_vl, " plaq(fin) = %18.8f\n", plaq1);
133 
134 
135  //- Metropolis test
136  vout.general(m_vl, "Metropolis test.\n");
137 
138  double diff_H = H_tot1 - H_tot0; // Delta H (SA)
139  double Arprob = exp(-diff_H); // e^{-Delta H} (SA)
140  double rn = -1.0;
141  if (m_Mtpl_test != 0) {
142  rn = m_rand->get(); // random number 0 <= rn < 1 (SA)
143  }
144  vout.general(m_vl, " H(diff) = %10.6f\n", diff_H);
145  vout.general(m_vl, " Acceptance probability = %10.6f\n", Arprob);
146  vout.general(m_vl, " Random number = %10.6f\n", rn);
147 
148  if (rn <= Arprob) { // accepted
149  vout.general(m_vl, " Accepted\n");
150  conf_org = U; // set new U to gauge conf. (SA)
151  } else { // rejected
152  vout.general(m_vl, " Rejected\n");
153  }
154 
155  return m_staple->plaquette(U);
156 }
157 
158 
159 //====================================================================
161 {
162  int Nc = CommonParameters::Nc();
163  int Lvol = CommonParameters::Lvol(); //global volume (SA)
164  int Ndim = CommonParameters::Ndim();
165  int NcA = Nc * Nc - 1; // Nc^2-1 (SA)
166 
167  int size_iP = NcA * Lvol * Ndim; // global size of momentum iP (SA)
168 
169  vout.general(m_vl, "Langevin step.\n");
170 
171  for (int i = 0; i < m_action.size(); ++i) {
172  m_action[i]->notify_linkv(); // tell action that gauge field is modified.(SA)
173  }
174 
175  for (int i = 0; i < m_director.size(); ++i) {
176  m_director[i]->notify_linkv(); // tell director that gauge filed is modified.(SA)
177  }
178 
179  //- kinetic term
180  double H_iP = langevin_P(iP); // calculate hamiltonian of momenta iP. (SA)
181  vout.general(m_vl, " H_kin = %18.8f\n", H_iP);
182  vout.general(m_vl, " H_kin/dof = %18.8f\n", H_iP / size_iP);
183 
184 
185  double H_actions = 0.0;
186  for (int i = 0; i < m_action.size(); ++i) {
187  H_actions += m_action[i]->langevin(m_rand);
188  // calculate contribution to hamiltonian from each action. (SA)
189  }
190 
191  double H_tot = H_iP + H_actions; // total hamiltonian. (SA)
192  return H_tot;
193 }
194 
195 
196 //====================================================================
198 {
199  int Nin = iP.nin();
200  int Nvol = iP.nvol(); // local volume (SA)
201  int Nex = iP.nex();
202 
203  int Nc = CommonParameters::Nc();
204  int NcA = Nc * Nc - 1;
205 
206  // confirm that now gauge group is SU(3)
207  assert(NcA == 8);
208 
209  Field Hrand(NcA, Nvol, Nex); // Local random number (SA)
210 
211  m_rand->gauss_lex_global(Hrand); // generate gaussian random number Hrand. (SA)
212 
213  double sq3r = 1.0 / sqrt(3.0);
214  double sq3r2 = 2.0 * sq3r;
215 
216  for (int ex = 0; ex < Nex; ++ex) {
217  for (int site = 0; site < Nvol; ++site) {
218  //here SU(3) is explicitly assumed. need to generalize.
219  // return (jin,site,ex) component(double) of Hrand. (SA)
220  double hc1 = Hrand.cmp(0, site, ex);
221  double hc2 = Hrand.cmp(1, site, ex);
222  double hc3 = Hrand.cmp(2, site, ex);
223  double hc4 = Hrand.cmp(3, site, ex);
224  double hc5 = Hrand.cmp(4, site, ex);
225  double hc6 = Hrand.cmp(5, site, ex);
226  double hc7 = Hrand.cmp(6, site, ex);
227  double hc8 = Hrand.cmp(7, site, ex);
228 
229  /*
230  iP = i P^a T^a: T^a: Gellmann matrix
231  P=
232  | hc3+hc8/sqrt(3), hc1-i*hc2, hc4-i*hc5 |
233  | hc1+i*hc2, -hc3+hc8/sqrt(3), hc6-i*hc7 |
234  | hc4+i*hc5, hc6+i*hc7, -2*hc8/sqrt(3) |
235  */
236  iP.set(0, site, ex, 0.0);
237  iP.set(1, site, ex, hc3 + hc8 * sq3r);
238  iP.set(2, site, ex, hc2);
239  iP.set(3, site, ex, hc1);
240  iP.set(4, site, ex, hc5);
241  iP.set(5, site, ex, hc4);
242  iP.set(6, site, ex, -hc2);
243  iP.set(7, site, ex, hc1);
244  iP.set(8, site, ex, 0.0);
245  iP.set(9, site, ex, -hc3 + hc8 * sq3r);
246  iP.set(10, site, ex, hc7);
247  iP.set(11, site, ex, hc6);
248  iP.set(12, site, ex, -hc5);
249  iP.set(13, site, ex, hc4);
250  iP.set(14, site, ex, -hc7);
251  iP.set(15, site, ex, hc6);
252  iP.set(16, site, ex, 0.0);
253  iP.set(17, site, ex, -hc8 * sq3r2);
254  }
255  }
256 
257  double iP2 = iP.norm(); //calculate global norm sqrt(|iP2|^2) (SA)
258  iP2 = 0.5 * iP2 * iP2; // |iP|^2/2 (SA)
259 
260  return iP2;
261 }
262 
263 
264 //====================================================================
266 {
267  int Nin = U.nin(); // Local volume (SA)
268  int Nvol = U.nvol();
269  int Nex = U.nex();
270 
271  int Nc = CommonParameters::Nc();
272  int Nd = CommonParameters::Nd();
273  int Lvol = CommonParameters::Lvol(); //Global volume (SA)
274  int NcA = Nc * Nc - 1;
275 
276  int size_iP = NcA * Lvol * Nex; // Global size of iP (SA)
277  int size_U = Lvol * 6.0; // Global size of U (SA)
278  int size_psf = Lvol * Nc * Nd; // Global size of pseudo-fermion (SA)
279 
280 
281  vout.general(m_vl, "Hamiltonian calculation.\n");
282 
283  // kinetic term
284  double H_iP = calcH_P(iP); // calculate hamiltonian for iP (SA)
285  vout.general(m_vl, " H_kin = %18.8f\n", H_iP);
286  vout.general(m_vl, " H_kin/dof = %18.8f\n", H_iP / size_iP);
287 
288  double H_actions = 0.0;
289  for (int i = 0; i < m_action.size(); ++i) {
290  // calculate contribution to hamiltonian from each action (SA)
291  H_actions += m_action[i]->calcH();
292  }
293 
294  double H_tot = H_iP + H_actions;
295  return H_tot;
296 }
297 
298 
299 //====================================================================
301 {
302  //calculate hamiltonian for iP: |iP|^2/2 (SA)
303  double hn = iP.norm();
304  double H_iP = 0.5 * hn * hn;
305 
306  return H_iP;
307 }
308 
309 
310 //====================================================================
312 {
313  vout.general(m_vl, "Integration.\n");
314 
315  double estep = m_Estep;
316  double estep2 = 0.5 * m_Estep;
317 
318  // Initial half step of update of h
319  if (m_Nmdc > 0) {
320  int imdc = 0;
321  vout.general(m_vl, " imdc = %d\n", imdc);
322  update_P(estep2, iP, U); // update momentum iP at first half step (SA)
323  }
324 
325  // Molecular dynamics step
326  for (int imdc = 1; imdc < m_Nmdc + 1; imdc++) {
327  vout.general(m_vl, " imdc = %d\n", imdc);
328 
329  update_U(estep, iP, U); // update gauge field U at full step (SA)
330 
331  if (imdc < m_Nmdc) {
332  update_P(estep, iP, U); // update momentum iP at full step (SA)
333  } else {
334  update_P(estep2, iP, U); // update momentum iP at last half step (SA)
335  }
336  } // here imdc loop ends
337 }
338 
339 
340 //====================================================================
341 void HMC_Leapfrog::update_P(double estep, Field_G& iP, Field_G& U)
342 {
343  int Nin = U.nin();
344  int Nvol = U.nvol();
345  int Nex = U.nex();
346  int Nc = CommonParameters::Nc();
347 
348  Field force(Nin, Nvol, Nex);
349 
350  force = 0.0;
351 
352  Field force1(Nin, Nvol, Nex);
353  double H_actions = 0.0;
354  for (int i = 0; i < m_action.size(); ++i) {
355  force1 = m_action[i]->force(); // calculate force for each action (SA)
356  force += estep * force1;
357  }
358 
359  iP += (Field_G)force; // iP = iP + step-size * force (SA)
360 }
361 
362 
363 //====================================================================
364 void HMC_Leapfrog::update_U(double estep, Field_G& iP, Field_G& U)
365 {
366  int Nvol = U.nvol();
367  int Nex = U.nex();
368  int Nc = CommonParameters::Nc();
369 
370  Mat_SU_N u0(Nc), u1(Nc), u2(Nc);
371  Mat_SU_N h1(Nc);
372 
373  for (int ex = 0; ex < Nex; ++ex) {
374  for (int site = 0; site < Nvol; ++site) {
375  u0 = U.mat(site, ex);
376  u1 = U.mat(site, ex);
377  h1 = iP.mat(site, ex);
378 
379  for (int iprec = 0; iprec < m_Nprec; ++iprec) {
380  double exf = estep / (m_Nprec - iprec); // step_size/(N-k) (SA)
381  u2 = h1 * u1; // iP* u1 (SA)
382  u2 *= exf; // step_size*iP*u1/(N-K) (SA)
383  u1 = u2;
384  u1 += u0; // U + step_size*iP*u1/(N-K) (SA)
385  }
386  // u1 =sum_{k=0}^{N-1} (step_size * iP)^k/k!, N=m_Nprec (SA)
387  u1.reunit(); // reunitarize u1 (SA)
388  U.set_mat(site, ex, u1); // U = u1 (SA)
389  }
390  }
391 
392  for (int i = 0; i < m_action.size(); ++i) {
393  m_action[i]->notify_linkv(); // notify all actions about update of U (SA)
394  }
395 
396  for (int i = 0; i < m_director.size(); ++i) {
397  m_director[i]->notify_linkv(); // notify all directors about update of U (SA)
398  }
399 }
400 
401 
402 //====================================================================
403 //============================================================END=====