#ifndef QCD_UTIL_SUN_H #define QCD_UTIL_SUN_H namespace Grid { namespace QCD { template class SU { public: static int generators(void) { return ncolour*ncolour-1; } static int su2subgroups(void) { return (ncolour*(ncolour-1))/2; } template using iSUnMatrix = iScalar > > ; ////////////////////////////////////////////////////////////////////////////////////////////////// // Types can be accessed as SU<2>::Matrix , SU<2>::vSUnMatrix, SU<2>::LatticeMatrix etc... ////////////////////////////////////////////////////////////////////////////////////////////////// typedef iSUnMatrix Matrix; typedef iSUnMatrix MatrixF; typedef iSUnMatrix MatrixD; typedef iSUnMatrix vMatrix; typedef iSUnMatrix vMatrixF; typedef iSUnMatrix vMatrixD; typedef Lattice LatticeMatrix; typedef Lattice LatticeMatrixF; typedef Lattice LatticeMatrixD; //////////////////////////////////////////////////////////////////////// // There are N^2-1 generators for SU(N). // // We take a traceless hermitian generator basis as follows // // * Normalisation: trace ta tb = 1/2 delta_ab // // * Off diagonal // - pairs of rows i1,i2 behaving like pauli matrices signma_x, sigma_y // // - there are (Nc-1-i1) slots for i2 on each row [ x 0 x ] // direct count off each row // // - Sum of all pairs is Nc(Nc-1)/2: proof arithmetic series // // (Nc-1) + (Nc-2)+... 1 ==> Nc*(Nc-1)/2 // 1+ 2+ + + Nc-1 // // - There are 2 x Nc (Nc-1)/ 2 of these = Nc^2 - Nc // // - We enumerate the row-col pairs. // - for each row col pair there is a (sigma_x) and a (sigma_y) like generator // // // t^a_ij = { in 0.. Nc(Nc-1)/2 -1} => delta_{i,i1} delta_{j,i2} + delta_{i,i1} delta_{j,i2} // t^a_ij = { in Nc(Nc-1)/2 ... Nc^(Nc-1) -1} => i delta_{i,i1} delta_{j,i2} - i delta_{i,i1} delta_{j,i2} // // * Diagonal; must be traceless and normalised // - Sequence is // N (1,-1,0,0...) // N (1, 1,-2,0...) // N (1, 1, 1,-3,0...) // N (1, 1, 1, 1,-4,0...) // // where 1/2 = N^2 (1+.. m^2)etc.... for the m-th diagonal generator // NB this gives the famous SU3 result for su2 index 8 // // N= sqrt(1/2 . 1/6 ) = 1/2 . 1/sqrt(3) // // ( 1 ) // ( 1 ) / sqrt(3) /2 = 1/2 lambda_8 // ( -2) //////////////////////////////////////////////////////////////////////// template static void generator(int lieIndex,iSUnMatrix &ta){ // map lie index to which type of generator int diagIndex; int su2Index; int sigxy; int NNm1 = ncolour*(ncolour-1); if ( lieIndex>= NNm1 ) { diagIndex = lieIndex -NNm1; generatorDiagonal(diagIndex,ta); return; } sigxy = lieIndex&0x1; su2Index= lieIndex>>1; if ( sigxy ) generatorSigmaY(su2Index,ta); else generatorSigmaX(su2Index,ta); } template static void generatorSigmaX(int su2Index,iSUnMatrix &ta){ ta=zero; int i1,i2; su2SubGroupIndex(i1,i2,su2Index); ta()()(i1,i2)=1.0; ta()()(i2,i1)=1.0; ta= ta *0.5; } template static void generatorSigmaY(int su2Index,iSUnMatrix &ta){ ta=zero; cplx i(0.0,1.0); int i1,i2; su2SubGroupIndex(i1,i2,su2Index); ta()()(i1,i2)=-i; ta()()(i2,i1)= i; ta= ta *0.5; } template static void generatorDiagonal(int diagIndex,iSUnMatrix &ta){ ta=zero; int trsq=0; int last=diagIndex+1; for(int i=0;i<=diagIndex;i++){ ta()()(i,i) = 1.0; trsq++; } ta()()(last,last) = -last; trsq+=last*last; RealD nrm = 1.0/std::sqrt(2.0*trsq); ta = ta *nrm; } //////////////////////////////////////////////////////////////////////// // Map a su2 subgroup number to the pair of rows that are non zero //////////////////////////////////////////////////////////////////////// static void su2SubGroupIndex(int &i1,int &i2,int su2_index){ assert( (su2_index>=0) && (su2_index< (ncolour*(ncolour-1))/2) ); int spare=su2_index; for(i1=0;spare >= (ncolour-1-i1);i1++ ){ spare = spare - (ncolour-1-i1); // remove the Nc-1-i1 terms } i2=i1+1+spare; } template static void su2Extract(std::vector > > &r, const Lattice > &source, int su2_index) { GridBase *grid(source._grid); assert(r.size() == 4); // store in 4 real parts for(int i=0;i<4;i++){ conformable(r[i],source); } int i1,i2; su2SubGroupIndex(i1,i2,su2_index); /* Compute the b(k) of A_SU(2) = b0 + i sum_k bk sigma_k */ // r[0] = toReal(real(peekColour(source,i1,i1)) + real(peekColour(source,i2,i2))); // r[1] = toReal(imag(peekColour(source,i1,i2)) + imag(peekColour(source,i2,i1))); // r[2] = toReal(real(peekColour(source,i1,i2)) - real(peekColour(source,i2,i1))); // r[3] = toReal(imag(peekColour(source,i1,i1)) - imag(peekColour(source,i2,i2))); r[0] = toReal(real(peekColour(source,i1,i1)) + real(peekColour(source,i2,i2))); r[1] = toReal(imag(peekColour(source,i1,i2)) + imag(peekColour(source,i2,i1))); r[2] = toReal(real(peekColour(source,i1,i2)) - real(peekColour(source,i2,i1))); r[3] = toReal(imag(peekColour(source,i1,i1)) - imag(peekColour(source,i2,i2))); } template static void su2Insert(const std::vector > > &r, Lattice > &dest, int su2_index) { typedef typename Lattice >::scalar_type cplx; typedef Lattice > Lcomplex; GridBase * grid = dest._grid; assert(r.size() == 4); // store in 4 real parts Lcomplex tmp(grid); std::vector cr(4,grid); for(int i=0;i r(4,grid); std::vector a(4,grid); su2Extract(r,V,su2_subgroup); // HERE LatticeReal r_l(grid); r_l = r[0]*r[0]+r[1]*r[1]+r[2]*r[2]+r[3]*r[3]; r_l = sqrt(r_l); LatticeReal ftmp(grid); LatticeReal ftmp1(grid); LatticeReal ftmp2(grid); LatticeReal one (grid); one = 1.0; LatticeReal zz (grid); zz = zero; LatticeReal recip(grid); recip = one/r_l; Real machine_epsilon= 1.0e-14; ftmp = where(r_l>machine_epsilon,recip,one); a[0] = where(r_l>machine_epsilon, r[0] * ftmp , one); a[1] = where(r_l>machine_epsilon, -(r[1] * ftmp), zz); a[2] = where(r_l>machine_epsilon, -(r[2] * ftmp), zz); a[3] = where(r_l>machine_epsilon, -(r[3] * ftmp), zz); r_l *= beta / ncolour; ftmp1 = where(wheremask,one,zz); Real num_sites = TensorRemove(sum(ftmp1)); Integer itrials = (Integer)num_sites; ntrials = 0; nfails = 0; LatticeInteger lupdate(grid); LatticeInteger lbtmp(grid); LatticeInteger lbtmp2(grid); lbtmp2=zero; int n_done = 0; int nhb = 0; r[0] = a[0]; lupdate = 1; LatticeReal ones (grid); ones = 1.0; LatticeReal zeros(grid); zeros=zero; const RealD twopi=2.0*M_PI; while ( nhb < nheatbath && n_done < num_sites ) { ntrials += itrials; random(pRNG,r[1]); std::cout<<"RANDOM SPARSE FLOAT r[1]"< b(4,grid); b[0] = r[0]*a[0] - r[1]*a[1] - r[2]*a[2] - r[3]*a[3]; b[1] = r[0]*a[1] + r[1]*a[0] - r[2]*a[3] + r[3]*a[2]; b[2] = r[0]*a[2] + r[2]*a[0] - r[3]*a[1] + r[1]*a[3]; b[3] = r[0]*a[3] + r[3]*a[0] - r[1]*a[2] + r[2]*a[1]; // // Now fill an SU(3) matrix V with the SU(2) submatrix su2_index // parametrized by a_k in the sigma matrix basis. // su2Insert(b,V,su2_subgroup); // U = V*U LatticeMatrix tmp(grid); tmp = V * link; //mask the assignment back link = where(wheremask,tmp,link); } static void printGenerators(void) { for(int gen=0;gen SU2; typedef SU<3> SU3; typedef SU<4> SU4; typedef SU<5> SU5; } } #endif