HILA
Loading...
Searching...
No Matches
suN_gauge_twist.cpp
1#include "gauge/staples.h"
2#include "gauge/stout_smear.h"
5#include "hila.h"
6#include "multicanonical.h"
7
8//#include "gauge/polyakov.h"
9
10#include <fftw3.h>
11#include <numeric>
12#include <stdio.h>
13#include <stdlib.h>
14
15// local includes
16#include "checkpoint.h"
17#include "parameters.h"
18#include "polyakov_surface.h"
19#include "twist_specific_methods.h"
20#include "utility.h"
21// /**
22// * @brief Helper function to get valid z-coordinate index
23// *
24// * @param z
25// * @return int
26// */
27// int z_ind(int z) { return (z + lattice.size(e_z)) % lattice.size(e_z); }
28
29/**
30 * @brief Measures Polyakov lines and Wilson action
31 *
32 * @tparam group
33 * @param U GaugeField to measure
34 * @param p Parameter struct
35 */
36template <typename group>
37void measure_plaq(const GaugeField<group> &U, const parameters &p) {
38
39 static bool first = true;
40
41 auto plaq = measure_plaq_with_z(
42 U, p.twist_coeff); /// (lattice.volume() * NDIM * (NDIM - 1) / 2);
43
44 if (first) {
45 print_formatted_numbers(plaq, "plaquette", true, true);
46 print_formatted_numbers(plaq, "plaquette", false, true);
47 first = false;
48 }
49 print_formatted_numbers(plaq, "plaquette", false, true);
50}
51
52/**
53 * @brief Measures Polyakov lines and Wilson action with multicanonical weights
54 *
55 * @tparam group
56 * @param U GaugeField to measure
57 * @param p Parameter struct
58 */
59template <typename group>
60void measure_plaq_multicanonical(const GaugeField<group> &U,
61 const parameters &p) {
62
63 static bool first = true;
64
65 auto plaq = measure_plaq_with_z(
66 U, p.twist_coeff); /// (lattice.volume() * NDIM * (NDIM - 1) / 2);
67
68 if (first) {
69 print_formatted_numbers(plaq, "plaquette", true, true);
70 print_formatted_numbers(plaq, "plaquette", false, true);
71 first = false;
72 }
73 print_formatted_numbers(plaq, "plaquette", false, true);
74 hila::out0 << "muca_plaquette: " << hila::muca::weight(plaq.back()) << '\n';
75}
76
77template <typename group>
78void measure_poly(const GaugeField<group> &U, const parameters &p) {
79 static bool first = true;
80 auto poly = measure_polyakov_with_z(U);
81 auto poly_abs = measure_polyakov_with_z_abs(U);
82 if (first) {
83 print_formatted_numbers(poly, "polyakov", true, true);
84 print_formatted_numbers(poly, "polyakov", false, true);
85 print_formatted_numbers(poly_abs, "polyakov abs", false, true);
86 first = false;
87 } else {
88 print_formatted_numbers(poly, "polyakov", false, true);
89 print_formatted_numbers(poly_abs, "polyakov abs", false, true);
90 }
91 hila::out0 << "polyakov last: " << poly.back() << '\n';
92 hila::out0 << "polyakov abs last: " << poly_abs.back() << '\n';
93}
94
95template <typename group>
96void measure_poly_multicanonical(const GaugeField<group> &U,
97 const parameters &p) {
98 static bool first = true;
99 auto poly = measure_polyakov_with_z(U);
100 auto poly_abs = measure_polyakov_with_z_abs(U);
101 if (first) {
102 print_formatted_numbers(poly, "polyakov", true, true);
103 print_formatted_numbers(poly, "polyakov", false, true);
104 print_formatted_numbers(poly_abs, "polyakov abs", false, true);
105 first = false;
106 } else {
107 print_formatted_numbers(poly, "polyakov", false, true);
108 print_formatted_numbers(poly_abs, "polyakov abs", false, true);
109 }
110 hila::out0 << "muca_polyakov: " << hila::muca::weight(poly_abs.back())
111 << '\n';
112}
113
114/**
115 * @brief Wrapper update function
116 * @details Updates Gauge Field one direction at a time first EVEN then ODD
117 * parity
118 *
119 * @tparam group
120 * @param U GaugeField to update
121 * @param p Parameter struct
122 * @param relax If true evolves GaugeField with over relaxation if false then
123 * with heat bath
124 */
125template <typename group>
126void update(GaugeField<group> &U, const parameters &p, bool relax) {
127 foralldir(d) {
128 for (Parity par : {EVEN, ODD}) {
129
130 update_parity_dir(U, p, par, d, relax);
131 }
132 }
133}
134
135template <typename group>
136void update_multicanonical(GaugeField<group> &U, const parameters &p, bool relax) {
137 foralldir(d) {
138 for (Parity par : {EVEN, ODD}) {
139 if (d==e_t) {
140 if (p.muca_poly) {
141 auto U_old = U;
142 update_parity_dir(U, p, par, d, relax);
143 auto OP = measure_polyakov_with_z_abs(U);
144 auto OP_old = measure_polyakov_with_z_abs(U_old);
145 //hila::out0 << "OP old: " << OP_old.back() << " OP new: " << OP.back() << std::endl;
146 if (!hila::muca::accept_reject(OP_old.back(), OP.back())) {
147 U = U_old;
148 }
149 } else if (p.muca_action) {
150 auto U_old = U;
151 update_parity_dir(U, p, par, d, relax);
152 auto OP = measure_plaq_with_z(U, p.twist_coeff);
153 auto OP_old = measure_plaq_with_z(U_old, p.twist_coeff);
154 //hila::out0 << "OP old: " << OP_old.back() << " OP new: " << OP.back() << std::endl;
155 if (!hila::muca::accept_reject(OP_old.back(), OP.back())) {
156 U = U_old;
157 }
158 }
159 } else {
160 update_parity_dir(U, p, par, d, relax);
161 }
162 }
163 }
164}
165
166/**
167 * @brief Wrapper function to updated GaugeField per direction
168 * @details Computes first staplesum, then uses computed result to evolve
169 * GaugeField either with over relaxation or heat bath
170 *
171 * @tparam group
172 * @param U GaugeField to evolve
173 * @param p parameter struct
174 * @param par Parity
175 * @param d Direction to evolve
176 * @param relax If true evolves GaugeField with over relaxation if false then
177 * with heat bath
178 */
179template <typename group>
180void update_parity_dir(GaugeField<group> &U, const parameters &p, Parity par,
181 Direction d, bool relax) {
182
183 static hila::timer hb_timer("Heatbath");
184 static hila::timer or_timer("Overrelax");
185 static hila::timer staples_timer("Staplesum");
186
187 Field<group> staples;
188
189 staples_timer.start();
190
191 // staplesum_twist(U, staples, d, p.twist_coeff,par);
192 staplesum_twist(U, staples, d, p.twist_coeff, par);
193
194 staples_timer.stop();
195
196 if (relax) {
197
198 or_timer.start();
199 onsites(par) { suN_overrelax(U[d][X], staples[X]); }
200 or_timer.stop();
201
202 } else {
203
204 hb_timer.start();
205 onsites(par) { suN_heatbath(U[d][X], staples[X], p.beta); }
206 hb_timer.stop();
207 }
208}
209
210/**
211 * @brief Evolve gauge field
212 * @details Evolution happens by means of heat bath and over relaxation. For
213 * each heatbath update (p.n_update) we update p.n_overrelax times with over
214 * relaxation.
215 *
216 * @tparam group
217 * @param U
218 * @param p
219 */
220template <typename group>
221void do_trajectory(GaugeField<group> &U, const parameters &p) {
222 auto U_old = U;
223 for (int n = 0; n < p.n_update; n++) {
224 for (int i = 0; i < p.n_overrelax; i++) {
225 update(U, p, true);
226 }
227
228 update(U, p, false);
229 }
231}
232
233/**
234 * @brief Evolve gauge field with multicanonical update
235 * @details Evolution happens by means of heat bath and over relaxation. For
236 * each heatbath update (p.n_update) we update p.n_overrelax times with over
237 * relaxation.
238 *
239 * @tparam group
240 * @param U
241 * @param p
242 */
243template <typename group>
244void do_trajectory_multicanonical(GaugeField<group> &U, const parameters &p) {
245 for (int n = 0; n < p.n_update; n++) {
246 for (int i = 0; i < p.n_overrelax; i++) {
247 update_multicanonical(U, p, true);
248 }
249
250 update_multicanonical(U, p, false);
251 }
253}
254
255/**
256 * @brief Create weight function with multicanonical method
257 *
258 * @param U Gauge field
259 * @param p Parameters struct
260 */
261void iterate_weights_multicanonical(GaugeField<mygroup> U,
262 const parameters &p) {
263
264 hila::out0 << "here also\n";
265 bool iterate_status = true;
266 while (iterate_status) {
267 for (int i = 0; i < p.muca_updates; i++) {
268 do_trajectory_multicanonical(U, p);
269 }
270 if (p.muca_action) {
271 auto OP = measure_plaq_with_z(U, p.twist_coeff);
272 hila::out0 << "Order parameter: " << OP.back() << std::endl;
273 iterate_status = hila::muca::iterate_weights(OP.back());
274 } else {
275 auto OP = measure_polyakov_with_z_abs(U);
276 hila::out0 << "Order parameter: " << abs(OP.back()) << std::endl;
277 iterate_status = hila::muca::iterate_weights(OP.back());
278 }
279 }
280 hila::muca::write_weight_function(hila::muca::generate_outfile_name());
281}
282
283int main(int argc, char **argv) {
284
285 // hila::initialize should be called as early as possible
286 hila::initialize(argc, argv);
287
288 // hila provides an input class hila::input, which is
289 // a convenient way to read in parameters from input files.
290 // parameters are presented as key - value pairs, as an example
291 // " lattice size 64, 64, 64, 64"
292 // is read below.
293 //
294 // Values are broadcast to all MPI nodes.
295 //
296 // .get() -method can read many different input types,
297 // see file "input.h" for documentation
298
299 parameters p;
300
301 hila::out0 << "SU(" << mygroup::size() << ") heat bath + overrelax update\n";
302
303 hila::input par("parameters");
304
305 CoordinateVector lsize;
306 lsize = par.get("lattice size"); // reads NDIM numbers
307
308 p.beta = par.get("beta");
309 // deltab sets system to different beta on different sides, by beta*(1 +-
310 // deltab) use for initial config generation only
311 p.deltab = par.get("delta beta fraction");
312 // trajectory length in steps
313 p.n_overrelax = par.get("overrelax steps");
314 p.n_update = par.get("updates in trajectory");
315 p.n_trajectories = par.get("trajectories");
316 p.n_thermal = par.get("thermalization");
317
318 // random seed = 0 -> get seed from time
319 long seed = par.get("random seed");
320 // save config and checkpoint
321 p.n_save = par.get("traj/saved");
322 // measure surface properties and print "profile"
323 p.config_file = par.get("config name");
324 p.twist_coeff = par.get("twist_coeff");
325 if (par.get_item("updates/profile meas", {"off", "%i"}) == 1) {
326 p.n_profile = par.get();
327 } else {
328 p.n_profile = 0;
329 }
330 if (p.n_profile) {
331 p.n_smear = par.get("smearing steps");
332 p.smear_coeff = par.get("smear coefficient");
333 p.z_smear = par.get("z smearing steps");
334 p.n_surface = par.get("traj/surface");
335 p.n_dump_polyakov = par.get("traj/polyakov dump");
336
337 if (p.n_smear.size() != p.z_smear.size()) {
339 << "Error in input file: number of values in 'smearing steps' != 'z "
340 "smearing steps'\n";
342 }
343
344 } else {
345 p.n_dump_polyakov = 0;
346 }
347 p.muca_action = par.get("muca_action");
348 p.muca_poly = par.get("muca_poly");
349 p.muca_updates = par.get("muca_updates");
350 p.measure_surface = par.get("measure_surface");
351 double initial_state = par.get("initial_state");
352
353 par.close(); // file is closed also when par goes out of scope
354
355 // setting up the lattice is convenient to do after reading
356 // the parameter
357 lattice.setup(lsize);
358 // Alloc gauge field
359
360 // U = initial_state;
361 // use negative trajectory for thermal
362 int start_traj = -p.n_thermal;
363
364 hila::timer update_timer("Updates");
365 hila::timer measure_timer("Measurements");
366 hila::timer muca_timer("Muca");
368
369
370 // We need random number here
371 if (!hila::is_rng_seeded())
372 hila::seed_random(seed);
373 foralldir(d) { onsites(ALL) U[d][X].gaussian_random(); }
374
375 restore_checkpoint(U, start_traj, p);
376
377 // muca_timer.start();
378
379 if (p.muca_action || p.muca_poly) {
380 hila::muca::initialise("muca_parameters");
381 std::ofstream MFile;
382 MFile.open("muca_measurements", std::ios_base::app);
383 iterate_weights_multicanonical(U, p);
384 }
385 // muca_timer.stop();
386
387 hila::out0 << "MEASURE start\n";
388 void (*do_trajectory_ptr)(GaugeField<mygroup> &, const parameters &);
389 void (*measure_plaquette_ptr)(const GaugeField<mygroup> &,
390 const parameters &);
391 void (*measure_polyakov_ptr)(const GaugeField<mygroup> &, const parameters &);
392 if (p.muca_action) {
393 do_trajectory_ptr = do_trajectory_multicanonical<mygroup>;
394 measure_plaquette_ptr = measure_plaq_multicanonical<mygroup>;
395 measure_polyakov_ptr = measure_poly<mygroup>;
396 } else if (p.muca_poly) {
397 do_trajectory_ptr = do_trajectory_multicanonical<mygroup>;
398 measure_plaquette_ptr = measure_plaq<mygroup>;
399 measure_polyakov_ptr = measure_poly_multicanonical<mygroup>;
400 } else {
401 do_trajectory_ptr = do_trajectory<mygroup>;
402 measure_plaquette_ptr = measure_plaq<mygroup>;
403 measure_polyakov_ptr = measure_poly<mygroup>;
404 }
405
406 for (int trajectory = start_traj; trajectory < p.n_trajectories;
407 trajectory++) {
408 double ttime = hila::gettime();
409
410 update_timer.start();
411
412 double acc = 0;
413 do_trajectory_ptr(U, p);
414
415 // put sync here in order to get approx gpu timing
416 hila::synchronize_threads();
417 update_timer.stop();
418
419 // trajectory is negative during thermalization
420 if (trajectory >= 0) {
421 measure_timer.start();
422
423 measure_plaquette_ptr(U, p);
424
425 measure_polyakov_ptr(U, p);
426
427 if (p.measure_surface)
428 measure_polyakov_surface(U, p, trajectory);
429
430 // hila::out0 << "Measure_end " << trajectory << std::endl;
431
432 measure_timer.stop();
433 }
434
435 if (p.n_save > 0 && (trajectory + 1) % p.n_save == 0) {
436 checkpoint(U, trajectory, p);
437 }
438 }
439 hila::out0 << "MEASURE end\n";
440 hila::out0 << expi(4.0 / 3.0 * M_PI) << std::endl;
442}
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
Gauge field class.
Definition gaugefield.h:22
void reunitarize_gauge()
Reunitarize Gauge Field consisting of matrices.
Definition gaugefield.h:94
static constexpr int size()
Returns size of Vector or square Matrix.
Definition matrix.h:248
hila::input - Class for parsing runtime parameter files.
Definition input.h:52
void setup(const CoordinateVector &siz)
General lattice setup.
Definition lattice.cpp:33
Complex< T > expi(T a)
Definition cmplx.h:1413
T abs(const Complex< T > &a)
Return absolute value of Complex number.
Definition cmplx.h:1187
Parity
Parity enum with values EVEN, ODD, ALL; refers to parity of the site. Parity of site (x,...
constexpr Parity EVEN
bit pattern: 001
#define foralldir(d)
Macro to loop over (all) Direction(s)
Definition coordinates.h:78
constexpr Parity ODD
bit pattern: 010
Direction
Enumerator for direction that assigns integer to direction to be interpreted as unit vector.
Definition coordinates.h:34
constexpr Parity ALL
bit pattern: 011
Checkpointing functions for saving and restoring lattice configurations.
void write_weight_function(string W_function_filename)
Reads the precomputed weight function from run_parameters struct and saves it into a file.
void initialise(const string wfile_name)
Loads parameters and weights for the multicanonical computation.
double weight(double OP)
process 0 interface to "weight function" for the user accessing the weights.
Header for model agnostic implementation of various multicanonical (muca) methods.
std::ostream out0
This writes output only from main process (node 0)
void initialize(int argc, char **argv)
Read in command line arguments. Initialise default stream and MPI communication.
void seed_random(uint64_t seed, bool device_rng=true)
Seed random generators with 64-bit unsigned value. On MPI shuffles the seed so that different MPI ran...
Definition random.cpp:86
double gettime()
Definition timing.cpp:163
bool is_rng_seeded()
Check if RNG is seeded already.
Definition random.cpp:243
void finishrun()
Normal, controlled exit - all nodes must call this. Prints timing information and information about c...
void terminate(int status)
void update(GaugeField< group > &U, const parameters &p, bool relax)
Wrapper update function.
Definition suN_gauge.cpp:73
void update_parity_dir(GaugeField< group > &U, const parameters &p, Parity par, Direction d, bool relax)
Wrapper function to updated GaugeField per direction.
void do_trajectory(GaugeField< group > &U, const parameters &p)
Evolve gauge field.
double suN_heatbath(SU< N, T > &U, const SU< N, T > &staple, double beta)
heatbath
void suN_overrelax(SU< N, T > &U, const SU< N, T > &staple)
Overrelaxation using SU(2) subgroups