HILA
Loading...
Searching...
No Matches
sun_overrelax.h
Go to the documentation of this file.
1/** @file sun_overrelax.h */
2
3#ifndef SUN_OVERRELAX_H
4#define SUN_OVERRELAX_H
5
6#include "sun_matrix.h"
7#include "su2.h"
8
9
10/**
11 * @brief \f$ SU(N) \f$ Overrelaxation using SU(2) subgroups
12 *
13 * @tparam T float/double/long double
14 * @tparam N Number of colors
15 * @param U \f$ SU(N) \f$ link to perform overrelaxation on
16 * @param staple Staple to compute overrelaxation with
17 */
18template <typename T, int N>
19void suN_overrelax(SU<N, T> &U, const SU<N, T> &staple) {
20 /* Do overrelaxation by SU(2) subgroups */
21 SU2<T> a;
22 SU<2, T> u;
23 SU<N, T> action = U * staple.dagger();
24
25 for (int ina = 0; ina < N - 1; ina++)
26 for (int inb = ina + 1; inb < N; inb++) {
27
28 /* decompose the action into SU(2) subgroups using Pauli matrix
29 * expansion
30 * The SU(2) hit matrix is represented as
31 * a0 + i * Sum j (sigma j * aj)
32 */
33 a = project_from_matrix(action, ina, inb);
34
35 a.normalize();
36
37 /* Now we need to multiply twice with the su2 element, thus;
38 * do now a^2; for example
39 * a^2_1 = a0 a1 + a1 a0 - i a2 a3 s2 s3 - i a2 a3 s3 s2
40 * = 2 a0 a1
41 * do also complex conjugate here
42 */
43
44 auto r = a.d * a.d - a.a * a.a - a.b * a.b - a.c * a.c;
45 a.a *= -2 * a.d;
46 a.b *= -2 * a.d;
47 a.c *= -2 * a.d;
48 a.d = r;
49
50 /* Elements of SU(2) matrix */
51
52 u = a.convert_to_2x2_matrix();
53
54 /* Do SU(2) hit on U and action (to overrelax) */
55
56 U.mult_by_2x2_left(ina, inb, u);
57 action.mult_by_2x2_left(ina, inb, u);
58
59 } /* hits */
60 /* check_unitarity( U );
61 */
62}
63
64
65/**
66 * @brief \f$ SU(N) \f$ full overrelaxation using SVD
67 *
68 * Following de Forcrand and Jahn, hep-lat/0503041
69 *
70 * Algorithm:
71 * - let U be link matrix, S sum of staples so that action = -beta/N Re Tr U S^*
72 * - Calculate svd S = u D v.dagger(), where D is diagonal matrix of singular values, u,v \in U(N)
73 * - Now M = u v.dagger() maximizes Tr(M S.dagger()) (in U(N)), but not SU(N) in general
74 * - compute det S = rho exp(i\phi)
75 * - Now e^(-i phi/N) u v.dagger() is SU(N)
76 * - Optimize: find diagonal P = {e^{i\theta_j}} in SU(N), i.e. sum_i theta_i = 0 (mod 2pi), which
77 * maximizes ReTr( S.dagger() e^{-i phi/N} u P v.dagger()).
78 * - Now matrix Z = e^(-i phi/N) u P v.dagger() in SU(N), and overrelax update
79 * U_new = Z U_old.dagger() Z
80 * - accept/reject with change in action
81 *
82 *
83 * Maximize ReTr( S.dagger() e^{-i phi/N} u P v.dagger()) = ReTr( e^{-i phi/N} D P ) =
84 * sum_j Re e^{i phi/N} e^{i\theta_j} D_j j = 0 .. (N-1)
85 * assuming D_min is smallest, def \theta_min = -\bar\theta = -sum_j \theta_j j != i_min
86 *
87 * Taking derivatives d/d\theta_j and setting these == 0, we obtain N-1 eqns which can be linearized
88 * Re e^{-i \phi/N} (i e^{i\theta_j}) D_j - Re e^{-i \phi/N} (i e^{-i \bar\theta}) D_min = 0
89 * (i - \theta_j) (i + \bar\theta)
90 *
91 * Let c == cos(phi/N), s == sin(phi/N)
92 * => (s - c \theta_j) D_j + (-s - c\bar\theta) D_min = 0
93 * => sum_k (D_j delta_jk + D_min ) \theta_k = (s/c)(D_j - D_min)
94 *
95 * This is a matrix equation of form M = (A + b F) theta = (A + w w^T) theta = rhs
96 * where A is diagonal and F is filled with 1, and w = sqrt(b)[1 1 1 ..]^T.
97 *
98 * This can be solved with the Sherman-Morrison formula
99 */
100
101#define USE_deForcrandJahn
102
103template <typename T, int N, typename Btype>
104int suN_overrelax_dFJ(SU<N, T> &U, const SU<N, T> &S, Btype beta) {
105
106 auto svdS = S.svd();
107 auto phiN = S.det().arg() / N;
108
109#ifdef USE_deForcrandJahn
110 // find smallest singular value
111 int imin = 0;
112 double smin = svdS.singularvalues.e(0);
113 for (int i = 1; i < N; i++) {
114 if (svdS.singularvalues.e(i) < smin) {
115 smin = svdS.singularvalues.e(i);
116 imin = i;
117 }
118 }
119
120 DiagonalMatrix<N - 1, double> diag;
121 int j = 0;
122 for (int i = 0; i < N; i++) {
123 if (i != imin)
124 diag.e(j++) = svdS.singularvalues.e(i);
125 }
126
127 // Do the Sherman-Morrison inverse - diag will contain the phase angles
128 diag.asVector() = hila::linalg::invert_diagonal_plus_constant_matrix(diag, smin) *
129 (tan(phiN) * (diag - smin).asVector());
130
131 // and construct diagonal P - absorb e^{-i phi/N} to P
133 j = 0;
134 for (int i = 0; i < N; i++) {
135 if (i != imin)
136 P.e(i) = expi(diag.e(j++) - phiN);
137 }
138 P.e(imin) = expi(-trace(diag) - phiN);
139#else
140 // This is Narayanan-Neuberger method. It has slightly worse acceptance
141 // to Forcrand + Jahn
143 P = expi(-phiN);
144#endif
145
146 // make unitary matrix Z
147 auto Z = svdS.U * P * svdS.V.dagger();
148
149 // candidate for new U
150 Z = Z * U.dagger() * Z;
151
152 // exp(old-new) > random()
153 if (exp(beta / N * real(mul_trace(Z - U, S.dagger()))) > hila::random()) {
154 // accepted
155 U = Z;
156 return 1;
157 } else
158 return 0;
159}
160
161
162#endif
Array< n, m, hila::arithmetic_type< T > > real(const Array< n, m, T > &arg)
Return real part of Array.
Definition array.h:662
Define type DiagonalMatrix<n,T>
T e(const int i) const
Element access - e(i) gives diagonal element i.
DiagonalMatrix dagger() const
dagger - conjugate elements
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
T det() const
determinant function - if matrix size is < 5, use Laplace, otherwise LU
Rtype dagger() const
Hermitian conjugate of matrix.
Definition matrix.h:1052
int svd(Matrix_t< n, n, Mt, MT > &_U, DiagonalMatrix< n, Et > &_D, Matrix_t< n, n, Mt, MT > &_V, enum hila::sort sorted=hila::sort::unsorted) const
Singular value decomposition: divide matrix A = U S V*, where U,V unitary and S diagonal matrix of re...
Definition su2.h:14
SU2< T > & normalize()
Normalize det = 1 to make sure it's an element of SU2.
Definition su2.h:47
Class for SU(N) matrix.
Definition sun_matrix.h:37
auto mul_trace(const Mtype1 &a, const Mtype2 &b)
Returns trace of product of two matrices.
Definition matrix.h:2528
double random()
Real valued uniform random number generator.
Definition hila_gpu.cpp:120
SU(N) Matrix definitions.
void suN_overrelax(SU< N, T > &U, const SU< N, T > &staple)
Overrelaxation using SU(2) subgroups