Grid 0.7.0
StoutSmearing.h
Go to the documentation of this file.
1/*************************************************************************************
2
3 Grid physics library, www.github.com/paboyle/Grid
4
5 Source file: ./lib/qcd/smearing/StoutSmearing.h
6
7 Copyright (C) 2019
8
9 Author: unknown
10 Author: Felix Erben <ferben@ed.ac.uk>
11 Author: Michael Marshall <Michael.Marshall@ed.ac.uk>
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License along
24 with this program; if not, write to the Free Software Foundation, Inc.,
25 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26
27 See the full license in the file "LICENSE" in the top level distribution
28 directory
29 *************************************************************************************/
30/*
31 @file StoutSmearing.h
32 @brief Declares Stout smearing class
33*/
34#pragma once
35
37
39template <class Gimpl>
40class Smear_Stout : public Smear<Gimpl> {
41 private:
42 int OrthogDim = -1;
43public:
44 const std::vector<double> SmearRho;
45private:
46 // Smear<Gimpl>* ownership semantics:
47 // Smear<Gimpl>* passed in to constructor are owned by caller, so we don't delete them here
48 // Smear<Gimpl>* created within constructor need to be deleted as part of the destructor
49 const std::unique_ptr<Smear<Gimpl>> OwnedBase; // deleted at destruction
50 const Smear<Gimpl>* SmearBase; // Not owned by this object, so not deleted at destruction
51
52 // only anticipated to be used from default constructor
53 inline static std::vector<double> rho3D(double rho, int orthogdim){
54 std::vector<double> rho3d(Nd*Nd);
55 for (int mu=0; mu<Nd; mu++)
56 for (int nu=0; nu<Nd; nu++)
57 rho3d[mu + Nd * nu] = (mu == nu || mu == orthogdim || nu == orthogdim) ? 0.0 : rho;
58 return rho3d;
59 };
60
61public:
63
64
66 assert(Nc == 3 && "Stout smearing currently implemented only for Nc==3");
67 }
68
70 Smear_Stout(const std::vector<double>& rho_)
71 : OwnedBase{new Smear_APE<Gimpl>(rho_)}, SmearBase{OwnedBase.get()} {
72 std::cout << GridLogDebug << "Stout smearing constructor : Smear_Stout(const std::vector<double>& " << rho_ << " )" << std::endl;
73 assert(Nc == 3 && "Stout smearing currently implemented only for Nc==3");
74 }
75
77 Smear_Stout(double rho = 1.0, int orthogdim = -1)
78 : OrthogDim{orthogdim}, SmearRho{ rho3D(rho,orthogdim) }, OwnedBase{ new Smear_APE<Gimpl>(SmearRho) }, SmearBase{OwnedBase.get()} {
79 assert(Nc == 3 && "Stout smearing currently implemented only for Nc==3");
80 }
81
82 ~Smear_Stout() {} // delete SmearBase...
83
84 void smear(GaugeField& u_smr, const GaugeField& U) const {
85 GaugeField C(U.Grid());
86 GaugeLinkField tmp(U.Grid()), iq_mu(U.Grid()), Umu(U.Grid());
87
88 std::cout << GridLogDebug << "Stout smearing started\n";
89
90 // C contains the staples multiplied by some rho
91 u_smr = U ; // set the smeared field to the current gauge field
92 SmearBase->smear(C, U);
93
94 for (int mu = 0; mu < Nd; mu++) {
95 if( mu == OrthogDim ) continue ;
96 // u_smr = exp(iQ_mu)*U_mu apart from Orthogdim
97 Umu = peekLorentz(U, mu);
98 tmp = peekLorentz(C, mu);
99 iq_mu = Ta( tmp * adj(Umu));
100 exponentiate_iQ(tmp, iq_mu);
101 pokeLorentz(u_smr, tmp * Umu, mu);
102 }
103 std::cout << GridLogDebug << "Stout smearing completed\n";
104 };
105
106 void derivative(GaugeField& SigmaTerm, const GaugeField& iLambda,
107 const GaugeField& Gauge) const {
108 SmearBase->derivative(SigmaTerm, iLambda, Gauge);
109 };
110
111 void BaseSmear(GaugeField& C, const GaugeField& U) const {
112 SmearBase->smear(C, U);
113 };
114
115
116 // Repetion of code here (use the Tensor_exp.h function)
117 void exponentiate_iQ(GaugeLinkField& e_iQ, const GaugeLinkField& iQ) const {
118 // Put this outside
119 // only valid for SU(3) matrices
120
121 // only one Lorentz direction at a time
122
123 // notice that it actually computes
124 // exp ( input matrix )
125 // the i sign is coming from outside
126 // input matrix is anti-hermitian NOT hermitian
127
128 GridBase* grid = iQ.Grid();
129 GaugeLinkField unity(grid);
130 unity = 1.0;
131
132 GaugeLinkField iQ2(grid), iQ3(grid);
133 LatticeComplex u(grid), w(grid);
134 LatticeComplex f0(grid), f1(grid), f2(grid);
135
136 iQ2 = iQ * iQ;
137 iQ3 = iQ * iQ2;
138
139 //We should check sgn(c0) here already and then apply eq (34) from 0311018
140 set_uw(u, w, iQ2, iQ3);
141 set_fj(f0, f1, f2, u, w);
142
143 e_iQ = f0 * unity + timesMinusI(f1) * iQ - f2 * iQ2;
144 };
145
146 void set_uw(LatticeComplex& u, LatticeComplex& w, GaugeLinkField& iQ2,
147 GaugeLinkField& iQ3) const {
148 Complex one_over_three = 1.0 / 3.0;
149 Complex one_over_two = 1.0 / 2.0;
150
151 GridBase* grid = u.Grid();
152 LatticeComplex c0(grid), c1(grid), tmp(grid), c0max(grid), theta(grid);
153
154 // sign in c0 from the conventions on the Ta
155 c0 = -imag(trace(iQ3)) * one_over_three;
156 c1 = -real(trace(iQ2)) * one_over_two;
157
158 // Cayley Hamilton checks to machine precision, tested
159 tmp = c1 * one_over_three;
160 c0max = 2.0 * pow(tmp, 1.5);
161
162 theta = acos(c0 / c0max) *
163 one_over_three; // divide by three here, now leave as it is
164 u = sqrt(tmp) * cos(theta);
165 w = sqrt(c1) * sin(theta);
166 }
167
169 const LatticeComplex& u, const LatticeComplex& w) const {
170 GridBase* grid = u.Grid();
171 LatticeComplex xi0(grid), u2(grid), w2(grid), cosw(grid);
172 LatticeComplex fden(grid);
173 LatticeComplex h0(grid), h1(grid), h2(grid);
174 LatticeComplex e2iu(grid), emiu(grid), ixi0(grid), qt(grid);
175 LatticeComplex unity(grid);
176 unity = 1.0;
177
178 xi0 = func_xi0(w);
179 u2 = u * u;
180 w2 = w * w;
181 cosw = cos(w);
182
183 ixi0 = timesI(xi0);
184 emiu = cos(u) - timesI(sin(u));
185 e2iu = cos(2.0 * u) + timesI(sin(2.0 * u));
186
187 h0 = e2iu * (u2 - w2) +
188 emiu * ((8.0 * u2 * cosw) + (2.0 * u * (3.0 * u2 + w2) * ixi0));
189 h1 = e2iu * (2.0 * u) - emiu * ((2.0 * u * cosw) - (3.0 * u2 - w2) * ixi0);
190 h2 = e2iu - emiu * (cosw + (3.0 * u) * ixi0);
191
192 fden = unity / (9.0 * u2 - w2); // reals
193 f0 = h0 * fden;
194 f1 = h1 * fden;
195 f2 = h2 * fden;
196 }
197
199 // Definition from arxiv 0311018
200 //if (abs(w) < 0.05) {w2 = w*w; return 1.0 - w2/6.0 * (1.0-w2/20.0 * (1.0-w2/42.0));}
201 return sin(w) / w;
202 }
203
205 // Define a function to do the check
206 // if( w < 1e-4 ) std::cout << GridLogWarning << "[Smear_stout] w too small:
207 // "<< w <<"\n";
208 return cos(w) / (w * w) - sin(w) / (w * w * w);
209 }
210};
211
#define INHERIT_GIMPL_TYPES(GImpl)
accelerator_inline void timesMinusI(Grid_simd2< S, V > &ret, const Grid_simd2< S, V > &in)
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 > cos(const Grid_simd< S, V > &r)
accelerator_inline Grid_simd< S, V > sin(const Grid_simd< S, V > &r)
accelerator_inline Grid_simd< S, V > acos(const Grid_simd< S, V > &r)
accelerator_inline Grid_simd< S, V > sqrt(const Grid_simd< S, V > &r)
Lattice< vobj > real(const Lattice< vobj > &lhs)
Lattice< vobj > imag(const Lattice< vobj > &lhs)
Lattice< vobj > adj(const Lattice< vobj > &lhs)
Lattice< obj > pow(const Lattice< obj > &rhs_i, RealD y)
GridLogger GridLogDebug(1, "Debug", GridLogColours, "PURPLE")
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
void pokeLorentz(Lattice< vobj > &lhs, const Lattice< decltype(peekIndex< LorentzIndex >(vobj(), 0))> &rhs, int i)
Definition QCD.h:487
static constexpr int Nd
Definition QCD.h:52
static constexpr int Nc
Definition QCD.h:50
Lattice< vTComplex > LatticeComplex
Definition QCD.h:359
auto peekLorentz(const vobj &rhs, int i) -> decltype(PeekIndex< LorentzIndex >(rhs, 0))
Definition QCD.h:446
std::complex< Real > Complex
Definition Simd.h:80
accelerator_inline iScalar< vtype > Ta(const iScalar< vtype > &r)
Definition Tensor_Ta.h:45
uint64_t base
static INTERNAL_PRECISION U
Definition Zolotarev.cc:230
GridBase * Grid(void) const
APE type smearing of link variables.
Definition APEsmearing.h:39
void set_uw(LatticeComplex &u, LatticeComplex &w, GaugeLinkField &iQ2, GaugeLinkField &iQ3) const
const Smear< Gimpl > * SmearBase
static std::vector< double > rho3D(double rho, int orthogdim)
void set_fj(LatticeComplex &f0, LatticeComplex &f1, LatticeComplex &f2, const LatticeComplex &u, const LatticeComplex &w) const
const std::vector< double > SmearRho
Smear_Stout(const std::vector< double > &rho_)
LatticeComplex func_xi1(const LatticeComplex &w) const
void BaseSmear(GaugeField &C, const GaugeField &U) const
void smear(GaugeField &u_smr, const GaugeField &U) const
const std::unique_ptr< Smear< Gimpl > > OwnedBase
void derivative(GaugeField &SigmaTerm, const GaugeField &iLambda, const GaugeField &Gauge) const
LatticeComplex func_xi0(const LatticeComplex &w) const
void exponentiate_iQ(GaugeLinkField &e_iQ, const GaugeLinkField &iQ) const
Smear_Stout(double rho=1.0, int orthogdim=-1)
Smear_Stout(Smear< Gimpl > *base)