HILA
Loading...
Searching...
No Matches
libraries/dirac/staggered.h
1#ifndef __DIRAC_STAGGERED_H__
2#define __DIRAC_STAGGERED_H__
3
4#include "../plumbing/defs.h"
5#include "../datatypes/cmplx.h"
6#include "../datatypes/matrix.h"
7#include "../datatypes/sun.h"
8#include "../plumbing/field.h"
9#include "../../libraries/hmc/gauge_field.h"
10
11template <typename vector> Field<vector> staggered_dirac_temp[NDIM];
12
13/// Initialize the staggered eta field
14inline void init_staggered_eta(Field<double> (&staggered_eta)[NDIM]) {
15 // Initialize the staggered eta field
16 foralldir(d) {
17 onsites(ALL) {
18 element<CoordinateVector> l = X.coordinates();
19 element<int> sumcoord = 0;
20 for (int d2 = e_x; d2 < d; d2++) {
21 sumcoord += l[d2];
22 }
23 // +1 if sumcoord divisible by 2, -1 otherwise
24 // If statements not yet implemented for vectors
25 staggered_eta[d][X] = (sumcoord % 2) * 2 - 1;
26 }
27 }
28}
29
30/// Apply the mass term v_out = m*v_in
31template <typename vtype>
32void dirac_staggered_diag(const double mass, const Field<vtype> &v_in,
33 Field<vtype> &v_out, Parity par) {
34 v_out[par] = v_out[X] + mass * v_in[X];
35}
36
37/// Apply the inverse of the diagonal part,
38/// v_out = 1/m * v_in
39template <typename vtype>
40void dirac_staggered_diag_inverse(const double mass, Field<vtype> &v_out, Parity par) {
41 v_out[par] = (1.0 / mass) * v_out[X];
42}
43
44/// Apply the derivative part
45template <typename mtype, typename vtype>
46void dirac_staggered_hop(const Field<mtype> *gauge, const Field<vtype> &v_in,
47 Field<vtype> &v_out, Field<double> (&staggered_eta)[NDIM],
48 Parity par, int sign) {
49 Field<vtype>(&vtemp)[NDIM] = staggered_dirac_temp<vtype>;
50 foralldir(dir) {
51 vtemp[dir].copy_boundary_condition(v_in);
52 v_in.start_gather(dir, par);
53 }
54
55 // First multiply the by conjugate before communicating the vector
56 foralldir(dir) {
57 vtemp[dir][opp_parity(par)] = gauge[dir][X].adjoint() * v_in[X];
58 vtemp[dir].start_gather(-dir, par);
59 }
60
61 // Run neighbour gathers and multiplications
62 foralldir(dir) {
63 v_out[par] = v_out[X] + 0.5 * sign * staggered_eta[dir][X] *
64 (gauge[dir][X] * v_in[X + dir] - vtemp[dir][X - dir]);
65 }
66}
67
68/// Calculate derivative d/dA_x,mu (chi D psi)
69/// Necessary for the HMC force calculation.
70template <typename gaugetype, typename momtype, typename vtype>
71void dirac_staggered_calc_force(const Field<gaugetype> *gauge, const Field<vtype> &chi,
72 const Field<vtype> &psi, Field<momtype> (&out)[NDIM],
73 Field<double> (&staggered_eta)[NDIM], int sign,
74 Parity par) {
75 foralldir(dir) {
76 out[dir][ALL] = 0;
77 out[dir][par] =
78 -sign * 0.5 * staggered_eta[dir][X] * chi[X + dir].outer_product(psi[X]);
79 out[dir][opp_parity(par)] = out[dir][X] + sign * 0.5 *
80 staggered_eta[dir][X + dir] *
81 psi[X + dir].outer_product(chi[X]);
82 }
83}
84
85/// An operator class that applies the staggered Dirac operator
86/// D.apply(in, out) aplies the operator
87/// D.dagger(int out) aplies the conjugate of the operator
88///
89/// This is useful for defining inverters as composite
90/// operators. For example the conjugate gradient inverter
91/// is CG<dirac_staggered>.
92template <typename matrix> class dirac_staggered {
93 private:
94 /// The eta Field in the staggered operator, eta_x,\nu -1^(sum_mu<nu x_\mu)
95 Field<double> staggered_eta[NDIM];
96
97 public:
98 /// the fermion mass
99 double mass;
100 /// The SU(N) vector type
101 using vector_type = SU_vector<matrix::size, hila::arithmetic_type<matrix>>;
102 /// The matrix type
103 using matrix_type = matrix;
104 /// A reference to the gauge links used in the dirac operator
105 Field<matrix> (&gauge)[NDIM];
106
107 /// Single precision type in case the base type is double precision.
108 /// This is used to precondition the inversion of this operator
110
111 /// The parity this operator applies to
113
114 // Constructor: initialize mass, gauge and eta
115 dirac_staggered(dirac_staggered &d) : gauge(d.gauge), mass(d.mass) {
116 // Initialize the eta field (Share this?)
117 init_staggered_eta(staggered_eta);
118 }
119 // Constructor: initialize mass, gauge and eta
120 dirac_staggered(double m, Field<matrix> (&g)[NDIM]) : gauge(g), mass(m) {
121 init_staggered_eta(staggered_eta);
122 }
123 // Constructor: initialize mass, gauge and eta
124 dirac_staggered(double m, gauge_field_base<matrix> &g) : gauge(g.gauge), mass(m) {
125 init_staggered_eta(staggered_eta);
126 }
127
128 /// Construct from another Dirac_Wilson operator of a different type.
129 template <typename M>
131 : gauge(g.gauge), mass(d.mass) {
132 init_staggered_eta(staggered_eta);
133 }
134
135 /// Applies the operator to in
137 out[ALL] = 0;
138 dirac_staggered_diag(mass, in, out, ALL);
139 dirac_staggered_hop(gauge, in, out, staggered_eta, ALL, 1);
140 }
141
142 /// Applies the conjugate of the operator
144 out[ALL] = 0;
145 dirac_staggered_diag(mass, in, out, ALL);
146 dirac_staggered_hop(gauge, in, out, staggered_eta, ALL, -1);
147 }
148
149 /// Applies the derivative of the Dirac operator with respect
150 /// to the gauge field
151 template <typename momtype>
152 void force(const Field<vector_type> &chi, const Field<vector_type> &psi,
153 Field<momtype> (&force)[NDIM], int sign = 1) {
154 dirac_staggered_calc_force(gauge, chi, psi, force, staggered_eta, sign, ALL);
155 }
156};
157
158/// Multiplying from the left applies the standard Dirac operator
159template <typename vector, typename matrix>
162 out.copy_boundary_condition(in);
163 D.apply(in, out);
164 return out;
165}
166
167/// Multiplying from the right applies the conjugate
168template <typename vector, typename matrix>
171 out.copy_boundary_condition(in);
172 D.dagger(in, out);
173 return out;
174}
175
176/// An even-odd decomposed Wilson Dirac operator. Applies
177/// D_{even to odd} D_{diag}^{-1} D_{odd to even} on the even
178/// sites of the vector.
179///
180/// The fermion partition function is
181/// det(D) = det(D_eveneodd) + det(D_{diag odd}).
182/// Dirac_Wilson_evenodd can be used to replace D_Wilson
183/// in the HMC action, as long as the diagonal odd to odd
184/// part is accounted for.
185///
186/// This is useful for defining inverters as composite
187/// operators. For example the conjugate gradient inverter
188/// is CG<Dirac_Wilson_evenodd>.
189///
190/// As a side effect, the output Field becomes
191/// out = D_{diag}^{-1} D_{odd to even} in
192///
193template <typename matrix> class dirac_staggered_evenodd {
194 private:
195 /// The eta Field in the staggered operator, eta_x,\nu -1^(sum_mu<nu x_\mu)
196 Field<double> staggered_eta[NDIM];
197
198 /// A reference to the gauge links used in the dirac operator
199 Field<matrix> (&gauge)[NDIM];
200
201 public:
202 /// the fermion mass
203 double mass;
204 /// The SU(N) vector type
205 using vector_type = SU_vector<matrix::size, hila::arithmetic_type<matrix>>;
206 /// The matrix type
207 using matrix_type = matrix;
208
209 /// Single precision type in case the base type is double precision.
210 /// This is used to precondition the inversion of this operator
211 using type_flt =
213
214 /// The parity this operator applies to
216
217 /// Constructor: initialize mass, gauge and eta
219 init_staggered_eta(staggered_eta);
220 }
221 /// Constructor: initialize mass, gauge and eta
222 dirac_staggered_evenodd(double m, Field<matrix> (&U)[NDIM]) : gauge(U), mass(m) {
223 init_staggered_eta(staggered_eta);
224 }
225 /// Constructor: initialize mass, gauge and eta
227 : gauge(g.gauge), mass(m) {
228 init_staggered_eta(staggered_eta);
229 }
230
231 /// Construct from another Dirac_Wilson operator of a different type.
232 template <typename M>
234 : gauge(g.gauge), mass(d.mass) {
235 init_staggered_eta(staggered_eta);
236 }
237
238 /// Applies the operator to in
240 out[ALL] = 0;
241 dirac_staggered_diag(mass, in, out, EVEN);
242
243 dirac_staggered_hop(gauge, in, out, staggered_eta, ODD, 1);
244 dirac_staggered_diag_inverse(mass, out, ODD);
245 dirac_staggered_hop(gauge, out, out, staggered_eta, EVEN, 1);
246 }
247
248 /// Applies the conjugate of the operator
250 out[ALL] = 0;
251 dirac_staggered_diag(mass, in, out, EVEN);
252
253 dirac_staggered_hop(gauge, in, out, staggered_eta, ODD, -1);
254 dirac_staggered_diag_inverse(mass, out, ODD);
255 dirac_staggered_hop(gauge, out, out, staggered_eta, EVEN, -1);
256 }
257
258 /// Applies the derivative of the Dirac operator with respect
259 /// to the gauge Field
260 template <typename momtype>
261 inline void force(const Field<vector_type> &chi, const Field<vector_type> &psi,
262 Field<momtype> (&force)[NDIM], int sign) {
263 Field<momtype> force2[NDIM];
266
267 tmp[ALL] = 0;
268 dirac_staggered_hop(gauge, chi, tmp, staggered_eta, ODD, -sign);
269 dirac_staggered_diag_inverse(mass, tmp, ODD);
270 dirac_staggered_calc_force(gauge, tmp, psi, force, staggered_eta, sign, EVEN);
271
272 tmp[ALL] = 0;
273 dirac_staggered_hop(gauge, psi, tmp, staggered_eta, ODD, sign);
274 dirac_staggered_diag_inverse(mass, tmp, ODD);
275 dirac_staggered_calc_force(gauge, chi, tmp, force2, staggered_eta, sign, ODD);
276
277 foralldir(dir) { force[dir][ALL] = force[dir][X] + force2[dir][X]; }
278 }
279};
280
281#endif
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
void copy_boundary_condition(const Field< A > &rhs)
Copy the boundary condition from another field.
Definition field.h:650
dir_mask_t start_gather(Direction d, Parity p=ALL) const
Definition field_comm.h:262
dirac_staggered_evenodd(double m, Field< matrix >(&U)[4])
Constructor: initialize mass, gauge and eta.
matrix matrix_type
The matrix type.
void dagger(Field< vector_type > &in, Field< vector_type > &out)
Applies the conjugate of the operator.
dirac_staggered_evenodd(double m, gauge_field_base< matrix > &g)
Constructor: initialize mass, gauge and eta.
dirac_staggered_evenodd(dirac_staggered_evenodd &d)
Constructor: initialize mass, gauge and eta.
void force(const Field< vector_type > &chi, const Field< vector_type > &psi, Field< momtype >(&force)[4], int sign)
SU_vector< matrix::size, hila::arithmetic_type< matrix > > vector_type
The SU(N) vector type.
Parity par
The parity this operator applies to.
void apply(Field< vector_type > &in, Field< vector_type > &out)
Applies the operator to in.
dirac_staggered_evenodd(dirac_staggered_evenodd< M > &d, gauge_field_base< matrix > &g)
Construct from another Dirac_Wilson operator of a different type.
void force(const Field< vector_type > &chi, const Field< vector_type > &psi, Field< momtype >(&force)[4], int sign=1)
SU_vector< matrix::size, hila::arithmetic_type< matrix > > vector_type
The SU(N) vector type.
matrix matrix_type
The matrix type.
Parity par
The parity this operator applies to.
void apply(const Field< vector_type > &in, Field< vector_type > &out)
Applies the operator to in.
double mass
the fermion mass
dirac_staggered(dirac_staggered< M > &d, gauge_field_base< matrix > &g)
Construct from another Dirac_Wilson operator of a different type.
void dagger(const Field< vector_type > &in, Field< vector_type > &out)
Applies the conjugate of the operator.
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
constexpr Parity ALL
bit pattern: 011
std::ostream out
this is our default output file stream