HILA
Loading...
Searching...
No Matches
suN_gauge_surface.cpp
1#include "hila.h"
2#include "gauge/staples.h"
3#include "gauge/polyakov.h"
4#include "gauge/stout_smear.h"
5
8#include "checkpoint.h"
9
10#include <fftw3.h>
11
12#ifndef NCOLOR
13#define NCOLOR 3
14#endif
15
17
18enum class poly_limit { OFF, RANGE, PARABOLIC };
19
20// define a struct to hold the input parameters: this
21// makes it simpler to pass the values around
22struct parameters {
23 double beta;
24 double deltab;
25 int n_overrelax;
26 int n_update;
27 int n_trajectories;
28 int n_thermal;
29 int n_save;
30 int n_profile;
31 std::string config_file;
32 double time_offset;
33 poly_limit polyakov_pot;
34 double poly_min, poly_max, poly_m2;
35 std::vector<int> n_smear;
36 double smear_coeff;
37 std::vector<int> z_smear;
38 int n_surface;
39 int n_dump_polyakov;
40};
41
42template <typename T>
43void staplesum_db(const GaugeField<T> &U, Field<T> &staples, Direction d1, Parity par,
44 double deltab) {
45
46 Field<T> lower;
47
48 // zero staples just in case
49 staples[par] = 0;
50
51 foralldir(d2) if (d2 != d1) {
52
53 // anticipate that these are needed
54 // not really necessary, but may be faster
55 U[d2].start_gather(d1, ALL);
56 U[d1].start_gather(d2, par);
57
58 // calculate first lower 'U' of the staple sum
59 // do it on opp parity
60 onsites(opp_parity(par)) {
61 double m;
62 if (2 * X.z() < lattice.size(e_z))
63 m = 1.0 - deltab;
64 else
65 m = 1.0 + deltab;
66
67 lower[X] = m * U[d2][X].dagger() * U[d1][X] * U[d2][X + d1];
68 }
69
70 // calculate then the upper 'n', and add the lower
71 // lower could also be added on a separate loop
72 onsites(par) {
73 double m;
74 if (2 * X.z() < lattice.size(e_z))
75 m = 1.0 - deltab;
76 else
77 m = 1.0 + deltab;
78
79 staples[X] += m * U[d2][X] * U[d1][X + d2] * U[d2][X + d1].dagger() + lower[X - d2];
80 }
81 }
82}
83
84template <typename group>
85double measure_plaq_db(const GaugeField<group> &U, double db = 0.0) {
87 plaq.allreduce(false);
88
89 foralldir(dir1) foralldir(dir2) if (dir1 < dir2) {
90 if (db == 0.0) {
91 onsites(ALL) {
92 plaq += 1.0 - real(trace(U[dir1][X] * U[dir2][X + dir1] *
93 U[dir1][X + dir2].dagger() * U[dir2][X].dagger())) /
94 group::size();
95 }
96 } else {
97 onsites(ALL) {
98 double c;
99 if (2 * X.z() < lattice.size(e_z))
100 c = 1 - db;
101 else
102 c = 1 + db;
103
104 plaq += c * (1.0 - real(trace(U[dir1][X] * U[dir2][X + dir1] *
105 U[dir1][X + dir2].dagger() * U[dir2][X].dagger())) /
106 group::size());
107 }
108 }
109 }
110 return plaq.value();
111}
112
113template <typename group>
114double measure_action(const GaugeField<group> &U, const VectorField<Algebra<group>> &E,
115 const parameters &p) {
116
117 auto plaq = measure_plaq_bp(U, p.deltab);
118
119 return p.beta * plaq;
120}
121
122/////////////////////////////////////////////////////////////////////////////
123/// Measure polyakov "field"
124///
125
126template <typename T>
127void measure_polyakov_field(const Field<T> &Ut, Field<float> &pl) {
128 Field<T> polyakov = Ut;
129
130 // mult links so that polyakov[X.dir == 0] contains the polyakov loop
131 for (int plane = lattice.size(e_t) - 2; plane >= 0; plane--) {
132
133 // safe_access(polyakov) pragma allows the expression below, otherwise
134 // hilapp would reject it because X and X+dir can refer to the same
135 // site on different "iterations" of the loop. However, here this
136 // is restricted on single dir-plane so it works but we must tell it to hilapp.
137
138#pragma hila safe_access(polyakov)
139 onsites(ALL) {
140 if (X.coordinate(e_t) == plane) {
141 polyakov[X] = Ut[X] * polyakov[X + e_t];
142 }
143 }
144 }
145
146 onsites(ALL) if (X.coordinate(e_t) == 0) {
147 pl[X] = real(trace(polyakov[X]));
148 }
149}
150
151////////////////////////////////////////////////////////////////////
152
153void smear_polyakov_field(Field<float> &pl, int nsmear, float smear_coeff) {
154
155 if (nsmear > 0) {
156 Field<float> pl2 = 0;
157
158 for (int i = 0; i < nsmear; i++) {
159 onsites(ALL) if (X.coordinate(e_t) == 0) {
160 pl2[X] = pl[X] + smear_coeff * (pl[X + e_x] + pl[X - e_x] + pl[X + e_y] +
161 pl[X - e_y] + pl[X + e_z] + pl[X - e_z]);
162 }
163
164 onsites(ALL) if (X.coordinate(e_t) == 0) {
165 pl[X] = pl2[X] / (1 + 6 * smear_coeff);
166 }
167 }
168 }
169}
170
171/////////////////////////////////////////////////////////////////////////////
172
173std::vector<float> measure_polyakov_profile(Field<float> &pl, std::vector<float> &pro1) {
174 ReductionVector<float> p(lattice.size(e_z)), p1(lattice.size(e_z));
175 p.allreduce(false);
176 p1.allreduce(false);
177 onsites(ALL) if (X.coordinate(e_t) == 0) {
178 p[X.z()] += pl[X];
179 if (X.x() == 0 && X.y() == 0)
180 p1[X.z()] += pl[X];
181 }
182 pro1 = p1.vector();
183 return p.vector();
184}
185
186
187///////////////////////////////////////////////////////////////////////////////////
188
189template <typename group>
190void measure_plaq_profile(GaugeField<group> &U) {
191 ReductionVector<float> p(lattice.size(e_z));
192 p.allreduce(false);
193 p.delayed(true);
194 foralldir(dir1) foralldir(dir2) if (dir2 > dir1) {
195 onsites(ALL) {
196 p[X.z()] += 1.0 - real(trace(U[dir1][X] * U[dir2][X + dir1] *
197 U[dir1][X + dir2].dagger() * U[dir2][X].dagger())) /
198 group::size();
199 }
200 }
201 p.reduce();
202
203 for (int z = 0; z < lattice.size(e_z); z++) {
204 hila::out0 << "PPLAQ " << z << ' '
205 << p[z] / (NDIM * (NDIM - 1) / 2 * lattice.volume() / lattice.size(e_z)) << '\n';
206 }
207}
208
209
210///////////////////////////////////////////////////////////////////////////////////
211
212template <typename group>
213void measure_stuff(const GaugeField<group> &U, const parameters &p) {
214
215 static bool first = true;
216
217 if (first) {
218 hila::out0 << "Legend:";
219 if (p.polyakov_pot == poly_limit::PARABOLIC)
220 hila::out0 << " -V(polyakov)";
221 hila::out0 << " plaq P.real P.imag\n";
222
223 first = false;
224 }
225
226 auto poly = measure_polyakov(U);
227
228 auto plaq = measure_plaq_db(U) / (lattice.volume() * NDIM * (NDIM - 1) / 2);
229
230 hila::out0 << "MEAS " << std::setprecision(14);
231
232 // write the -(polyakov potential) first, this is used as a weight factor in aa
233 if (p.polyakov_pot == poly_limit::PARABOLIC) {
234 hila::out0 << -polyakov_potential(p, poly.real()) << ' ';
235 }
236
237 hila::out0 << plaq << ' ' << poly << '\n';
238}
239
240///////////////////////////////////////////////////////////////////////////////////
241
242void spectraldensity_surface(std::vector<float> &surf, std::vector<double> &npow,
243 std::vector<int> &hits) {
244
245 // do fft for the surface
246 static bool first = true;
247 static Complex<double> *buf;
248 static fftw_plan fftwplan;
249
250 int area = lattice.size(e_x) * lattice.size(e_y);
251
252 if (first) {
253 first = false;
254
255 buf = (Complex<double> *)fftw_malloc(sizeof(Complex<double>) * area);
256
257 // note: we had x as the "fast" dimension, but fftw wants the 2nd dim to be
258 // the "fast" one. thus, first y, then x.
259 fftwplan = fftw_plan_dft_2d(lattice.size(e_y), lattice.size(e_x), (fftw_complex *)buf,
260 (fftw_complex *)buf, FFTW_FORWARD, FFTW_ESTIMATE);
261 }
262
263 for (int i = 0; i < area; i++) {
264 buf[i] = surf[i];
265 }
266
267 fftw_execute(fftwplan);
268
269 int pow_size = npow.size();
270
271 for (int i = 0; i < area; i++) {
272 int x = i % lattice.size(e_x);
273 int y = i / lattice.size(e_x);
274 x = (x <= lattice.size(e_x) / 2) ? x : (lattice.size(e_x) - x);
275 y = (y <= lattice.size(e_y) / 2) ? y : (lattice.size(e_y) - y);
276
277 int k = x * x + y * y;
278 if (k < pow_size) {
279 npow[k] += buf[i].squarenorm() / (area * area);
280 hits[k]++;
281 }
282 }
283}
284
285///////////////////////////////////////////////////////////////////////////////////
286// helper function to get valid z-coordinate index
287
288int z_ind(int z) {
289 return (z + lattice.size(e_z)) % lattice.size(e_z);
290}
291
292///////////////////////////////////////////////////////////////////////////////////
293
294template <typename group>
295void measure_polyakov_surface(GaugeField<group> &U, const parameters &p, int traj) {
296
297 Field<float> pl;
298
299
300 if (0) {
301 // this section does local sums of poly lines
302 Field<group> staples, Ut;
303
304 Ut = U[e_t];
305
306 for (int s = 0; s < 20; s++) {
307 staplesum(U, staples, e_t);
308 U[e_t][ALL] = (U[e_t][X] + 0.5 * staples[X]) / (1 + 6 * 0.5);
309 }
310
311 measure_polyakov_field(U[e_t], pl);
312
313 U[e_t] = Ut;
314
315 } else {
316 // here standard non-link integrated field
317 measure_polyakov_field(U[e_t], pl);
318 }
319
320 hila::out0 << std::setprecision(7);
321
322 std::vector<float> profile, prof1;
323
324 int prev_smear = 0;
325 for (int sl = 0; sl < p.n_smear.size(); sl++) {
326
327 int smear = p.n_smear.at(sl);
328 smear_polyakov_field(pl, smear - prev_smear, p.smear_coeff);
329 prev_smear = smear;
330
331 Field<float> plz = pl;
332 if (p.z_smear.at(sl) > 0) {
333 Field<float> pl2;
334 for (int j = 0; j < p.z_smear.at(sl); j++) {
335 onsites(ALL) if (X.coordinate(e_t) == 0) {
336 pl2[X] = plz[X] + p.smear_coeff * (plz[X + e_z] + plz[X - e_z]);
337 }
338 onsites(ALL) if (X.coordinate(e_t) == 0) {
339 plz[X] = pl2[X] / (1 + 2 * p.smear_coeff);
340 }
341 }
342 }
343
344 profile = measure_polyakov_profile(plz, prof1);
345
346 double m = 1.0 / (lattice.size(e_x) * lattice.size(e_y));
347 for (int i = 0; i < profile.size(); i++) {
348 profile[i] *= m;
349 hila::out0 << "PRO" << sl << ' ' << i << ' ' << profile[i] << ' ' << prof1[i] << '\n';
350 }
351
352 float min = 1e8, max = 0;
353 int minloc, maxloc;
354 for (int i = 0; i < profile.size(); i++) {
355 if (min > profile[i]) {
356 min = profile[i];
357 minloc = i;
358 }
359 if (max < profile[i]) {
360 max = profile[i];
361 maxloc = i;
362 }
363 }
364
365 // find the surface between minloc and maxloc
366 float surface_level = max * 0.5; // assume min is really 0
367 int area = lattice.size(e_x) * lattice.size(e_y);
368
369 hila::out0 << "Surface_level" << sl << ' ' << surface_level << '\n';
370
371 int startloc, startloc2;
372 if (maxloc > minloc)
373 startloc = (maxloc + minloc) / 2;
374 else
375 startloc = ((maxloc + minloc + lattice.size(e_z)) / 2) % lattice.size(e_z);
376
377 // starting positio for the other surface
378 startloc2 = z_ind(startloc + lattice.size(e_z) / 2);
379
380 std::vector<float> surf1, surf2;
381 if (hila::myrank() == 0) {
382 surf1.resize(area);
383 surf2.resize(area);
384 }
385
386 hila::out0 << std::setprecision(6);
387
388 std::vector<float> poly;
389 std::vector<float> line(lattice.size(e_z));
390
391 // get full xyz-volume t=0 slice to main node
392 // poly = plz.get_slice({-1, -1, -1, 0});
393
394 for (int y = 0; y < lattice.size(e_y); y++) {
395 // get now full xz-plane polyakov line to main node
396 // reduces MPI calls compared with doing line-by-line
397 poly = plz.get_slice({-1, y, -1, 0});
398 if (hila::myrank() == 0) {
399 for (int x = 0; x < lattice.size(e_x); x++) {
400 // line = plz.get_slice({x, y, -1, 0});
401
402 // copy ploop data to line - x runs fastest
403 for (int z = 0; z < lattice.size(e_z); z++) {
404 line[z] = poly[x + lattice.size(e_x) * (z)];
405 }
406
407 // if (hila::myrank() == 0) {
408 // start search of the surface from the center between min and max
409 int z = startloc;
410
411 while (line[z_ind(z)] > surface_level && startloc - z < lattice.size(e_z) * 0.4)
412 z--;
413
414 while (line[z_ind(z + 1)] <= surface_level &&
415 z - startloc < lattice.size(e_z) * 0.4)
416 z++;
417
418
419 // do linear interpolation
420 // surf[x + y * lattice.size(e_x)] = z;
421 surf1[x + y * lattice.size(e_x)] =
422 z +
423 (surface_level - line[z_ind(z)]) / (line[z_ind(z + 1)] - line[z_ind(z)]);
424
425 if (p.n_surface > 0 && (traj + 1) % p.n_surface == 0) {
426 hila::out0 << "SURF" << sl << ' ' << x << ' ' << y << ' '
427 << surf1[x + y * lattice.size(e_x)] << '\n';
428 }
429
430 // and locate the other surface - start from Lz/2 offset
431
432 z = startloc2;
433
434 while (line[z_ind(z)] <= surface_level &&
435 startloc2 - z < lattice.size(e_z) * 0.4)
436 z--;
437
438 while (line[z_ind(z + 1)] > surface_level &&
439 z - startloc2 < lattice.size(e_z) * 0.4)
440 z++;
441
442 // do linear interpolation
443 // surf[x + y * lattice.size(e_x)] = z;
444 surf2[x + y * lattice.size(e_x)] =
445 z +
446 (surface_level - line[z_ind(z)]) / (line[z_ind(z + 1)] - line[z_ind(z)]);
447 }
448 }
449 }
450
451 if (hila::myrank() == 0) {
452 constexpr int pow_size = 200;
453 std::vector<double> npow(pow_size);
454 std::vector<int> hits(pow_size);
455
456 spectraldensity_surface(surf1, npow, hits);
457 spectraldensity_surface(surf2, npow, hits);
458
459 for (int i = 0; i < pow_size; i++) {
460 if (hits[i] > 0)
461 hila::out0 << "POW" << sl << ' ' << i << ' ' << npow[i] / hits[i] << ' '
462 << hits[i] << '\n';
463 }
464 }
465 }
466}
467
468
469////////////////////////////////////////////////////////////////
470
471template <typename group>
472void update(GaugeField<group> &U, const parameters &p, bool relax) {
473
474 for (const auto &dp : hila::shuffle_directions_and_parities()) {
475
476 update_parity_dir(U, p, dp.parity, dp.direction, relax);
477 }
478}
479
480////////////////////////////////////////////////////////////////
481
482template <typename group>
483void update_parity_dir(GaugeField<group> &U, const parameters &p, Parity par, Direction d,
484 bool relax) {
485
486 static hila::timer hb_timer("Heatbath");
487 static hila::timer or_timer("Overrelax");
488 static hila::timer staples_timer("Staplesum");
489
490 Field<group> staples;
491
492 staples_timer.start();
493 if (p.deltab != 0)
494 staplesum_db(U, staples, d, par, p.deltab);
495 else
496 staplesum(U, staples, d, par);
497 staples_timer.stop();
498
499 if (relax) {
500
501 or_timer.start();
502 onsites(par) {
503#ifdef SUN_OVERRELAX_dFJ
504 suN_overrelax_dFJ(U[d][X], staples[X], p.beta);
505#else
506 suN_overrelax(U[d][X], staples[X]);
507#endif
508 }
509 or_timer.stop();
510
511 } else {
512
513 hb_timer.start();
514 onsites(par) {
515 suN_heatbath(U[d][X], staples[X], p.beta);
516 }
517 hb_timer.stop();
518 }
519}
520
521
522////////////////////////////////////////////////////////////////
523
524template <typename group>
525void do_trajectory(GaugeField<group> &U, const parameters &p) {
526
527 for (int n = 0; n < p.n_update; n++) {
528 for (int i = 0; i < p.n_overrelax; i++) {
529 update(U, p, true);
530 }
531 update(U, p, false);
532 }
534}
535
536////////////////////////////////////////////////////////////////
537
538double polyakov_potential(const parameters &p, const double poly) {
539
540 return p.poly_m2 * (sqr(poly - p.poly_min));
541}
542
543
544////////////////////////////////////////////////////////////////
545
546bool accept_polyakov(const parameters &p, const double p_old, const double p_new) {
547
548 if (p.polyakov_pot == poly_limit::PARABOLIC) {
549 double dpot = polyakov_potential(p, p_new) - polyakov_potential(p, p_old);
550
551 bool accept = hila::broadcast(hila::random() < exp(-dpot));
552
553 return accept;
554 } else {
555 if (p_new >= p.poly_min && p_new <= p.poly_max)
556 return true;
557 if (p_new > p.poly_max && p_new < p_old)
558 return true;
559 if (p_new < p.poly_min && p_new > p_old)
560 return true;
561 return false;
562 }
563}
564
565////////////////////////////////////////////////////////////////
566
567template <typename group>
568double update_once_with_range(GaugeField<group> &U, const parameters &p, double &poly, bool relax) {
569
570 Field<group> Ut_old;
571
572 Ut_old = U[e_t];
573
574 // spatial links always updated, t-links are conditional
575 // acc/rej separately for parities
576
577 foralldir(d) if (d < e_t) {
578 for (Parity par : {EVEN, ODD})
579 update_parity_dir(U, p, par, d, relax);
580 }
581
582 // t-links
583 double acc = 0;
584 for (Parity par : {EVEN, ODD}) {
585 update_parity_dir(U, p, par, e_t, relax);
586
587 double p_now = measure_polyakov(U).real();
588
589 bool acc_update = accept_polyakov(p, poly, p_now);
590
591 if (acc_update) {
592 poly = p_now;
593 acc += 0.5;
594 } else {
595 U[e_t][par] = Ut_old[X]; // restore rejected
596 }
597 }
598 return acc;
599}
600
601////////////////////////////////////////////////////////////////
602
603template <typename group>
604double trajectory_with_range(GaugeField<group> &U, const parameters &p, double &poly) {
605
606 double acc_or = 0;
607 double acc_hb = 0;
608
609 double p_now = measure_polyakov(U).real();
610
611 for (int n = 0; n < p.n_update; n++) {
612 for (int i = 0; i < p.n_overrelax; i++) {
613
614 // OR updates
615 acc_or += update_once_with_range(U, p, p_now, true);
616 }
617
618 // and then HBs
619
620 acc_hb += update_once_with_range(U, p, p_now, false);
621
623 }
624 return (acc_or + acc_hb) / (p.n_update * (p.n_overrelax + 1));
625}
626
627/////////////////////////////////////////////////////////////////
628
629
630int main(int argc, char **argv) {
631
632 // hila::initialize should be called as early as possible
633 hila::initialize(argc, argv);
634
635 // hila provides an input class hila::input, which is
636 // a convenient way to read in parameters from input files.
637 // parameters are presented as key - value pairs, as an example
638 // " lattice size 64, 64, 64, 64"
639 // is read below.
640 //
641 // Values are broadcast to all MPI nodes.
642 //
643 // .get() -method can read many different input types,
644 // see file "input.h" for documentation
645
646 parameters p;
647
648 hila::out0 << "SU(" << mygroup::size() << ") heat bath + overrelax update\n";
649
650 hila::input par("parameters");
651
652 CoordinateVector lsize;
653 lsize = par.get("lattice size"); // reads NDIM numbers
654
655 p.beta = par.get("beta");
656 // deltab sets system to different beta on different sides, by beta*(1 +- deltab)
657 // use for initial config generation only
658 p.deltab = par.get("delta beta fraction");
659 // trajectory length in steps
660 p.n_overrelax = par.get("overrelax steps");
661 p.n_update = par.get("updates in trajectory");
662 p.n_trajectories = par.get("trajectories");
663 p.n_thermal = par.get("thermalization");
664
665 // random seed = 0 -> get seed from time
666 uint64_t seed = par.get("random seed");
667 // save config and checkpoint
668 p.n_save = par.get("traj/saved");
669 // measure surface properties and print "profile"
670 p.config_file = par.get("config name");
671
672 // if polyakov range is off, do nothing with
673 int p_item = par.get_item("polyakov potential", {"off", "min", "range"});
674 if (p_item == 0) {
675 p.polyakov_pot = poly_limit::OFF;
676 } else if (p_item == 1) {
677 p.polyakov_pot = poly_limit::PARABOLIC;
678 p.poly_min = par.get();
679 p.poly_m2 = par.get("mass2");
680 } else {
681 p.polyakov_pot = poly_limit::RANGE;
683 r = par.get();
684 p.poly_min = r[0];
685 p.poly_max = r[1];
686 }
687
688 if (par.get_item("updates/profile meas", {"off", "%i"}) == 1) {
689 p.n_profile = par.get();
690 } else {
691 p.n_profile = 0;
692 }
693
694 if (p.n_profile) {
695 p.n_smear = par.get("smearing steps");
696 p.smear_coeff = par.get("smear coefficient");
697 p.z_smear = par.get("z smearing steps");
698 p.n_surface = par.get("traj/surface");
699 p.n_dump_polyakov = par.get("traj/polyakov dump");
700
701 if (p.n_smear.size() != p.z_smear.size()) {
702 hila::out0 << "Error in input file: number of values in 'smearing steps' != 'z "
703 "smearing steps'\n";
705 }
706
707 } else {
708 p.n_dump_polyakov = 0;
709 }
710
711 par.close(); // file is closed also when par goes out of scope
712
713 // setting up the lattice is convenient to do after reading
714 // the parameter
715 lattice.setup(lsize);
716
717 // Alloc gauge field
719
720 U = 1;
721
722 // use negative trajectory for thermal
723 int start_traj = -p.n_thermal;
724
725 hila::timer update_timer("Updates");
726 hila::timer measure_timer("Measurements");
727
728 restore_checkpoint(U, p.config_file, p.n_trajectories, start_traj);
729
730 // We need random number here
731 if (!hila::is_rng_seeded())
732 hila::seed_random(seed);
733
734 double p_now = measure_polyakov(U).real();
735
736 for (int trajectory = start_traj; trajectory < p.n_trajectories; trajectory++) {
737
738 double ttime = hila::gettime();
739
740 update_timer.start();
741
742 double acc = 0;
743 if (p.polyakov_pot != poly_limit::OFF) {
744 acc += trajectory_with_range(U, p, p_now);
745 } else {
746 do_trajectory(U, p);
747 }
748
749 // put sync here in order to get approx gpu timing
750 hila::synchronize_threads();
751 update_timer.stop();
752
753 // trajectory is negative during thermalization
754 if (trajectory >= 0) {
755 measure_timer.start();
756
757 hila::out0 << "Measure_start " << trajectory << '\n';
758
759 measure_stuff(U, p);
760
761 if (p.n_profile && (trajectory + 1) % p.n_profile == 0) {
762 measure_polyakov_surface(U, p, trajectory);
763 measure_plaq_profile(U);
764 }
765
766 if (p.n_dump_polyakov && (trajectory + 1) % p.n_dump_polyakov == 0) {
767 Field<float> pl;
768 std::ofstream poly;
769 if (hila::myrank() == 0) {
770 poly.open("polyakov", std::ios::out | std::ios::app);
771 }
772 measure_polyakov_field(U[e_t], pl);
773 pl.write_slice(poly, {-1, -1, -1, 0});
774 }
775
776 if (p.polyakov_pot != poly_limit::OFF) {
777 hila::out0 << "ACCP " << acc << '\n';
778 }
779
780 hila::out0 << "Measure_end " << trajectory << std::endl;
781
782 measure_timer.stop();
783 }
784
785 if (p.n_save > 0 && (trajectory + 1) % p.n_save == 0) {
786 checkpoint(U, p.config_file, p.n_trajectories, trajectory);
787 }
788 }
789
791}
Array< n, m, T > exp(Array< n, m, T > a)
Exponential.
Definition array.h:1059
Array< n, m, hila::arithmetic_type< T > > real(const Array< n, m, T > &arg)
Return real part of Array.
Definition array.h:688
Definition su2.h:7
Complex definition.
Definition cmplx.h:56
T squarenorm() const
Compute square norm of Complex number.
Definition cmplx.h:248
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
std::vector< T > get_slice(const CoordinateVector &c, bool broadcast=false) const
and get a slice (subvolume)
Definition field_comm.h:703
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
Matrix class which defines matrix operations.
Definition matrix.h:1620
Special reduction class: enables delayed and non-blocking reductions, which are not possible with the...
Definition reduction.h:14
const T value()
Return value of the reduction variable. Wait for the comms if needed.
Definition reduction.h:157
Reduction & allreduce(bool b=true)
allreduce(bool) turns allreduce on or off. By default on.
Definition reduction.h:130
Class for SU(N) matrix.
Definition sun_matrix.h:110
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 > dagger(const Complex< T > &val)
Return dagger of Complex number.
Definition cmplx.h:1223
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
constexpr T sqr(const T &arg)
Define convenience function sqr(), returning square of argument.
Definition defs.h:154
Implement hila::swap for gauge fields.
Definition array.h:981
auto shuffle_directions_and_parities()
Definition shuffle.h:49
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
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)
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.
int z_ind(int z)
Helper function to get valid z-coordinate index.
Definition suN_gauge.cpp:29
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