Grid 0.7.0
GaugeGroupTwoIndex.h
Go to the documentation of this file.
1
2//
3// * Two index representation generators
4//
5// * Normalisation for the fundamental generators:
6// trace ta tb = 1/2 delta_ab = T_F delta_ab
7// T_F = 1/2 for SU(N) groups
8//
9//
10// base for NxN two index (anti-symmetric) matrices
11// normalized to 1 (d_ij is the kroenecker delta)
12//
13// (e^(ij)_{kl} = 1 / sqrt(2) (d_ik d_jl +/- d_jk d_il)
14//
15// Then the generators are written as
16//
17// (iT_a)^(ij)(lk) = i * ( tr[e^(ij)^dag e^(lk) T^trasp_a] +
18// tr[e^(lk)e^(ij)^dag T_a] ) //
19//
20//
22
23// Authors: David Preti, Guido Cossu
24
25#ifndef QCD_UTIL_GAUGEGROUPTWOINDEX_H
26#define QCD_UTIL_GAUGEGROUPTWOINDEX_H
27
29
31
32constexpr inline Real delta(int a, int b) { return (a == b) ? 1.0 : 0.0; }
33
34namespace detail {
35
36template <class cplx, int nc, TwoIndexSymmetry S>
38
39template <class cplx, int nc>
41 static const int ngroup = nc / 2;
42 static void baseOffDiagonalSp(int i, int j, iScalar<iScalar<iMatrix<cplx, nc> > > &eij) {
43 eij = Zero();
44 RealD tmp;
45
46 if ((i == ngroup + j) && (1 <= j) && (j < ngroup)) {
47 for (int k = 0; k < j+1; k++) {
48 if (k < j) {
49 tmp = 1 / sqrt(j * (j + 1));
50 eij()()(k, k + ngroup) = tmp;
51 eij()()(k + ngroup, k) = -tmp;
52 }
53 if (k == j) {
54 tmp = -j / sqrt(j * (j + 1));
55 eij()()(k, k + ngroup) = tmp;
56 eij()()(k + ngroup, k) = -tmp;
57 }
58 }
59
60 }
61
62 else if (i != ngroup + j) {
63 for (int k = 0; k < nc; k++)
64 for (int l = 0; l < nc; l++) {
65 eij()()(l, k) =
66 delta(i, k) * delta(j, l) - delta(j, k) * delta(i, l);
67 }
68 }
69 RealD nrm = 1. / std::sqrt(2.0);
70 eij = eij * nrm;
71 }
72};
73
74template <class cplx, int nc>
76 static void baseOffDiagonalSp(int i, int j, iScalar<iScalar<iMatrix<cplx, nc> > > &eij) {
77 eij = Zero();
78 for (int k = 0; k < nc; k++)
79 for (int l = 0; l < nc; l++)
80 eij()()(l, k) =
81 delta(i, k) * delta(j, l) + delta(j, k) * delta(i, l);
82
83 RealD nrm = 1. / std::sqrt(2.0);
84 eij = eij * nrm;
85 }
86};
87
88} // closing detail namespace
89
90template <int ncolour, TwoIndexSymmetry S, class group_name>
91class GaugeGroupTwoIndex : public GaugeGroup<ncolour, group_name> {
92 public:
93 // The chosen convention is that we are taking ncolour to be N in SU<N> but 2N
94 // in Sp(2N). ngroup is equal to N for SU but 2N/2 = N for Sp(2N).
95 static_assert(std::is_same<group_name, GroupName::SU>::value or
96 std::is_same<group_name, GroupName::Sp>::value,
97 "ngroup is only implemented for SU and Sp currently.");
98 static const int ngroup =
99 std::is_same<group_name, GroupName::SU>::value ? ncolour : ncolour / 2;
100 static const int Dimension =
101 (ncolour * (ncolour + S) / 2) + (std::is_same<group_name, GroupName::Sp>::value ? (S - 1) / 2 : 0);
102 static const int DimensionAS =
103 (ncolour * (ncolour - 1) / 2) + (std::is_same<group_name, GroupName::Sp>::value ? (- 1) : 0);
104 static const int DimensionS =
105 ncolour * (ncolour + 1) / 2;
106 static const int NumGenerators =
108
109 template <typename vtype>
111
115
119
123
130
131 template <typename vtype>
133
137
138private:
139 template <class cplx>
140 static void baseDiagonal(int Index, iGroupMatrix<cplx> &eij) {
141 eij = Zero();
142 eij()()(Index - ncolour * (ncolour - 1) / 2,
143 Index - ncolour * (ncolour - 1) / 2) = 1.0;
144 }
145
146 template <class cplx>
147 static void baseOffDiagonal(int i, int j, iGroupMatrix<cplx> &eij, GroupName::SU) {
148 eij = Zero();
149 for (int k = 0; k < ncolour; k++)
150 for (int l = 0; l < ncolour; l++)
151 eij()()(l, k) =
152 delta(i, k) * delta(j, l) + S * delta(j, k) * delta(i, l);
153
154 RealD nrm = 1. / std::sqrt(2.0);
155 eij = eij * nrm;
156 }
157
158 template <class cplx>
162
163public:
164
165 template <class cplx>
166 static void base(int Index, iGroupMatrix<cplx> &eij) {
167 // returns (e)^(ij)_{kl} necessary for change of base U_F -> U_R
168 assert(Index < Dimension);
169 eij = Zero();
170 // for the linearisation of the 2 indexes
171 static int a[ncolour * (ncolour - 1) / 2][2]; // store the a <-> i,j
172 static bool filled = false;
173 if (!filled) {
174 int counter = 0;
175 for (int i = 1; i < ncolour; i++) {
176 for (int j = 0; j < i; j++) {
177 if (std::is_same<group_name, GroupName::Sp>::value)
178 {
179 if (j==0 && i==ngroup+j && S==-1) {
180 //std::cout << "skipping" << std::endl; // for Sp2n this vanishes identically.
181 j = j+1;
182 }
183 }
184 a[counter][0] = i;
185 a[counter][1] = j;
186 counter++;
187 }
188 }
189 filled = true;
190 }
191 if (Index < ncolour*ncolour - DimensionS)
192 {
193 baseOffDiagonal(a[Index][0], a[Index][1], eij, group_name());
194 } else {
195 baseDiagonal(Index, eij);
196 }
197 }
198
199 static void printBase(void) {
200 for (int gen = 0; gen < Dimension; gen++) {
201 Matrix tmp;
202 base(gen, tmp);
203 std::cout << GridLogMessage << "Nc = " << ncolour << " t_" << gen
204 << std::endl;
205 std::cout << GridLogMessage << tmp << std::endl;
206 }
207 }
208
209 template <class cplx>
210 static void generator(int Index, iGroupTwoIndexMatrix<cplx> &i2indTa) {
214
215 for (int a = 0; a < NumGenerators; a++)
217
218 for (int a = 0; a < Dimension; a++) base(a, eij[a]);
219
220 for (int a = 0; a < Dimension; a++) {
221 tmp = transpose(eij[a]*ta[Index]) + transpose(eij[a]) * ta[Index];
222 for (int b = 0; b < Dimension; b++) {
223 Complex iTr = TensorRemove(timesI(trace(tmp * eij[b])));
224 i2indTa()()(a, b) = iTr;
225 }
226 }
227 }
228
229 static void printGenerators(void) {
230 for (int gen = 0; gen < NumGenerators; gen++) {
231 TIMatrix i2indTa;
232 generator(gen, i2indTa);
233 std::cout << GridLogMessage << "Nc = " << ncolour << " t_" << gen
234 << std::endl;
235 std::cout << GridLogMessage << i2indTa << std::endl;
236 }
237 }
238
239 static void testGenerators(void) {
240 TIMatrix i2indTa, i2indTb;
241 std::cout << GridLogMessage << "2IndexRep - Checking if traceless"
242 << std::endl;
243 for (int a = 0; a < NumGenerators; a++) {
244 generator(a, i2indTa);
245 std::cout << GridLogMessage << a << std::endl;
246 assert(norm2(trace(i2indTa)) < 1.0e-6);
247 }
248 std::cout << GridLogMessage << std::endl;
249
250 std::cout << GridLogMessage << "2IndexRep - Checking if antihermitean"
251 << std::endl;
252 for (int a = 0; a < NumGenerators; a++) {
253 generator(a, i2indTa);
254 std::cout << GridLogMessage << a << std::endl;
255 assert(norm2(adj(i2indTa) + i2indTa) < 1.0e-6);
256 }
257
258 std::cout << GridLogMessage << std::endl;
259 std::cout << GridLogMessage
260 << "2IndexRep - Checking Tr[Ta*Tb]=delta(a,b)*(N +- 2)/2"
261 << std::endl;
262 for (int a = 0; a < NumGenerators; a++) {
263 for (int b = 0; b < NumGenerators; b++) {
264 generator(a, i2indTa);
265 generator(b, i2indTb);
266
267 // generator returns iTa, so we need a minus sign here
268 Complex Tr = -TensorRemove(trace(i2indTa * i2indTb));
269 std::cout << GridLogMessage << "a=" << a << "b=" << b << "Tr=" << Tr
270 << std::endl;
271 if (a == b) {
272 assert(real(Tr) - ((ncolour + S * 2) * 0.5) < 1e-8);
273 } else {
274 assert(real(Tr) < 1e-8);
275 }
276 assert(imag(Tr) < 1e-8);
277 }
278 }
279 std::cout << GridLogMessage << std::endl;
280 }
281
284 LatticeTwoIndexMatrix &out, Real scale = 1.0) {
285 conformable(h, out);
286 GridBase *grid = out.Grid();
287 LatticeTwoIndexMatrix la(grid);
288 TIMatrix i2indTa;
289
290 out = Zero();
291 for (int a = 0; a < NumGenerators; a++) {
292 generator(a, i2indTa);
293 la = peekColour(h, a) * i2indTa;
294 out += la;
295 }
296 out *= scale;
297 }
298
299 // Projects the algebra components
300 // of a lattice matrix ( of dimension ncol*ncol -1 )
301 static void projectOnAlgebra(
303 const LatticeTwoIndexMatrix &in, Real scale = 1.0) {
304 conformable(h_out, in);
305 h_out = Zero();
306 TIMatrix i2indTa;
307 Real coefficient = -2.0 / (ncolour + 2 * S) * scale;
308 // 2/(Nc +/- 2) for the normalization of the trace in the two index rep
309 for (int a = 0; a < NumGenerators; a++) {
310 generator(a, i2indTa);
311 pokeColour(h_out, real(trace(i2indTa * in)) * coefficient, a);
312 }
313 }
314
315 // a projector that keeps the generators stored to avoid the overhead of
316 // recomputing them
317 static void projector(
319 const LatticeTwoIndexMatrix &in, Real scale = 1.0) {
320 conformable(h_out, in);
321 // to store the generators
322 static std::vector<TIMatrix> i2indTa(NumGenerators);
323 h_out = Zero();
324 static bool precalculated = false;
325 if (!precalculated) {
326 precalculated = true;
327 for (int a = 0; a < NumGenerators; a++) generator(a, i2indTa[a]);
328 }
329
330 Real coefficient =
331 -2.0 / (ncolour + 2 * S) * scale; // 2/(Nc +/- 2) for the normalization
332 // of the trace in the two index rep
333
334 for (int a = 0; a < NumGenerators; a++) {
335 auto tmp = real(trace(i2indTa[a] * in)) * coefficient;
336 pokeColour(h_out, tmp, a);
337 }
338 }
339};
340
341template <int ncolour, TwoIndexSymmetry S>
343
344// Some useful type names
347
352
357
358template <int ncolour, TwoIndexSymmetry S>
360
363
366
368
370
371#endif
std::vector< T, uvmAllocator< T > > Vector
SU_TwoIndex< Nc, Symmetric > TwoIndexSymmMatrices
SU_TwoIndex< 2, Symmetric > SU2TwoIndexSymm
SU_TwoIndex< 5, AntiSymmetric > SU5TwoIndexAntiSymm
Sp_TwoIndex< 2, Symmetric > Sp2TwoIndexSymm
SU_TwoIndex< 2, AntiSymmetric > SU2TwoIndexAntiSymm
TwoIndexSymmetry
@ AntiSymmetric
@ Symmetric
SU_TwoIndex< 5, Symmetric > SU5TwoIndexSymm
SU_TwoIndex< Nc, AntiSymmetric > TwoIndexAntiSymmMatrices
SU_TwoIndex< 3, AntiSymmetric > SU3TwoIndexAntiSymm
GaugeGroupTwoIndex< ncolour, S, GroupName::SU > SU_TwoIndex
Sp_TwoIndex< 4, AntiSymmetric > Sp4TwoIndexAntiSymm
Sp_TwoIndex< Nc, Symmetric > SpTwoIndexSymmMatrices
Sp_TwoIndex< Nc, AntiSymmetric > SpTwoIndexAntiSymmMatrices
Sp_TwoIndex< 4, Symmetric > Sp4TwoIndexSymm
GaugeGroupTwoIndex< ncolour, S, GroupName::Sp > Sp_TwoIndex
SU_TwoIndex< 3, Symmetric > SU3TwoIndexSymm
SU_TwoIndex< 4, Symmetric > SU4TwoIndexSymm
SU_TwoIndex< 4, AntiSymmetric > SU4TwoIndexAntiSymm
constexpr Real delta(int a, int b)
accelerator_inline void timesI(Grid_simd2< S, V > &ret, const Grid_simd2< S, V > &in)
accelerator_inline Grid_simd2< S, V > trace(const Grid_simd2< S, V > &arg)
accelerator_inline Grid_simd< S, V > sqrt(const Grid_simd< S, V > &r)
void conformable(const Lattice< obj1 > &lhs, const Lattice< obj2 > &rhs)
Lattice< vobj > real(const Lattice< vobj > &lhs)
Lattice< vobj > imag(const Lattice< vobj > &lhs)
Lattice< vobj > adj(const Lattice< vobj > &lhs)
RealD norm2(const Lattice< vobj > &arg)
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
static constexpr int Nd
Definition QCD.h:52
auto peekColour(const vobj &rhs, int i) -> decltype(PeekIndex< ColourIndex >(rhs, 0))
Definition QCD.h:429
void pokeColour(Lattice< vobj > &lhs, const Lattice< decltype(peekIndex< ColourIndex >(vobj(), 0))> &rhs, int i)
Definition QCD.h:459
RealF Real
Definition Simd.h:65
std::complex< Real > Complex
Definition Simd.h:80
double RealD
Definition Simd.h:61
accelerator_inline std::enable_if<!isGridTensor< T >::value, T >::type TensorRemove(T arg)
accelerator_inline ComplexD transpose(ComplexD &rhs)
uint64_t base
static void baseOffDiagonal(int i, int j, iGroupMatrix< cplx > &eij, GroupName::Sp)
static void generator(int Index, iGroupTwoIndexMatrix< cplx > &i2indTa)
static void baseDiagonal(int Index, iGroupMatrix< cplx > &eij)
Lattice< vTIMatrixD > LatticeTwoIndexMatrixD
Lattice< vTIMatrixF > LatticeTwoIndexMatrixF
iScalar< iScalar< iMatrix< vtype, ncolour > > > iGroupMatrix
iGroupMatrix< ComplexF > MatrixF
static const int DimensionAS
iScalar< iScalar< iMatrix< vtype, Dimension > > > iGroupTwoIndexMatrix
iGroupTwoIndexMatrix< vComplexD > vTIMatrixD
static void TwoIndexLieAlgebraMatrix(const typename GaugeGroup< ncolour, group_name >::LatticeAlgebraVector &h, LatticeTwoIndexMatrix &out, Real scale=1.0)
static void testGenerators(void)
iGroupMatrix< Complex > Matrix
Lattice< iVector< iScalar< iMatrix< vComplexF, Dimension > >, Nd > > LatticeTwoIndexFieldF
static void base(int Index, iGroupMatrix< cplx > &eij)
iGroupTwoIndexMatrix< Complex > TIMatrix
iGroupTwoIndexMatrix< vComplexF > vTIMatrixF
Lattice< vTIMatrix > LatticeTwoIndexMatrix
static void projector(typename GaugeGroup< ncolour, group_name >::LatticeAlgebraVector &h_out, const LatticeTwoIndexMatrix &in, Real scale=1.0)
iGroupMatrix< ComplexD > MatrixD
static void projectOnAlgebra(typename GaugeGroup< ncolour, group_name >::LatticeAlgebraVector &h_out, const LatticeTwoIndexMatrix &in, Real scale=1.0)
Lattice< iVector< iScalar< iMatrix< vComplex, Dimension > >, Nd > > LatticeTwoIndexField
static const int DimensionS
iGroupTwoIndexMatrix< ComplexF > TIMatrixF
iGroupTwoIndexMatrix< vComplex > vTIMatrix
Lattice< iVector< iScalar< iMatrix< vComplexD, Dimension > >, Nd > > LatticeTwoIndexFieldD
static void printGenerators(void)
static void printBase(void)
static void baseOffDiagonal(int i, int j, iGroupMatrix< cplx > &eij, GroupName::SU)
iGroupTwoIndexMatrix< ComplexD > TIMatrixD
static const int NumGenerators
Lattice< vAlgebraVector > LatticeAlgebraVector
Definition GaugeGroup.h:135
static const int AlgebraDimension
Definition GaugeGroup.h:94
static void generator(int lieIndex, iGroupMatrix< cplx > &ta, GroupName::SU)
Definition GaugeGroup.h:66
GridBase * Grid(void) const
Definition Simd.h:194
static void baseOffDiagonalSp(int i, int j, iScalar< iScalar< iMatrix< cplx, nc > > > &eij)
static void baseOffDiagonalSp(int i, int j, iScalar< iScalar< iMatrix< cplx, nc > > > &eij)