HILA
Loading...
Searching...
No Matches
gauge_field.h
1#ifndef GAUGE_FIELD_H
2#define GAUGE_FIELD_H
3
4#include "hila.h"
5#include "datatypes/sun.h"
6#include "datatypes/representations.h"
7#include "integrator.h"
8
9/// Define a standard base gauge class. Gauge field types (represented,
10/// smeared, etc) inherit from this
11template <typename sun> class gauge_field_base {
12 public:
13 /// The base type of the matrix (double, int,...)
14 using basetype = hila::arithmetic_type<sun>;
15 /// The matrix type
16 using gauge_type = sun;
17 /// The size of the matrix
18 static constexpr int N = sun::size;
19
20 /// A matrix field for each Direction
22 /// Also create a momentum field. This is only
23 /// allocated if necessary
25
26 /// Recalculate represented or smeared field
27 virtual void refresh() {}
28 /// Set the field to unity
29 virtual void set_unity() {}
30 /// Draw a random gauge field
31 virtual void random() {}
32
33 /// Update the momentum by given force
35 /// Draw gaussian random momentum
36 virtual void draw_momentum() {}
37 /// Set the momentum to zero
38 virtual void zero_momentum() {}
39 /// Make a copy of the gauge field for HMC
40 virtual void backup() {}
41 /// Restore the gauge field from the backup.
42 /// Used when an HMC trajectory is rejected.
43 virtual void restore_backup() {}
44
45 /// If the base type is double, this will be the
46 /// corresponding floating point type.
47 using gauge_type_flt = sun;
48};
49
50/// Specialize double precision SU(N) matrix types
51template <template <int, typename> class M, int N> class gauge_field_base<M<N, double>> {
52 public:
53 /// The basetype is double
54 using basetype = double;
55 /// The matrix type
56 using gauge_type = M<N, double>;
57
58 /// A matrix field for each Direction
60 /// Also create a momentum field. This is only
61 /// allocated if necessary
63
64 /// Recalculate represented or smeared field
65 virtual void refresh() {}
66 /// Set the field to unity
67 virtual void set_unity() {}
68 /// Draw a random gauge field
69 virtual void random() {}
70
71 /// Update the momentum by given force
73 /// Draw gaussian random momentum
74 virtual void draw_momentum() {}
75 /// Set the momentum to zero
76 virtual void zero_momentum() {}
77 /// Make a copy of the gauge field for HMC
78 virtual void backup() {}
79 /// Restore the gauge field from the backup.
80 /// Used when an HMC trajectory is rejected.
81 virtual void restore_backup() {}
82
83 /// This is the single precision type
84 using gauge_type_flt = M<N, float>;
85 /// Return a single precision copy of the gauge field
88 foralldir(dir) { gauge_flt.gauge[dir] = gauge[dir]; }
89 return gauge_flt;
90 }
91};
92
93/// Calculate the Polyakov loop for a given gauge field.
94template <int N> double polyakov_loop(Direction dir, Field<SU<N>> (&gauge)[NDIM]) {
95 // This implementation uses the onsites() to cycle through the
96 // NDIM-1 dimensional planes. This is probably not the most
97 // efficient implementation.
98 CoordinateVector vol = lattice.size();
99 Field<SU<N>> polyakov;
100 polyakov[ALL] = 1;
101 for (int t = 0; t < vol[dir]; t++) {
102 onsites(ALL) {
103 if (X.coordinate(dir) == (t + 1) % vol[dir]) {
104 polyakov[X] = polyakov[X] * gauge[dir][X - dir];
105 }
106 }
107 }
108
109 double poly = 0;
110 onsites(ALL) {
111 if (X.coordinates()[dir] == 0) {
112 poly += polyakov[X].trace().re;
113 }
114 }
115
116 double v3 = lattice.volume() / vol[dir];
117 return poly / (N * v3);
118}
119
120/// Calculate the sum of staples in Direction dir2
121/// connected to links in Direction dir1
122/// This version takes two different fields for the
123/// different directions and is necessary for HEX
124/// smearing
125template <typename SUN>
126Field<SUN> calc_staples(Field<SUN> *U1, Field<SUN> *U2, Direction dir1, Direction dir2) {
127 Field<SUN> staple_sum;
128 static Field<SUN> down_staple;
129 staple_sum[ALL] = 0;
130 // Calculate the down side staple.
131 // This will be communicated up.
132 down_staple[ALL] = U2[dir2][X + dir1].dagger() * U1[dir1][X].dagger() * U2[dir2][X];
133 // Forward staple
134 staple_sum[ALL] = staple_sum[X] +
135 U2[dir2][X + dir1] * U1[dir1][X + dir2].dagger() * U2[dir2][X].dagger();
136 // Add the down staple
137 staple_sum[ALL] = staple_sum[X] + down_staple[X - dir2];
138 return staple_sum;
139}
140
141/// Calculate the sum of staples connected to links in Direction dir
142template <typename SUN> Field<SUN> calc_staples(Field<SUN> *U, Direction dir) {
143 Field<SUN> staple_sum;
144 static Field<SUN> down_staple;
145 staple_sum[ALL] = 0;
146 foralldir(dir2) if (dir2 != dir) {
147 // Calculate the down side staple.
148 // This will be communicated up.
149 down_staple[ALL] = U[dir2][X + dir].dagger() * U[dir][X].dagger() * U[dir2][X];
150 // Forward staple
151 staple_sum[ALL] = staple_sum[X] +
152 U[dir2][X + dir] * U[dir][X + dir2].dagger() * U[dir2][X].dagger();
153 // Add the down staple
154 staple_sum[ALL] = staple_sum[X] + down_staple[X - dir2];
155 }
156 return staple_sum;
157}
158
159/// Measure the plaquette
160template <int N, typename radix> double plaquette_sum(Field<SU<N, radix>> *U) {
161 Reduction<double> Plaq = 0;
162 Plaq.delayed();
163 foralldir(dir1) foralldir(dir2) if (dir2 < dir1) {
164 onsites(ALL) {
165 element<SU<N, radix>> temp;
166 temp = U[dir1][X] * U[dir2][X + dir1] * U[dir1][X + dir2].dagger() *
167 U[dir2][X].dagger();
168 Plaq += 1 - temp.trace().re / N;
169 }
170 }
171 Plaq.reduce();
172 return Plaq;
173}
174
175/// The plaquette measurement for square matrices
176template <int N, typename radix> double plaquette_sum(Field<Matrix<N, N, radix>> *U) {
177 double Plaq = 0;
178 foralldir(dir1) foralldir(dir2) if (dir2 < dir1) {
179 onsites(ALL) {
180 element<SU<N, radix>> temp;
181 temp = U[dir1][X] * U[dir2][X + dir1] * U[dir1][X + dir2].dagger() *
182 U[dir2][X].dagger();
183 Plaq += 1 - temp.trace() / N;
184 }
185 }
186 return Plaq;
187}
188
189/// A gauge field contains a SU(N) matrix in each
190/// Direction for the gauge field and for the momentum.
191/// Defines methods for HMC to update the field and the
192/// momentum.
193template <typename matrix> class gauge_field : public gauge_field_base<matrix> {
194 public:
195 /// The matrix type
196 using gauge_type = matrix;
197 /// The fundamental gauge type. In the standard case
198 /// it is the same as the matrix type
199 using fund_type = matrix;
200 /// The base type (double, float, int...)
201 using basetype = hila::arithmetic_type<matrix>;
202 /// The size of the matrix
203 static constexpr int N = matrix::size;
204 /// Storage for a backup of the gauge field
206
207 /// Set the gauge field to unity
208 void set_unity() {
209 foralldir(dir) {
210 onsites(ALL) { this->gauge[dir][X] = 1; }
211 }
212 }
213
214 /// Draw a random gauge field
215 void random() {
216 foralldir(dir) {
217 onsites(ALL) {
218 this->gauge[dir][X].random();
219 }
220 }
221 }
222
223 /// Gaussian random momentum for each element
225 foralldir(dir) {
226 onsites(ALL) {
227 this->momentum[dir][X].gaussian_algebra();
228 }
229 }
230 }
231
232 /// Set the momentum to zero
234 foralldir(dir) { this->momentum[dir][ALL] = 0; }
235 }
236
237 /// Update the gauge field with time step eps
238 void gauge_update(double eps) {
239 foralldir(dir) {
240 onsites(ALL) {
241 element<matrix> momexp = (eps * this->momentum[dir][X]).exp();
242 this->gauge[dir][X] = momexp * this->gauge[dir][X];
243 }
244 }
245 }
246
247 /// Project a force term to the algebra and add to the
248 /// momentum
250 foralldir(dir) {
251 onsites(ALL) {
252 force[dir][X] = this->gauge[dir][X] * force[dir][X];
253 project_antihermitean(force[dir][X]);
254 this->momentum[dir][X] = this->momentum[dir][X] + force[dir][X];
255 }
256 }
257 }
258
259 /// Make a copy of fields updated in a trajectory
260 void backup() { foralldir(dir) gauge_backup[dir] = this->gauge[dir]; }
261
262 /// Restore the previous backup
263 void restore_backup() { foralldir(dir) this->gauge[dir] = gauge_backup[dir]; }
264
265 /// Read the gauge field from a file
266 void read_file(std::string filename) {
267 std::ifstream inputfile;
268 inputfile.open(filename, std::ios::in | std::ios::binary);
269 foralldir(dir) { read_fields(inputfile, this->gauge[dir]); }
270 inputfile.close();
271 }
272
273 /// Write the gauge field to a file
274 void write_file(std::string filename) {
275 std::ofstream outputfile;
276 outputfile.open(filename, std::ios::out | std::ios::trunc | std::ios::binary);
277 foralldir(dir) { write_fields(outputfile, this->gauge[dir]); }
278 outputfile.close();
279 }
280
281 /// Calculate the plaquette
282 double plaquette() {
283 return plaquette_sum(this->gauge) / (lattice.volume() * NDIM * (NDIM - 1) / 2);
284 }
285
286 /// Calculate the polyakov loop
287 double polyakov(int dir) { return polyakov_loop(dir, this->gauge); }
288
289 /// Return a reference to the momentum field
290 Field<gauge_type> &get_momentum(int dir) { return this->momentum[dir]; }
291 /// Return a reference to the gauge field
292 Field<gauge_type> &get_gauge(int dir) { return this->gauge[dir]; }
293};
294
295/// A gauge field, similar to the standard gauge_field class above,
296/// but with the gauge field projected into a higher representation.
297template <class repr> class represented_gauge_field : public gauge_field_base<repr> {
298 public:
299 /// The matrix type
300 using gauge_type = repr;
301 /// The type of a fundamental representation matrix
302 using fund_type = typename repr::sun;
303 /// The base type (double, float, int...)
304 using basetype = hila::arithmetic_type<repr>;
305 /// The size of the matrix
306 static constexpr int Nf = fund_type::size;
307 /// The size of the representation
308 static constexpr int N = repr::size;
309 /// Reference to the fundamental gauge field
311
312 /// Construct from a fundamental field
315 }
316 /// Copy constructor
319 }
320
321 /// Represent the fields
322 void refresh() {
323 foralldir(dir) {
324 this->gauge[dir].check_alloc();
325 onsites(ALL) {
326 this->gauge[dir][X].represent(fundamental.gauge[dir][X]);
327 }
328 }
329 }
330
331 /// Set the gauge field to unity. This will set the
332 /// underlying fundamental field
333 void set_unity() {
335 refresh();
336 }
337
338 /// Draw a random gauge field. This will set the
339 /// underlying fundamental field
340 void random() {
342 refresh();
343 }
344
345 /// Project a force term to the algebra and add to the
346 /// momentum
348 foralldir(dir) {
349 onsites(ALL) {
350 element<fund_type> fforce;
351 fforce = repr::project_force(this->gauge[dir][X] * force[dir][X]);
352 fundamental.momentum[dir][X] = fundamental.momentum[dir][X] + fforce;
353 }
354 }
355 }
356
357 /// This gets called if there is a represented gauge action term.
358 /// If there is also a fundamental term, it gets called twice...
360
361 /// Set the momentum to zero
363
364 /// Make a backup of the fundamental gauge field
365 /// Again, this may get called twice.
367
368 /// Restore the previous backup
370
371 /// Return a reference to the momentum field
373 /// Return a reference to the gauge Field
375};
376
377/// Shortcuts for represented gauge fields
378template <int N, typename radix>
380/// Shortcuts for represented gauge fields
381template <int N, typename radix>
383/// Shortcuts for represented gauge fields
384template <int N, typename radix>
386
387/*******************
388 * Action terms
389 *******************/
390
391/// The action of the canonical momentum of a gauge field.
392/// Momentum actions are a special case. It does not contain
393/// a force_step()-function. It contains a step()-function,
394/// which updates the momentum itself. It can be used as
395/// the lowest level of an integrator.
396template <typename gauge_field>
398 public:
399 /// The underlying gauge field type
401 /// The gauge matrix type
403 /// The size of the gauge matrix
404 static constexpr int N = gauge_mat::size;
405 /// The type of the momentum field
407
408 /// A reference to the gauge field
410
411 /// construct from a gauge field
413 /// construct a copy
415
416 /// The gauge action
417 double action() {
418 double Sa = 0;
419 foralldir(dir) {
420 onsites(ALL) { Sa += gauge.momentum[dir][X].algebra_norm(); }
421 }
422 return Sa;
423 }
424
425 /// Gaussian random momentum for each element
427
428 /* The following allow using a gauge action as the lowest level
429 of an integrator. */
430 /// Make a copy of fields updated in a trajectory
432
433 /// Restore the previous backup
435
436 /// A momentum action is also the lowest level of an
437 /// integrator hierarchy and needs to define the an step
438 /// to update the gauge field using the momentum
439
440 /// Update the gauge field with momentum
441 void step(double eps) { gauge.gauge_update(eps); }
442};
443
444/// The Wilson plaquette action of a gauge field.
445/// Action terms contain a force_step()-function, which
446/// updates the momentum of the gauge field. To do this,
447/// it needs to have a reference to the momentum field.
448template <typename gauge_field> class gauge_action : public action_base {
449 public:
450 /// The underlying gauge field type
452 /// The gauge matrix type
454 /// The size of the gauge matrix
455 static constexpr int N = gauge_mat::size;
456 /// The type of the momentum field
458
459 /// A reference to the gauge field
461 /// The coupling
462 double beta;
463
464 /// Construct out of a gauge field
465 gauge_action(gauge_field &g, double b) : gauge(g), beta(b) {}
466 /// Construct a copy
468
469 /// The gauge action
470 double action() {
471 double Sg = beta * plaquette_sum(gauge.gauge);
472 return Sg;
473 }
474
475 /// Update the momentum with the gauge field force
476 void force_step(double eps) {
477 Field<gauge_mat> staple;
478 Field<momtype> force[NDIM];
479 foralldir(dir) {
480 staple = calc_staples(gauge.gauge, dir);
481 onsites(ALL) { force[dir][X] = (-beta * eps / N) * staple[X]; }
482 }
483 gauge.add_momentum(force);
484 }
485};
486
487#endif
Array< n, m, T > exp(Array< n, m, T > a)
Exponential.
Definition array.h:1059
Complex definition.
Definition cmplx.h:56
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
Field< A > dagger() const
Returns dagger or Hermitian conjugate of Field depending on how it is defined for Field type T.
Definition field.h:1104
void check_alloc()
Allocate Field if it is not already allocated.
Definition field.h:458
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
Reduction & delayed(bool b=true)
deferred(bool) turns deferred on or off. By default turns on.
Definition reduction.h:148
void reduce()
Complete the reduction - start if not done, and wait if ongoing.
Definition reduction.h:274
Class for SU(N) matrix.
Definition sun_matrix.h:38
Definition u1.h:14
typename gauge_field::gauge_type gauge_mat
The gauge matrix type.
static constexpr int N
The size of the gauge matrix.
gauge_action(gauge_action &ga)
Construct a copy.
double beta
The coupling.
void force_step(double eps)
Update the momentum with the gauge field force.
gauge_action(gauge_field &g, double b)
Construct out of a gauge field.
double action()
The gauge action.
gauge_field & gauge
A reference to the gauge field.
gauge_field_base< M< N, float > > get_single_precision()
Return a single precision copy of the gauge field.
Definition gauge_field.h:86
M< N, float > gauge_type_flt
This is the single precision type.
Definition gauge_field.h:84
virtual void add_momentum(Field< SquareMatrix< N, Complex< basetype > > > *force)
Update the momentum by given force.
Definition gauge_field.h:72
double basetype
The basetype is double.
Definition gauge_field.h:54
virtual void draw_momentum()
Draw gaussian random momentum.
Definition gauge_field.h:74
virtual void zero_momentum()
Set the momentum to zero.
Definition gauge_field.h:76
virtual void refresh()
Recalculate represented or smeared field.
Definition gauge_field.h:65
virtual void random()
Draw a random gauge field.
Definition gauge_field.h:69
virtual void backup()
Make a copy of the gauge field for HMC.
Definition gauge_field.h:78
virtual void set_unity()
Set the field to unity.
Definition gauge_field.h:67
M< N, double > gauge_type
The matrix type.
Definition gauge_field.h:56
virtual void restore_backup()
Definition gauge_field.h:43
virtual void refresh()
Recalculate represented or smeared field.
Definition gauge_field.h:27
virtual void draw_momentum()
Draw gaussian random momentum.
Definition gauge_field.h:36
Field< sun > momentum[4]
Definition gauge_field.h:24
virtual void random()
Draw a random gauge field.
Definition gauge_field.h:31
hila::arithmetic_type< sun > basetype
The base type of the matrix (double, int,...)
Definition gauge_field.h:14
Field< sun > gauge[4]
A matrix field for each Direction.
Definition gauge_field.h:21
sun gauge_type
The matrix type.
Definition gauge_field.h:16
static constexpr int N
The size of the matrix.
Definition gauge_field.h:18
virtual void set_unity()
Set the field to unity.
Definition gauge_field.h:29
virtual void backup()
Make a copy of the gauge field for HMC.
Definition gauge_field.h:40
virtual void add_momentum(Field< SquareMatrix< N, Complex< basetype > > > *force)
Update the momentum by given force.
Definition gauge_field.h:34
virtual void zero_momentum()
Set the momentum to zero.
Definition gauge_field.h:38
hila::arithmetic_type< matrix > basetype
The base type (double, float, int...)
void restore_backup()
Restore the previous backup.
void zero_momentum()
Set the momentum to zero.
void gauge_update(double eps)
Update the gauge field with time step eps.
void set_unity()
Set the gauge field to unity.
matrix gauge_type
The matrix type.
void random()
Draw a random gauge field.
void backup()
Make a copy of fields updated in a trajectory.
Field< gauge_type > & get_gauge(int dir)
Return a reference to the gauge field.
double polyakov(int dir)
Calculate the polyakov loop.
void read_file(std::string filename)
Read the gauge field from a file.
void draw_momentum()
Gaussian random momentum for each element.
Field< matrix > gauge_backup[4]
Storage for a backup of the gauge field.
matrix fund_type
static constexpr int N
The size of the matrix.
double plaquette()
Calculate the plaquette.
void add_momentum(Field< SquareMatrix< N, Complex< basetype > > > *force)
void write_file(std::string filename)
Write the gauge field to a file.
Field< gauge_type > & get_momentum(int dir)
Return a reference to the momentum field.
gauge_momentum_action(gauge_momentum_action &ga)
construct a copy
void restore_backup()
Restore the previous backup.
gauge_momentum_action(gauge_field &g)
construct from a gauge field
static constexpr int N
The size of the gauge matrix.
gauge_field & gauge
A reference to the gauge field.
double action()
The gauge action.
void draw_gaussian_fields()
Gaussian random momentum for each element.
void backup_fields()
Make a copy of fields updated in a trajectory.
void step(double eps)
Update the gauge field with momentum.
typename gauge_field::gauge_type gauge_mat
The gauge matrix type.
void add_momentum(Field< SquareMatrix< N, Complex< basetype > > >(&force)[4])
Field< fund_type > & get_gauge(int dir)
Return a reference to the gauge Field.
typename repr::sun fund_type
The type of a fundamental representation matrix.
gauge_field< fund_type > & fundamental
Reference to the fundamental gauge field.
void restore_backup()
Restore the previous backup.
static constexpr int Nf
The size of the matrix.
hila::arithmetic_type< repr > basetype
The base type (double, float, int...)
void refresh()
Represent the fields.
repr gauge_type
The matrix type.
void zero_momentum()
Set the momentum to zero.
represented_gauge_field(represented_gauge_field &r)
Copy constructor.
Field< fund_type > & get_momentum(int dir)
Return a reference to the momentum field.
represented_gauge_field(gauge_field< fund_type > &f)
Construct from a fundamental field.
static constexpr int N
The size of the representation.
#define foralldir(d)
Macro to loop over (all) Direction(s)
Definition coordinates.h:78
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