HILA
Loading...
Searching...
No Matches
cs_flow.h
Go to the documentation of this file.
1/** @file cs_flow.h */
2
3#ifndef CS_FLOW_H_
4#define CS_FLOW_H_
5
6#include "hila.h"
10#include "gauge/clover_action.h"
12
13#ifdef CSFLOWACTION
14#define CSFLOWS CSFLOWACTION
15#else
16#define CSFLOWS 3
17#endif
18
19#if CSFLOWS == 1
21#elif CSFLOWS > 1
22#if CSFLOWS < 5
24#else
26#endif
27#endif
28
29#include "tools/string_format.h"
30
31
32template <typename group, typename atype = hila::arithmetic_type<group>>
33void get_cs_force(const GaugeField<group> &U, VectorField<Algebra<group>> &K) {
34 // wrapper for force computation routine to be used for constant action flow
35
36 atype eps = 1.0; // in principle need factor 2.0 here to switch from unoriented to oriented
37 // plaquettes (factor is usually absorbed in \beta, but gradient flow force
38 // is computed from action term with \beta-factor stripped off)
39 // however; it seems that in practice factor 1.0 is used.
40 // note: when switching to factor 2.0, remember to change also the stability
41 // limit in the do_gradient_flow_adapt() below
42
44
45 atype isqrt2 = 1.0/sqrt(2.0);
46
47#if CSFLOWS == 1 // Bulk-Prevention (BP)
48 get_force_bp(U, E, eps);
49#elif CSFLOWS == 2 // Luscher-Weisz (LW)
50 atype c12 = -1.0 / 12.0; // rectangle weight
51 atype c11 = 1.0 - 8.0 * c12; // plaquette weight
52 get_force_impr(U, E, eps * c11, eps * c12);
53#elif CSFLOWS == 3 // IWASAKI
54 atype c12 = -0.331; // rectangle weight
55 atype c11 = 1.0 - 8.0 * c12; // plaquette weight
56 get_force_impr(U, E, eps * c11, eps * c12);
57#elif CSFLOWS == 4 // DBW2
58 atype c12 = -1.4088; // rectangle weight
59 atype c11 = 1.0 - 8.0 * c12; // plaquette weight
60 get_force_impr(U, E, eps * c11, eps * c12);
61#elif CSFLOWS == 5 // LOG-PLAQUETTE
62 get_force_log_plaq(U, E, eps);
63#else // WILSON
64 get_force_wplaq(U, E, eps);
65#endif
66
67 foralldir(d) {
68 onsites(ALL) {
69 E[d][X] /= isqrt2 * E[d][X].norm();
70 K[d][X] -= E[d][X].dot(K[d][X]) * E[d][X];
71 K[d][X] /= isqrt2 * K[d][X].norm();
72 }
73 }
74
75 // 2/9*BP+7/9*Wilson
76 // get_force_bp(U,E,eps*2.0/9.0);
77 // get_force_wplaq_add(U,E,eps*7.0/9.0);
78};
79
80template <typename group, typename atype = hila::arithmetic_type<group>>
81atype measure_cs_s(const GaugeField<group> &U) {
82 // wrapper for gauge action computation routine
83 // (for gauge action that is used to evolve the flow)
84#if CSFLOWS == 1 // BP
85 atype res = measure_s_bp(U);
86#elif CSFLOWS == 2 // LW
87 atype c12 = -1.0 / 12.0; // rectangle weight
88 atype c11 = 1.0 - 8.0 * c12; // plaquette weight
89 atype res = measure_s_impr(U, c11, c12);
90#elif CSFLOWS == 3 // IWASAKI
91 atype c12 = -0.331; // rectangle weight
92 atype c11 = 1.0 - 8.0 * c12; // plaquette weight
93 atype res = measure_s_impr(U, c11, c12);
94#elif CSFLOWS == 4 // DBW2
95 atype c12 = -1.4088; // rectangle weight
96 atype c11 = 1.0 - 8.0 * c12; // plaquette weight
97 atype res = measure_s_impr(U, c11, c12);
98#elif CSFLOWS == 5 // LOG-PLAQUETTE
99 atype res = measure_s_log_plaq(U);
100#else // WILSON
101 atype res = measure_s_wplaq(U);
102#endif
103
104 // 2/9*BP+7/9*Wilson
105 // atype res=measure_s_bp(U,E,eps*2.0/9.0)+measure_s_wplaq(U,E,eps*7.0/9.0);
106
107 return res;
108}
109
110template <typename group, typename atype = hila::arithmetic_type<group>>
111atype measure_dE_wplaq_dt(const GaugeField<group> &U, const VectorField<Algebra<group>>& E) {
112 Reduction<double> de = 0;
113 de.allreduce(false).delayed(true);
115 K = E;
116 get_cs_force(U, K);
117 get_force_wplaq(U, Kc, -2.0);
118 foralldir(d) {
119 onsites(ALL) {
120 de += Kc[d][X].dot(K[d][X]);
121 }
122 }
123 return (atype)de.value();
124}
125
126template <typename group, typename atype = hila::arithmetic_type<group>>
127atype measure_dE_clov_dt(const GaugeField<group> &U, const VectorField<Algebra<group>> &E) {
128 Reduction<double> de = 0;
129 de.allreduce(false).delayed(true);
131 K = E;
132 get_cs_force(U, K);
133 get_force_clover(U, Kc, -2.0);
134 foralldir(d) {
135 onsites(ALL) {
136 de += Kc[d][X].dot(K[d][X]);
137 }
138 }
139 return (atype)de.value();
140}
141
142template <typename group, typename atype = hila::arithmetic_type<group>>
143atype measure_dE_log_dt(const GaugeField<group> &U, const VectorField<Algebra<group>> &E) {
144 Reduction<double> de = 0;
145 de.allreduce(false).delayed(true);
147 K = E;
148 get_cs_force(U, K);
149 get_force_log(U, Kc, -2.0);
150 foralldir(d) {
151 onsites(ALL) {
152 de += Kc[d][X].dot(K[d][X]);
153 }
154 }
155 return (atype)de.value();
156}
157
158template <typename group, typename atype = hila::arithmetic_type<group>>
159void measure_cs_flow_stuff(const GaugeField<group> &V, const VectorField<Algebra<group>> &K,
160 atype flow_t, atype t_step) {
161 // perform measurements on flowed gauge configuration V at flow time flow_t
162 // [t_step is the flow time integration step size used in last cs flow step]
163 // and print results in formatted form to standard output
164 static bool first = true;
165 if (first) {
166 // print info about used flow action
167#if CSFLOWS == 1 // BP
168 hila::out0 << "CSINFO using bulk-prevention action\n";
169#elif CSFLOWS == 2 // LW
170 hila::out0 << "CSINFO using Luscher-Weisz action\n";
171#elif CSFLOWS == 3 // IWASAKI
172 hila::out0 << "CSINFO using Iwasaki action\n";
173#elif CSFLOWS == 4 // DBW2
174 hila::out0 << "CSINFO using DBW2 action\n";
175#elif CSFLOWS == 5 // LOG-PLAQUETTE
176 hila::out0 << "cSINFO using log-plaquette action\n";
177#else // WILSON
178 hila::out0 << "CSINFO using Wilson's plaquette action\n";
179#endif
180 // print legend for flow measurement output
181 hila::out0 << "LCSFLMEAS t S-flow S-plaq E_plaq dE_plaq/dt "
182 " E_clv dE_clv/dt Qtopo_clv E_log dE_log/dt "
183 "Qtopo_log [t_step_size] [max_S-plaq]\n";
184 first = false;
185 }
186 atype slocal = measure_cs_s(V) /
187 (lattice.volume() * NDIM * (NDIM - 1) / 2); // average action per plaquette
188
189 atype max_plaq = 0;
190 atype plaq = measure_s_wplaq(V, max_plaq) /
191 (lattice.volume() * NDIM * (NDIM - 1) / 2); // average wilson plaquette action
192 atype eplaq = plaq * NDIM * (NDIM - 1) *
193 group::size(); // naive energy density (based on wilson plaquette action)
194
195 // average energy density and toplogical charge from
196 // clover definition of field strength tensor :
197 atype qtopocl, ecl;
198 measure_topo_charge_and_energy_clover(V, qtopocl, ecl);
199 ecl /= lattice.volume();
200
201 // average energy density and toplogical charge from
202 // symmetric log definition of field strength tensor :
203 atype qtopolog, elog;
204 measure_topo_charge_and_energy_log(V, qtopolog, elog);
205 elog /= lattice.volume();
206
207 // derivative of plaquette energy density w.r.t. to flow time :
208 atype deplaqdt = measure_dE_wplaq_dt(V, K) / lattice.volume();
209
210 // derivative of clover energy density w.r.t. to flow time :
211 atype declovdt = measure_dE_clov_dt(V, K) / lattice.volume();
212
213 // derivative of log energy density w.r.t. to flow time :
214 atype delogdt = measure_dE_log_dt(V, K) / lattice.volume();
215
216 // print formatted results to standard output :
217 hila::out0 << string_format("CSFLMEAS % 9.3f % 0.6e % 0.6e % 0.6e % 0.6e % 0.6e % 0.6e % 0.6e "
218 "% 0.6e % 0.6e % 0.6e [%0.3e] [%0.3e]",
219 flow_t, slocal, plaq, eplaq, deplaqdt, ecl, declovdt, qtopocl, elog,
220 delogdt, qtopolog, t_step, max_plaq)
221 << '\n';
222}
223
224template <typename group, typename atype = hila::arithmetic_type<group>>
225atype do_cs_flow_adapt(GaugeField<group> &V, VectorField<Algebra<group>> &E,
226 atype t_len, atype atol = 1.0e-6, atype rtol = 1.0e-6, atype tstep = 0.0) {
227 // constant action flow integration from flow scale l_start to l_end using 3rd order
228 // 3-step Runge-Kutta (RK3) from arXiv:1006.4518 (cf. appendix C of
229 // arXiv:2101.05320 for derivation of this Runge-Kutta method)
230 // and embedded RK2 for adaptive step size
231
232 atype esp = 3.0; // expected error scaling power: err ~ step^(esp)
233 atype iesp = 1.0 / esp;
234
235 atype maxstepmf = 1.0e2; // max. growth factor of adaptive step size
236 atype minmaxreldiff = pow(maxstepmf, -esp);
237
238 // translate flow scale interval [l_start,l_end] to corresponding
239 // flow time interval [t,tmax] :
240 atype t = 0;
241 atype tmax = t_len;
242
243 atype ubstep = (tmax - t) / 3.0; // max. allowed time step
244
245 atype tatol = atol * sqrt(2.0);
246
247 // hila::out0<<"t: "<<t<<" , tmax: "<<tmax<<" , step: "<<tstep<<" , minmaxreldiff:
248 // "<<minmaxreldiff<<"\n";
249
250 // temporary variables :
251 VectorField<Algebra<group>> k1, k2, tk;
252 GaugeField<group> V2, V0;
253 Field<atype> reldiff;
254 atype maxstep;
255
256 // RK3 coefficients from arXiv:1006.4518 :
257 // correspond to standard RK3 with Butcher-tableau
258 // (cf. arXiv:2101.05320, Appendix C)
259 // 0 | 0 0 0
260 // # | 1/4 0 0
261 // # | -2/9 8/9 0
262 // -------------------------
263 // | 1/4 0 3/4
264 //
265 atype a11 = 0.25;
266 atype a21 = -17.0 / 36.0, a22 = 8.0 / 9.0;
267 atype a33 = 0.75;
268
269 // RK2 coefficients :
270 // cf. Alg. 6 and Eqn. (13)-(14) in arXiv:2101.05320 to see
271 // how these are obtained from standard RK2 with Butcher-tableau
272 // 0 | 0 0
273 // # | 1/4 0
274 // -----------------
275 // | -1 2
276 //
277 atype b21 = -1.25, b22 = 2.0;
278
279 atype step = min(tstep, ubstep); // initial step size
280
281 if (step == 0) {
282 // when using a gauge action for cs flow that is different from
283 // the one used to sample the gauge cofingurations, the initial force
284 // can be huge. Therefore, if no t_step is provided as input, the inital
285 // value for step is here adjustet so that
286 // step * <largest local force> = maxstk
287 atype maxstk = 1.0e-1;
288
289 // get max. local gauge force:
290
291 get_cs_force(V, E);
292 tk = E;
293 atype maxtk = 0.0;
294 foralldir(d) {
295 onsites(ALL) {
296 reldiff[X] = (tk[d][X].squarenorm());
297 }
298 atype tmaxtk = reldiff.max();
299 if(tmaxtk>maxtk) {
300 maxtk = tmaxtk;
301 }
302 }
303 maxtk = sqrt(0.5 * maxtk);
304
305 if (step == 0) {
306 if (maxtk > maxstk) {
307 step = min(maxstk / maxtk,
308 ubstep); // adjust initial step size based on max. force magnitude
309 hila::out0 << "CSFINFO using max. gauge force (max_X |F(X)|=" << maxtk
310 << ") to set initial flow time step size: " << step << "\n";
311 } else {
312 step = min((atype)1.0, ubstep);
313 }
314 } else if (step * maxtk > maxstk) {
315 step = min(maxstk / maxtk,
316 ubstep); // adjust initial step size based on max. force magnitude
317 hila::out0 << "CSFINFO using max. gauge force (max_X |F(X)|=" << maxtk
318 << ") to set initial flow time step size: " << step << "\n";
319 }
320 }
321
322
323 V0 = V;
324 bool stop = false;
325 tstep = step;
326 while (t < tmax && !stop) {
327 if (t + step >= tmax) {
328 step = tmax - t;
329 stop = true;
330 } else {
331 tstep = step;
332 if (t + 1.5 * step >= tmax) {
333 step = 0.501 * (tmax - t);
334 }
335 }
336 get_cs_force(V, E);
337 k1 = E;
338 foralldir(d) onsites(ALL) {
339 // first steps of RK3 and RK2 are the same :
340 V[d][X] = chexp(k1[d][X] * (step * a11)) * V[d][X];
341 }
342 get_cs_force(V, E);
343 k2 = E;
344 foralldir(d) onsites(ALL) {
345 // second step of RK2 :
346 // (tk[d][X] will be used for rel. error computation)
347 tk[d][X] = k2[d][X];
348 tk[d][X] *= (step * b22);
349 tk[d][X] += k1[d][X] * (step * b21);
350 V2[d][X] = chexp(tk[d][X]) * V[d][X];
351
352 // second step of RK3 :
353 k2[d][X] *= (step * a22);
354 k2[d][X] += k1[d][X] * (step * a21);
355 V[d][X] = chexp(k2[d][X]) * V[d][X];
356 }
357 get_cs_force(V, E);
358 k1 = E;
359 foralldir(d) onsites(ALL) {
360 // third step of RK3 :
361 k1[d][X] *= (step * a33);
362 k1[d][X] -= k2[d][X];
363 V[d][X] = chexp(k1[d][X]) * V[d][X];
364 }
365
366 // determine maximum difference between RK3 and RK2,
367 // relative to desired accuracy :
368 atype maxreldiff = 0.0;
369 foralldir(d) {
370 onsites(ALL) {
371 reldiff[X] = (V2[d][X] * V[d][X].dagger()).project_to_algebra().norm() /
372 (tatol + rtol * tk[d][X].norm() / step);
373 }
374 atype tmaxreldiff = reldiff.max();
375 if (tmaxreldiff > maxreldiff) {
376 maxreldiff = tmaxreldiff;
377 }
378 }
379
380 if (maxreldiff < 1.0) {
381 // proceed to next iteration
382 t += step;
384 V0 = V;
385 } else {
386 // repeat current iteration if step size was larger than maxstep
387 V = V0;
388 stop = false;
389 }
390
391 // determine step size to achieve desired accuracy goal :
392 if (maxreldiff > minmaxreldiff) {
393 maxstep = step * pow(maxreldiff, -iesp);
394 } else {
395 maxstep = step * maxstepmf;
396 }
397
398 // adjust step size :
399 step = min((atype)0.9 * maxstep, ubstep);
400 //hila::out0<<"t: "<<t<<" , maxreldiff: "<<maxreldiff<<" , maxstep: "
401 // <<maxstep<<" gf , step:"<<step<<"\n";
402 }
403
404 return tstep;
405}
406
407#endif
Array< n, m, T > sqrt(Array< n, m, T > a)
Square root.
Definition array.h:1039
Array< n, m, T > pow(Array< n, m, T > a, int b)
Power.
Definition array.h:1204
Definition su2.h:7
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
T max(Parity par=ALL) const
Find maximum value from Field.
Definition reduction.h:424
double norm()
Norm.
Definition field.h:1101
Gauge field class.
Definition gaugefield.h:22
void reunitarize_gauge()
Reunitarize Gauge Field consisting of matrices.
Definition gaugefield.h:94
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
Reduction & delayed(bool b=true)
deferred(bool) turns deferred on or off. By default turns on.
Definition reduction.h:148
#define foralldir(d)
Macro to loop over (all) Direction(s)
Definition coordinates.h:78
constexpr Parity ALL
bit pattern: 011
int chexp(const Matrix_t< n, m, T, MT > &mat, Matrix_t< n, m, T, MT > &omat, Mt(&pl)[n])
Calculate exp of a square matrix.
Definition matrix.h:2933
std::ostream out0
This writes output only from main process (node 0)