HILA
Loading...
Searching...
No Matches
suN_gauge_gf.cpp
1#include "hila.h"
2#include "gauge/polyakov.h"
6#include "gauge/staples.h"
10
11#ifndef NCOLOR
12#define NCOLOR 3
13#endif
14
15using ftype = double;
17
18// define a struct to hold the input parameters: this
19// makes it simpler to pass the values around
20struct parameters {
21 ftype beta; // inverse gauge coupling
22 int n_traj; // number of trajectories to generate
23 int n_therm; // number of thermalization trajectories (counts only accepted traj.)
24 int n_update; // number of heat-bath sweeps per "trajectory"
25 int n_overrelax; // number of overrelaxation sweeps between heat-batch sweeps
26 int gflow_freq; // number of trajectories between gflow measurements
27 ftype gflow_max_l; // flow scale at which gradient flow stops
28 ftype gflow_l_step; // flow scale interval between flow measurements
29 ftype gflow_a_accu; // desired absolute accuracy of gradient flow integration steps
30 ftype gflow_r_accu; // desired relative accuracy of gradient flow integration steps
31 int n_save; // number of trajectories between config. check point
32 std::string config_file;
33 ftype time_offset;
34};
35
36
37///////////////////////////////////////////////////////////////////////////////////
38// heat-bath functions
39
40/**
41 * @brief Wrapper update function
42 * @details Gauge Field update sweep with randomly chosen parities and directions
43 *
44 * @tparam group
45 * @param U GaugeField to update
46 * @param p Parameter struct
47 * @param relax If true evolves GaugeField with over relaxation if false then with heat bath
48 */
49template <typename group>
50void update(GaugeField<group> &U, const parameters &p, bool relax) {
51 for (int i = 0; i < 2 * NDIM; ++i) {
52 int tdp = hila::broadcast((int)(hila::random() * 2 * NDIM));
53 int tdir = tdp / 2;
54 int tpar = 1 + (tdp % 2);
55 //hila::out0 << " " << Parity(tpar) << " -- " << Direction(tdir);
56 update_parity_dir(U, p, Parity(tpar), Direction(tdir), relax);
57 }
58 //hila::out0 << "\n";
59}
60
61/**
62 * @brief Wrapper function to updated GaugeField per direction
63 * @details Computes first staplesum, then uses computed result to evolve GaugeField either with
64 * over relaxation or heat bath
65 *
66 * @tparam group
67 * @param U GaugeField to evolve
68 * @param p parameter struct
69 * @param par Parity
70 * @param d Direction to evolve
71 * @param relax If true evolves GaugeField with over relaxation if false then with heat bath
72 */
73template <typename group>
74void update_parity_dir(GaugeField<group> &U, const parameters &p, Parity par, Direction d,
75 bool relax) {
76
77 static hila::timer hb_timer("Heatbath");
78 static hila::timer or_timer("Overrelax");
79 static hila::timer staples_timer("Staplesum");
80
81 Field<group> staples;
82
83 staples_timer.start();
84
85 staplesum(U, staples, d, par);
86 staples_timer.stop();
87
88 if (relax) {
89
90 or_timer.start();
91
92 onsites(par) {
93#ifdef SUN_OVERRELAX_dFJ
94 suN_overrelax_dFJ(U[d][X], staples[X], p.beta);
95#else
96 suN_overrelax(U[d][X], staples[X]);
97#endif
98 }
99 or_timer.stop();
100
101 } else {
102
103 hb_timer.start();
104 onsites(par) {
105 suN_heatbath(U[d][X], staples[X], p.beta);
106 }
107 hb_timer.stop();
108 }
109}
110
111/**
112 * @brief Evolve gauge field
113 * @details Evolution happens by means of heat bath and over relaxation. For each heatbath update
114 * (p.n_update) we update on average also p.n_overrelax times with over relaxation.
115 *
116 * @tparam group
117 * @param U
118 * @param p
119 */
120template <typename group>
121void do_trajectory(GaugeField<group> &U, const parameters &p) {
122
123 for (int n = 0; n < p.n_update; n++) {
124 for (int i = 0; i <= p.n_overrelax; i++) {
125 bool relax = hila::broadcast((int)(hila::random() * (1 + p.n_overrelax)) != 0);
126 update(U, p, relax);
127 //hila::out0 << relax << "\n";
128 }
129 }
131}
132
133// heat-bath functions
134///////////////////////////////////////////////////////////////////////////////////
135// measurement functions
136
137template <typename group>
138void measure_stuff(const GaugeField<group> &U) {
139 // perform measurements on current gauge and momentum pair (U, E) and
140 // print results in formatted form to standard output
141 static bool first = true;
142 if (first) {
143 // print legend for measurement output
144 hila::out0 << "LMEAS: plaq P.real P.imag\n";
145 first = false;
146 }
147 auto plaq = measure_s_wplaq(U) / (lattice.volume() * NDIM * (NDIM - 1) / 2);
148 auto poly = measure_polyakov(U, e_t);
149 hila::out0 << string_format("MEAS % 0.6e % 0.6e % 0.6e", plaq, poly.real(), poly.imag())
150 << '\n';
151}
152
153// end measurement functions
154///////////////////////////////////////////////////////////////////////////////////
155// load/save config functions
156
157template <typename group>
158void checkpoint(const GaugeField<group> &U, int trajectory, const parameters &p) {
159 double t = hila::gettime();
160 // name of config with extra suffix
161 std::string config_file =
162 p.config_file + "_" + std::to_string(abs((trajectory + 1) / p.n_save) % 2);
163 // save config
164 U.config_write(config_file);
165 // write run_status file
166 if (hila::myrank() == 0) {
167 std::ofstream outf;
168 outf.open("run_status", std::ios::out | std::ios::trunc);
169 outf << "trajectory " << trajectory + 1 << '\n';
170 outf << "seed " << static_cast<uint64_t>(hila::random() * (1UL << 61)) << '\n';
171 outf << "time " << hila::gettime() << '\n';
172 // write config name to status file:
173 outf << "config name " << config_file << '\n';
174 outf.close();
175 }
176 std::stringstream msg;
177 msg << "Checkpointing, time " << hila::gettime() - t;
178 hila::timestamp(msg.str().c_str());
179}
180
181template <typename group>
182bool restore_checkpoint(GaugeField<group> &U, int &trajectory, parameters &p) {
183 uint64_t seed;
184 bool ok = true;
185 p.time_offset = 0;
186 hila::input status;
187 if (status.open("run_status", false, false)) {
188 hila::out0 << "RESTORING FROM CHECKPOINT:\n";
189 trajectory = status.get("trajectory");
190 seed = status.get("seed");
191 p.time_offset = status.get("time");
192 // get config name with suffix from status file:
193 std::string config_file = status.get("config name");
194 status.close();
195 hila::seed_random(seed);
196 U.config_read(config_file);
197 ok = true;
198 } else {
199 std::ifstream in;
200 in.open(p.config_file, std::ios::in | std::ios::binary);
201 if (in.is_open()) {
202 in.close();
203 hila::out0 << "READING initial config\n";
204 U.config_read(p.config_file);
205 ok = true;
206 } else {
207 ok = false;
208 }
209 }
210 return ok;
211}
212
213// end load/save config functions
214///////////////////////////////////////////////////////////////////////////////////
215
216
217int main(int argc, char **argv) {
218
219 // hila::initialize should be called as early as possible
220 hila::initialize(argc, argv);
221
222 // hila provides an input class hila::input, which is
223 // a convenient way to read in parameters from input files.
224 // parameters are presented as key - value pairs, as an example
225 // " lattice size 64, 64, 64, 64"
226 // is read below.
227 //
228 // Values are broadcast to all MPI nodes.
229 //
230 // .get() -method can read many different input types,
231 // see file "input.h" for documentation
232
233 hila::out0 << "SU(" << mygroup::size() << ") heat-bath with overrelaxation\n";
234
235 hila::out0 << "Using floating point epsilon: " << fp<ftype>::epsilon << "\n";
236
237 parameters p;
238
239 hila::input par("parameters");
240
241 CoordinateVector lsize;
242 // reads NDIM numbers
243 lsize = par.get("lattice size");
244 // inverse gauge coupling
245 p.beta = par.get("beta");
246 // number of trajectories
247 p.n_traj = par.get("number of trajectories");
248 // number of heat-bath (HB) sweeps per trajectory
249 p.n_update = par.get("updates in trajectory");
250 // number of overrelaxation sweeps petween HB sweeps
251 p.n_overrelax = par.get("overrelax steps");
252 // number of thermalization trajectories
253 p.n_therm = par.get("thermalization trajs");
254 // wilson flow frequency (number of traj. between w. flow measurement)
255 p.gflow_freq = par.get("gflow freq");
256 // wilson flow max. flow-distance
257 p.gflow_max_l = par.get("gflow max lambda");
258 // wilson flow flow-distance step size
259 p.gflow_l_step = par.get("gflow lambda step");
260 // wilson flow absolute accuracy (per integration step)
261 p.gflow_a_accu = par.get("gflow abs. accuracy");
262 // wilson flow relative accuracy (per integration step)
263 p.gflow_r_accu = par.get("gflow rel. accuracy");
264 // random seed = 0 -> get seed from time
265 long seed = par.get("random seed");
266 // save config and checkpoint
267 p.n_save = par.get("trajs/saved");
268 // measure surface properties and print "profile"
269 p.config_file = par.get("config name");
270
271 par.close(); // file is closed also when par goes out of scope
272
273 // set up the lattice
274 lattice.setup(lsize);
275
276 // We need random number here
277 hila::seed_random(seed);
278
279 // Alloc gauge field and momenta (E)
282
283 // use negative trajectory for thermal
284 int start_traj = -p.n_therm;
285
286 if (!restore_checkpoint(U, start_traj, p)) {
287 U = 1;
288 }
289
290
291 hila::timer update_timer("Updates");
292 hila::timer measure_timer("Measurements");
293 hila::timer gf_timer("Gradient Flow");
294
295 ftype t_step0 = 0;
296 for (int trajectory = start_traj; trajectory < p.n_traj; ++trajectory) {
297
298 ftype ttime = hila::gettime();
299
300 update_timer.start();
301
302 do_trajectory(U, p);
303
304 // put sync here in order to get approx gpu timing
305 hila::synchronize_threads();
306 update_timer.stop();
307
308 measure_timer.start();
309
310 hila::out0 << "Measure_start " << trajectory << '\n';
311
312 measure_stuff(U);
313
314 hila::out0 << "Measure_end " << trajectory << '\n';
315
316 measure_timer.stop();
317
318 if (trajectory >= 0) {
319
320 if (p.gflow_freq > 0 && trajectory % p.gflow_freq == 0) {
321
322
323 int gtrajectory = trajectory / p.gflow_freq;
324 if (p.gflow_l_step > 0) {
325
326 gf_timer.start();
327
328 int nflow_steps = (int)(p.gflow_max_l / p.gflow_l_step);
329 ftype gftime = hila::gettime();
330 hila::out0 << "Gflow_start " << gtrajectory << '\n';
331
333
334 ftype t_step = t_step0;
335 measure_gradient_flow_stuff(V, (ftype)0.0, t_step);
336 t_step = do_gradient_flow_adapt(V, (ftype)0.0, p.gflow_l_step, p.gflow_a_accu,
337 p.gflow_r_accu, t_step);
338 measure_gradient_flow_stuff(V, p.gflow_l_step, t_step);
339 t_step0 = t_step;
340
341 for (int i = 1; i < nflow_steps; ++i) {
342
343 t_step =
344 do_gradient_flow_adapt(V, i * p.gflow_l_step, (i + 1) * p.gflow_l_step,
345 p.gflow_a_accu, p.gflow_r_accu, t_step);
346
347 measure_gradient_flow_stuff(V, (i + 1) * p.gflow_l_step, t_step);
348 }
349
350 hila::out0 << "Gflow_end " << gtrajectory << " time " << std::setprecision(3)
351 << hila::gettime() - gftime << '\n';
352
353 gf_timer.stop();
354 }
355 }
356 }
357
358 if (p.n_save > 0 && (trajectory + 1) % p.n_save == 0) {
359 checkpoint(U, trajectory, p);
360 }
361 }
362
364}
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
void config_write(const std::string &filename) const
config_write writes the gauge field to file, with additional "verifying" header
Definition gaugefield.h:155
static constexpr int size()
Returns size of Vector or square Matrix.
Definition matrix.h:248
Class for SU(N) matrix.
Definition sun_matrix.h:110
hila::input - Class for parsing runtime parameter files.
Definition input.h:52
void close()
Closes input parameter file.
Definition input.cpp:79
returntype get(const std::string &key)
Get next value in stack of read in input string from parameters file.
Definition input.h:269
bool open(const std::string &fname, bool use_cmdline=true, bool exit_on_error=true)
Open file that parameters are read from.
Definition input.cpp:22
void setup(const CoordinateVector &siz)
General lattice setup.
Definition lattice.cpp:33
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,...
Direction
Enumerator for direction that assigns integer to direction to be interpreted as unit vector.
Definition coordinates.h:34
double random()
Real valued uniform random number generator.
Definition hila_gpu.cpp:121
int myrank()
rank of this node
Definition com_mpi.cpp:234
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
T broadcast(T &var, int rank=0)
Broadcast the value of var to all MPI ranks from rank (default=0).
Definition com_mpi.h:152
double gettime()
Definition timing.cpp:163
void finishrun()
Normal, controlled exit - all nodes must call this. Prints timing information and information about c...
Complex< double > measure_polyakov(const GaugeField< T > &U, Direction dir=Direction(NDIM - 1))
Measure Polyakov lines to direction dir.
Definition polyakov.h:17
void staplesum(const GaugeField< T > &U, Field< T > &staples, Direction d1, Parity par=ALL)
Sum the staples of link matrices to direction dir.
Definition staples.h:28
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.
void measure_stuff(const GaugeField< group > &U, const parameters &p)
Measures Polyakov lines and Wilson action.
Definition suN_gauge.cpp:41
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