HILA
Loading...
Searching...
No Matches
sun_heatbath.h
Go to the documentation of this file.
1/** @file sun_heatbath.h */
2
3#ifndef SUN_HEATBATH_H
4#define SUN_HEATBATH_H
5
6
7/* Kennedy-Pendleton quasi heat bath on SU(2) subgroups */
8
9/* This does the heatbath with
10 * beta ( 1 - 1/Ncol Tr U S^+ ) S is the sum of staples.
11 * -> -beta/Ncol Tr u (US+) = -beta/Ncol u_ab (US+)_ba
12 * here u is a SU(2) embedded in SU(N); u = su2 * 1.
13 */
14
15#include "sun_matrix.h"
16#include "su2.h"
17
18/**
19 * @brief \f$ SU(N) \f$ heatbath
20 * @details Kennedy-Pendleton quasi heat bath on \f$ SU(2)\f$ subgroups
21 * @tparam T Group element type such as Real or Complex
22 * @tparam N Number of colors
23 * @param U \f$ SU(N) \f$ link to perform heatbath on
24 * @param staple Staple to compute heatbath with
25 * @param beta
26 * @return double
27 */
28template <typename T, int N>
29double suN_heatbath(SU<N, T> &U, const SU<N, T> &staple, double beta) {
30 // K-P quasi-heat bath by SU(2) subgroups
31
32 double utry, uhit;
33 double xr1, xr2, xr3, xr4;
34
35 double r, r2, rho, z;
36 double al, d, xl, xd;
37 int k, test;
38 double b3;
39 SU<N, T> action;
40 SU<2, T> h2x2;
41 SU2<T> v, a, h;
42 double pi2 = M_PI * 2.0;
43
44 b3 = beta / N;
45
46 utry = uhit = 0.0;
47
48 /* now for the qhb updating */
49
50 action = U * staple.dagger();
51
52 /* SU(2) subgroups */
53 for (int ina = 0; ina < N - 1; ina++)
54 for (int inb = ina + 1; inb < N; inb++) {
55
56 /* decompose the action into SU(2) subgroups using
57 * Pauli matrix expansion
58 * The SU(2) hit matrix is represented as
59 * a0 + i * Sum j (sigma j * aj)
60 * Let us actually store dagger, v = action(a,b).dagger
61 */
62 v.d = action.e(ina, ina).re + action.e(inb, inb).re;
63 v.c = -(action.e(ina, ina).im - action.e(inb, inb).im);
64 v.a = -(action.e(ina, inb).im + action.e(inb, ina).im);
65 v.b = -(action.e(ina, inb).re - action.e(inb, ina).re);
66
67 z = sqrt(v.det());
68
69 v /= z;
70
71 /* end norm check--trial SU(2) matrix is a0 + i a(j)sigma(j)*/
72 /* test */
73 /* now begin qhb */
74 /* get four random numbers */
75
76 xr1 = log(1.0 - hila::random());
77 xr2 = log(1.0 - hila::random());
78 xr3 = hila::random();
79 xr4 = hila::random();
80
81 xr3 = cos(pi2 * xr3);
82
83
84 // generate a0 component of suN matrix
85 //
86 // first consider generating an su(2) matrix h
87 // according to exp(bg/Ncol * re tr(h*s))
88 // rewrite re tr(h*s) as re tr(h*v)z where v is
89 // an su(2) matrix and z is a real normalization constant
90 // let v = z*v. (z is 2*xi in k-p notation)
91 // v is represented in the form v(0) + i*sig*v (sig are pauli)
92 // v(0) and vector v are real
93 //
94 // let a = h*v and now generate a
95 // rewrite beta/3 * re tr(h*v) * z as al*a0
96 // a0 has prob(a0) = n0 * sqrt(1 - a0**2) * exp(al * a0)
97
98
99 al = b3 * z;
100
101 // let a0 = 1 - del**2
102 // get d = del**2
103 // such that prob2(del) = n1 * del**2 * exp(-al*del**2)
104
105
106 d = -(xr2 + xr1 * xr3 * xr3) / al;
107
108 /* monte carlo prob1(del) = n2 * sqrt(1 - 0.5*del**2)
109 * then prob(a0) = n3 * prob1(a0)*prob2(a0)
110 */
111
112 if ((1.00 - 0.5 * d) <= xr4 * xr4) {
113 if (al > 2.0) { /* k-p algorithm */
114 test = 0;
115 for (k = 0; k < 40 && !test; k++) {
116 /* get four random numbers */
117 xr1 = log(1.0 - hila::random());
118 xr2 = log(1.0 - hila::random());
119 xr3 = hila::random();
120 xr4 = hila::random();
121
122 xr3 = cos(pi2 * xr3);
123
124 d = -(xr2 + xr1 * xr3 * xr3) / al;
125 if ((1.00 - 0.5 * d) > xr4 * xr4)
126 test = 1;
127 }
128 utry += k;
129 uhit++;
130#ifndef __CUDA_ARCH__
131 // TODO: Make parallel-warning out of this
132 // hila::out0 << "site took 20 kp hits\n";
133#endif
134 } else { /* now al <= 2.0 */
135
136 /* creutz algorithm */
137 xl = exp((double)(-2.0 * al));
138 xd = 1.0 - xl;
139 test = 0;
140 double a0;
141 for (k = 0; k < 40 && test == 0; k++) {
142 /* get two random numbers */
143 xr1 = hila::random();
144 xr2 = hila::random();
145
146 r = xl + xd * xr1;
147 a0 = 1.00 + log((double)r) / al;
148 if ((1.0 - a0 * a0) > xr2 * xr2)
149 test = 1;
150 }
151 d = 1.0 - a0;
152 utry += k;
153 uhit++;
154#ifndef __CUDA_ARCH__
155 // hila::out0 << "site took 20 creutz hits\n";
156#endif
157 } /* endif al */
158
159 } else {
160 /* direct hit */
161 utry += 1.0;
162 uhit += 1.0;
163 }
164
165 /* generate full su(2) matrix and update link matrix*/
166
167 /* find a0 = 1 - d*/
168 a.d = 1.0 - d;
169 /* compute r */
170 r2 = 1.0 - a.d * a.d;
171 r2 = fabs(r2);
172 r = sqrt(r2);
173
174 /* compute a3 */
175 a.c = (2.0 * hila::random() - 1.0) * r;
176
177 /* compute a1 and a2 */
178 rho = r2 - a.c * a.c;
179 rho = sqrt(fabs(rho));
180
181 /*xr2 is a random number between 0 and 2*pi */
182 xr2 = pi2 * hila::random();
183 a.a = rho * cos((double)xr2);
184 a.b = rho * sin((double)xr2);
185
186 /* now do the updating. h = a*v^dagger, new u = h*u */
187 h = a * v; // v was daggerized above
188
189 /* Elements of SU(2) matrix */
190 h2x2 = h.convert_to_2x2_matrix();
191
192 /* update the link and 'action' */
193
194 U.mult_by_2x2_left(ina, inb, h2x2);
195 action.mult_by_2x2_left(ina, inb, h2x2);
196
197 } /* hits */
198
199 /* check_unitarity( U );
200 */
201 return (uhit / utry);
202
203} /* site */
204
205#endif
void mult_by_2x2_left(int p, int q, const Matrix_t< 2, 2, R, Mt > &M)
Multiply -matrix from the left by matrix defined by sub matrix.
Definition matrix.h:1532
Rtype dagger() const
Hermitian conjugate of matrix.
Definition matrix.h:1052
T e(const int i, const int j) const
Standard array indexing operation for matrices.
Definition matrix.h:272
Definition su2.h:14
Class for SU(N) matrix.
Definition sun_matrix.h:37
double random()
Real valued uniform random number generator.
Definition hila_gpu.cpp:120
double suN_heatbath(SU< N, T > &U, const SU< N, T > &staple, double beta)
heatbath
SU(N) Matrix definitions.