mirror of
https://github.com/paboyle/Grid.git
synced 2025-06-19 08:17:05 +01:00
Merge branch 'develop' into feature/scidac-wp1
This commit is contained in:
@ -129,6 +129,22 @@ public:
|
||||
virtual ~Action(){}
|
||||
};
|
||||
|
||||
template <class GaugeField >
|
||||
class EmptyAction : public Action <GaugeField>
|
||||
{
|
||||
virtual void refresh(const GaugeField& U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) { assert(0);}; // refresh pseudofermions
|
||||
virtual RealD S(const GaugeField& U) { return 0.0;}; // evaluate the action
|
||||
virtual void deriv(const GaugeField& U, GaugeField& dSdU) { assert(0); }; // evaluate the action derivative
|
||||
|
||||
///////////////////////////////
|
||||
// Logging
|
||||
///////////////////////////////
|
||||
virtual std::string action_name() { return std::string("Level Force Log"); };
|
||||
virtual std::string LogParameters() { return std::string("No parameters");};
|
||||
};
|
||||
|
||||
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
||||
#endif // ACTION_BASE_H
|
||||
|
@ -63,7 +63,9 @@ public:
|
||||
virtual void MooeeDag(const FermionField &in, FermionField &out) ;
|
||||
virtual void MooeeInv(const FermionField &in, FermionField &out) ;
|
||||
virtual void MooeeInvDag(const FermionField &in, FermionField &out) ;
|
||||
|
||||
virtual void M(const FermionField &in, FermionField &out) ;
|
||||
virtual void Mdag(const FermionField &in, FermionField &out) ;
|
||||
|
||||
private:
|
||||
RealD mu; // TwistedMass parameter
|
||||
|
||||
|
@ -280,20 +280,16 @@ void StaggeredKernels<Impl>::DhopImproved(StencilImpl &st, LebesgueOrder &lo,
|
||||
|
||||
if( interior && exterior ) {
|
||||
if (Opt == OptGeneric ) { KERNEL_CALL(DhopSiteGeneric,1); return;}
|
||||
#ifndef GRID_CUDA
|
||||
if (Opt == OptHandUnroll ) { KERNEL_CALL(DhopSiteHand,1); return;}
|
||||
#ifndef GRID_CUDA
|
||||
if (Opt == OptInlineAsm ) { ASM_CALL(DhopSiteAsm); return;}
|
||||
#endif
|
||||
} else if( interior ) {
|
||||
if (Opt == OptGeneric ) { KERNEL_CALL(DhopSiteGenericInt,1); return;}
|
||||
#ifndef GRID_CUDA
|
||||
if (Opt == OptHandUnroll ) { KERNEL_CALL(DhopSiteHandInt,1); return;}
|
||||
#endif
|
||||
} else if( exterior ) {
|
||||
if (Opt == OptGeneric ) { KERNEL_CALL(DhopSiteGenericExt,1); return;}
|
||||
#ifndef GRID_CUDA
|
||||
if (Opt == OptHandUnroll ) { KERNEL_CALL(DhopSiteHandExt,1); return;}
|
||||
#endif
|
||||
}
|
||||
assert(0 && " Kernel optimisation case not covered ");
|
||||
}
|
||||
@ -322,19 +318,13 @@ void StaggeredKernels<Impl>::DhopNaive(StencilImpl &st, LebesgueOrder &lo,
|
||||
|
||||
if( interior && exterior ) {
|
||||
if (Opt == OptGeneric ) { KERNEL_CALL(DhopSiteGeneric,0); return;}
|
||||
#ifndef GRID_CUDA
|
||||
if (Opt == OptHandUnroll ) { KERNEL_CALL(DhopSiteHand,0); return;}
|
||||
#endif
|
||||
} else if( interior ) {
|
||||
if (Opt == OptGeneric ) { KERNEL_CALL(DhopSiteGenericInt,0); return;}
|
||||
#ifndef GRID_CUDA
|
||||
if (Opt == OptHandUnroll ) { KERNEL_CALL(DhopSiteHandInt,0); return;}
|
||||
#endif
|
||||
} else if( exterior ) {
|
||||
if (Opt == OptGeneric ) { KERNEL_CALL(DhopSiteGenericExt,0); return;}
|
||||
#ifndef GRID_CUDA
|
||||
if (Opt == OptHandUnroll ) { KERNEL_CALL(DhopSiteHandExt,0); return;}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,5 +93,25 @@ void WilsonTMFermion<Impl>::MooeeInvDag(const FermionField &in, FermionField &ou
|
||||
RealD b = tm /sq;
|
||||
axpibg5x(out,in,a,b);
|
||||
}
|
||||
template<class Impl>
|
||||
void WilsonTMFermion<Impl>::M(const FermionField &in, FermionField &out) {
|
||||
out.Checkerboard() = in.Checkerboard();
|
||||
this->Dhop(in, out, DaggerNo);
|
||||
FermionField tmp(out.Grid());
|
||||
RealD a = 4.0+this->mass;
|
||||
RealD b = this->mu;
|
||||
axpibg5x(tmp,in,a,b);
|
||||
axpy(out, 1.0, tmp, out);
|
||||
}
|
||||
template<class Impl>
|
||||
void WilsonTMFermion<Impl>::Mdag(const FermionField &in, FermionField &out) {
|
||||
out.Checkerboard() = in.Checkerboard();
|
||||
this->Dhop(in, out, DaggerYes);
|
||||
FermionField tmp(out.Grid());
|
||||
RealD a = 4.0+this->mass;
|
||||
RealD b = -this->mu;
|
||||
axpibg5x(tmp,in,a,b);
|
||||
axpy(out, 1.0, tmp, out);
|
||||
}
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
@ -87,6 +87,8 @@ public:
|
||||
|
||||
const ActionSet<Field, RepresentationPolicy> as;
|
||||
|
||||
ActionSet<Field,RepresentationPolicy> LevelForces;
|
||||
|
||||
//Get a pointer to a shared static instance of the "do-nothing" momentum filter to serve as a default
|
||||
static MomentumFilterBase<MomentaField> const* getDefaultMomFilter(){
|
||||
static MomentumFilterNone<MomentaField> filter;
|
||||
@ -124,6 +126,9 @@ public:
|
||||
// input U actually not used in the fundamental case
|
||||
// Fundamental updates, include smearing
|
||||
|
||||
assert(as.size()==LevelForces.size());
|
||||
|
||||
Field level_force(U.Grid()); level_force =Zero();
|
||||
for (int a = 0; a < as[level].actions.size(); ++a) {
|
||||
|
||||
double start_full = usecond();
|
||||
@ -144,7 +149,10 @@ public:
|
||||
MomFilter->applyFilter(force);
|
||||
|
||||
std::cout << GridLogIntegrator << " update_P : Level [" << level <<"]["<<a <<"] "<<name<<" dt "<<ep<< std::endl;
|
||||
|
||||
|
||||
// track the total
|
||||
level_force = level_force+force;
|
||||
|
||||
Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites()); //average per-site norm. nb. norm2(latt) = \sum_x norm2(latt[x])
|
||||
Real impulse_abs = force_abs * ep * HMC_MOMENTUM_DENOMINATOR;
|
||||
|
||||
@ -167,6 +175,16 @@ public:
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
// total force
|
||||
Real force_abs = std::sqrt(norm2(level_force)/U.Grid()->gSites()); //average per-site norm. nb. norm2(latt) = \sum_x norm2(latt[x])
|
||||
Real impulse_abs = force_abs * ep * HMC_MOMENTUM_DENOMINATOR;
|
||||
|
||||
Real force_max = std::sqrt(maxLocalNorm2(level_force));
|
||||
Real impulse_max = force_max * ep * HMC_MOMENTUM_DENOMINATOR;
|
||||
LevelForces[level].actions.at(0)->deriv_log(force_abs,force_max,impulse_abs,impulse_max);
|
||||
}
|
||||
|
||||
// Force from the other representations
|
||||
as[level].apply(update_P_hireps, Representations, Mom, U, ep);
|
||||
|
||||
@ -216,6 +234,16 @@ public:
|
||||
|
||||
//Default the momentum filter to "do-nothing"
|
||||
MomFilter = getDefaultMomFilter();
|
||||
|
||||
for (int level = 0; level < as.size(); ++level) {
|
||||
int multiplier = as.at(level).multiplier;
|
||||
ActionLevel<Field, RepresentationPolicy> * Level = new ActionLevel<Field, RepresentationPolicy>(multiplier);
|
||||
Level->push_back(new EmptyAction<Field>);
|
||||
LevelForces.push_back(*Level);
|
||||
// does it copy by value or reference??
|
||||
// - answer it copies by value, BUT the action level contains a reference that is NOT updated.
|
||||
// Unsafe code in Guido's area
|
||||
}
|
||||
};
|
||||
|
||||
virtual ~Integrator() {}
|
||||
@ -233,10 +261,14 @@ public:
|
||||
|
||||
void reset_timer(void)
|
||||
{
|
||||
assert(as.size()==LevelForces.size());
|
||||
for (int level = 0; level < as.size(); ++level) {
|
||||
for (int actionID = 0; actionID < as[level].actions.size(); ++actionID) {
|
||||
as[level].actions.at(actionID)->reset_timer();
|
||||
}
|
||||
int actionID=0;
|
||||
assert(LevelForces.at(level).actions.size()==1);
|
||||
LevelForces.at(level).actions.at(actionID)->reset_timer();
|
||||
}
|
||||
}
|
||||
void print_timer(void)
|
||||
@ -298,6 +330,16 @@ public:
|
||||
<<" calls " << as[level].actions.at(actionID)->deriv_num
|
||||
<< std::endl;
|
||||
}
|
||||
int actionID=0;
|
||||
std::cout << GridLogMessage
|
||||
<< LevelForces[level].actions.at(actionID)->action_name()
|
||||
<<"["<<level<<"]["<< actionID<<"] :\n\t\t "
|
||||
<<" force max " << LevelForces[level].actions.at(actionID)->deriv_max_average()
|
||||
<<" norm " << LevelForces[level].actions.at(actionID)->deriv_norm_average()
|
||||
<<" Fdt max " << LevelForces[level].actions.at(actionID)->Fdt_max_average()
|
||||
<<" Fdt norm " << LevelForces[level].actions.at(actionID)->Fdt_norm_average()
|
||||
<<" calls " << LevelForces[level].actions.at(actionID)->deriv_num
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << GridLogMessage << ":::::::::::::::::::::::::::::::::::::::::"<< std::endl;
|
||||
}
|
||||
@ -319,6 +361,13 @@ public:
|
||||
std::cout << as[level].actions.at(actionID)->LogParameters();
|
||||
}
|
||||
}
|
||||
std::cout << " [Integrator] Total Force loggers: "<< LevelForces.size() <<std::endl;
|
||||
for (int level = 0; level < LevelForces.size(); ++level) {
|
||||
std::cout << GridLogMessage << "[Integrator] ---- Level: "<< level << std::endl;
|
||||
for (int actionID = 0; actionID < LevelForces[level].actions.size(); ++actionID) {
|
||||
std::cout << GridLogMessage << "["<< LevelForces[level].actions.at(actionID)->action_name() << "] ID: " << actionID << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << GridLogMessage << ":::::::::::::::::::::::::::::::::::::::::"<< std::endl;
|
||||
}
|
||||
|
||||
@ -400,6 +449,7 @@ public:
|
||||
RealD S(Field& U)
|
||||
{ // here also U not used
|
||||
|
||||
assert(as.size()==LevelForces.size());
|
||||
std::cout << GridLogIntegrator << "Integrator action\n";
|
||||
|
||||
RealD H = - FieldImplementation::FieldSquareNorm(P)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
/*!
|
||||
@file GaugeConfiguration.h
|
||||
@brief Declares the GaugeConfiguration class
|
||||
@ -6,6 +7,15 @@
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
|
||||
template<class T> void Dump(const Lattice<T> & lat,
|
||||
std::string s,
|
||||
Coordinate site = Coordinate({0,0,0,0}))
|
||||
{
|
||||
typename T::scalar_object tmp;
|
||||
peekSite(tmp,lat,site);
|
||||
std::cout << " Dump "<<s<<" "<<tmp<<std::endl;
|
||||
}
|
||||
/*!
|
||||
@brief Smeared configuration masked container
|
||||
Modified for a multi-subset smearing (aka Luscher Flowed HMC)
|
||||
@ -28,6 +38,101 @@ private:
|
||||
typedef typename SU3Adjoint::LatticeAdjMatrix AdjMatrixField;
|
||||
typedef typename SU3Adjoint::LatticeAdjVector AdjVectorField;
|
||||
|
||||
void BaseSmearDerivative(GaugeField& SigmaTerm,
|
||||
const GaugeField& iLambda,
|
||||
const GaugeField& U,
|
||||
int mmu, RealD rho)
|
||||
{
|
||||
// Reference
|
||||
// Morningstar, Peardon, Phys.Rev.D69,054501(2004)
|
||||
// Equation 75
|
||||
// Computing Sigma_mu, derivative of S[fat links] with respect to the thin links
|
||||
// Output SigmaTerm
|
||||
|
||||
GridBase *grid = U.Grid();
|
||||
|
||||
WilsonLoops<Gimpl> WL;
|
||||
GaugeLinkField staple(grid), u_tmp(grid);
|
||||
GaugeLinkField iLambda_mu(grid), iLambda_nu(grid);
|
||||
GaugeLinkField U_mu(grid), U_nu(grid);
|
||||
GaugeLinkField sh_field(grid), temp_Sigma(grid);
|
||||
Real rho_munu, rho_numu;
|
||||
|
||||
rho_munu = rho;
|
||||
rho_numu = rho;
|
||||
for(int mu = 0; mu < Nd; ++mu){
|
||||
U_mu = peekLorentz( U, mu);
|
||||
iLambda_mu = peekLorentz(iLambda, mu);
|
||||
|
||||
for(int nu = 0; nu < Nd; ++nu){
|
||||
if(nu==mu) continue;
|
||||
|
||||
U_nu = peekLorentz( U, nu);
|
||||
|
||||
// Nd(nd-1) = 12 staples normally.
|
||||
// We must compute 6 of these
|
||||
// in FTHMC case
|
||||
if ( (mu==mmu)||(nu==mmu) )
|
||||
WL.StapleUpper(staple, U, mu, nu);
|
||||
|
||||
if(nu==mmu) {
|
||||
iLambda_nu = peekLorentz(iLambda, nu);
|
||||
|
||||
temp_Sigma = -rho_numu*staple*iLambda_nu; //ok
|
||||
//-r_numu*U_nu(x+mu)*Udag_mu(x+nu)*Udag_nu(x)*Lambda_nu(x)
|
||||
Gimpl::AddLink(SigmaTerm, temp_Sigma, mu);
|
||||
|
||||
sh_field = Cshift(iLambda_nu, mu, 1);// general also for Gparity?
|
||||
|
||||
temp_Sigma = rho_numu*sh_field*staple; //ok
|
||||
//r_numu*Lambda_nu(mu)*U_nu(x+mu)*Udag_mu(x+nu)*Udag_nu(x)
|
||||
Gimpl::AddLink(SigmaTerm, temp_Sigma, mu);
|
||||
}
|
||||
|
||||
if ( mu == mmu ) {
|
||||
sh_field = Cshift(iLambda_mu, nu, 1);
|
||||
|
||||
temp_Sigma = -rho_munu*staple*U_nu*sh_field*adj(U_nu); //ok
|
||||
//-r_munu*U_nu(x+mu)*Udag_mu(x+nu)*Lambda_mu(x+nu)*Udag_nu(x)
|
||||
Gimpl::AddLink(SigmaTerm, temp_Sigma, mu);
|
||||
}
|
||||
|
||||
// staple = Zero();
|
||||
sh_field = Cshift(U_nu, mu, 1);
|
||||
|
||||
temp_Sigma = Zero();
|
||||
|
||||
if ( mu == mmu )
|
||||
temp_Sigma = -rho_munu*adj(sh_field)*adj(U_mu)*iLambda_mu*U_nu;
|
||||
|
||||
if ( nu == mmu ) {
|
||||
temp_Sigma += rho_numu*adj(sh_field)*adj(U_mu)*iLambda_nu*U_nu;
|
||||
|
||||
u_tmp = adj(U_nu)*iLambda_nu;
|
||||
sh_field = Cshift(u_tmp, mu, 1);
|
||||
temp_Sigma += -rho_numu*sh_field*adj(U_mu)*U_nu;
|
||||
}
|
||||
|
||||
sh_field = Cshift(temp_Sigma, nu, -1);
|
||||
Gimpl::AddLink(SigmaTerm, sh_field, mu);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BaseSmear(GaugeLinkField& Cup, const GaugeField& U,int mu,RealD rho) {
|
||||
GridBase *grid = U.Grid();
|
||||
GaugeLinkField tmp_stpl(grid);
|
||||
WilsonLoops<Gimpl> WL;
|
||||
Cup = Zero();
|
||||
for(int nu=0; nu<Nd; ++nu){
|
||||
if (nu != mu) {
|
||||
// get the staple in direction mu, nu
|
||||
WL.Staple(tmp_stpl, U, mu, nu); //nb staple conventions of IroIro and Grid differ by a dagger
|
||||
Cup += adj(tmp_stpl*rho);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Adjoint vector to GaugeField force
|
||||
void InsertForce(GaugeField &Fdet,AdjVectorField &Fdet_nu,int nu)
|
||||
{
|
||||
@ -47,27 +152,54 @@ private:
|
||||
GaugeLinkField UtaU(PlaqL.Grid());
|
||||
GaugeLinkField D(PlaqL.Grid());
|
||||
AdjMatrixField Dbc(PlaqL.Grid());
|
||||
AdjMatrixField Dbc_opt(PlaqL.Grid());
|
||||
LatticeComplex tmp(PlaqL.Grid());
|
||||
const int Ngen = SU3Adjoint::Dimension;
|
||||
Complex ci(0,1);
|
||||
ColourMatrix ta,tb,tc;
|
||||
|
||||
RealD t=0;
|
||||
RealD tp=0;
|
||||
RealD tta=0;
|
||||
RealD tpk=0;
|
||||
t-=usecond();
|
||||
for(int a=0;a<Ngen;a++) {
|
||||
tta-=usecond();
|
||||
SU3::generator(a, ta);
|
||||
ta = 2.0 * ci * ta;
|
||||
// Qlat Tb = 2i Tb^Grid
|
||||
UtaU= 2.0*ci*adj(PlaqL)*ta*PlaqR;
|
||||
UtaU= adj(PlaqL)*ta*PlaqR; // 6ms
|
||||
tta+=usecond();
|
||||
////////////////////////////////////////////
|
||||
// Could add this entire C-loop to a projection routine
|
||||
// for performance. Could also pick checkerboard on UtaU
|
||||
// and set checkerboard on result for 2x perf
|
||||
////////////////////////////////////////////
|
||||
for(int c=0;c<Ngen;c++) {
|
||||
SU3::generator(c, tc);
|
||||
D = Ta( (2.0)*ci*tc *UtaU);
|
||||
tc = 2.0*ci*tc;
|
||||
tp-=usecond();
|
||||
D = Ta( tc *UtaU); // 2ms
|
||||
#if 1
|
||||
SU3::LieAlgebraProject(Dbc_opt,D,c); // 5.5ms
|
||||
#else
|
||||
for(int b=0;b<Ngen;b++){
|
||||
SU3::generator(b, tb);
|
||||
tmp =-trace(ci*tb*D);
|
||||
PokeIndex<ColourIndex>(Dbc,tmp,b,c); // Adjoint rep
|
||||
}
|
||||
#endif
|
||||
tp+=usecond();
|
||||
}
|
||||
tmp = trace(MpInvJx * Dbc);
|
||||
// Dump(Dbc_opt,"Dbc_opt");
|
||||
// Dump(Dbc,"Dbc");
|
||||
tpk-=usecond();
|
||||
tmp = trace(MpInvJx * Dbc_opt);
|
||||
PokeIndex<ColourIndex>(Fdet2,tmp,a);
|
||||
tpk+=usecond();
|
||||
}
|
||||
t+=usecond();
|
||||
std::cout << GridLogPerformance << " Compute_MpInvJx_dNxxdSy " << t/1e3 << " ms proj "<<tp/1e3<< " ms"
|
||||
<< " ta "<<tta/1e3<<" ms" << " poke "<<tpk/1e3<< " ms"<<std::endl;
|
||||
}
|
||||
|
||||
void ComputeNxy(const GaugeLinkField &PlaqL,const GaugeLinkField &PlaqR,AdjMatrixField &NxAd)
|
||||
@ -79,12 +211,17 @@ private:
|
||||
ColourMatrix tc;
|
||||
for(int b=0;b<Ngen;b++) {
|
||||
SU3::generator(b, tb);
|
||||
Nx = (2.0)*Ta( adj(PlaqL)*ci*tb * PlaqR );
|
||||
tb = 2.0 * ci * tb;
|
||||
Nx = Ta( adj(PlaqL)*tb * PlaqR );
|
||||
#if 1
|
||||
SU3::LieAlgebraProject(NxAd,Nx,b);
|
||||
#else
|
||||
for(int c=0;c<Ngen;c++) {
|
||||
SU3::generator(c, tc);
|
||||
auto tmp =closure( -trace(ci*tc*Nx));
|
||||
PokeIndex<ColourIndex>(NxAd,tmp,c,b);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void ApplyMask(GaugeField &U,int smr)
|
||||
@ -164,8 +301,7 @@ public:
|
||||
// Computes ALL the staples -- could compute one only and do it here
|
||||
RealD time;
|
||||
time=-usecond();
|
||||
this->StoutSmearing->BaseSmear(C, U);
|
||||
Cmu = peekLorentz(C, mu);
|
||||
BaseSmear(Cmu, U,mu,rho);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Assemble Luscher exp diff map J matrix
|
||||
@ -209,6 +345,36 @@ public:
|
||||
// dJ(x)/dxe
|
||||
//////////////////////////////////////
|
||||
time=-usecond();
|
||||
#if 1
|
||||
std::vector<AdjMatrixField> dJdX; dJdX.resize(8,grid);
|
||||
std::vector<AdjMatrix> TRb_s; TRb_s.resize(8);
|
||||
AdjMatrixField tbXn(grid);
|
||||
AdjMatrixField sumXtbX(grid);
|
||||
AdjMatrixField t2(grid);
|
||||
AdjMatrixField dt2(grid);
|
||||
AdjMatrixField t3(grid);
|
||||
AdjMatrixField dt3(grid);
|
||||
AdjMatrixField aunit(grid);
|
||||
|
||||
for(int b=0;b<8;b++){
|
||||
SU3Adjoint::generator(b, TRb_s[b]);
|
||||
dJdX[b] = TRb_s[b];
|
||||
}
|
||||
aunit = ComplexD(1.0);
|
||||
// Could put into an accelerator_for
|
||||
X = (-1.0)*ZxAd;
|
||||
t2 = X;
|
||||
for (int j = 12; j > 1; --j) {
|
||||
t3 = t2*(1.0 / (j + 1)) + aunit;
|
||||
t2 = X * t3;
|
||||
for(int b=0;b<8;b++){
|
||||
dJdX[b]= TRb_s[b] * t3 + X * dJdX[b]*(1.0 / (j + 1));
|
||||
}
|
||||
}
|
||||
for(int b=0;b<8;b++){
|
||||
dJdX[b] = -dJdX[b];
|
||||
}
|
||||
#else
|
||||
std::vector<AdjMatrixField> dJdX; dJdX.resize(8,grid);
|
||||
AdjMatrixField tbXn(grid);
|
||||
AdjMatrixField sumXtbX(grid);
|
||||
@ -224,14 +390,15 @@ public:
|
||||
X = (-1.0)*ZxAd;
|
||||
t2 = X;
|
||||
dt2 = TRb;
|
||||
for (int j = 20; j > 1; --j) {
|
||||
t3 = t2*(1.0 / (j + 1)) + aunit;
|
||||
for (int j = 12; j > 1; --j) {
|
||||
t3 = t2*(1.0 / (j + 1)) + aunit;
|
||||
dt3 = dt2*(1.0 / (j + 1));
|
||||
t2 = X * t3;
|
||||
dt2 = TRb * t3 + X * dt3;
|
||||
}
|
||||
dJdX[b] = -dt2;
|
||||
}
|
||||
#endif
|
||||
time+=usecond();
|
||||
std::cout << GridLogMessage << "dJx took "<<time<< " us"<<std::endl;
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@ -281,8 +448,8 @@ public:
|
||||
|
||||
for(int e =0 ; e<8 ; e++){
|
||||
LatticeComplexD tr(grid);
|
||||
ColourMatrix te;
|
||||
SU3::generator(e, te);
|
||||
// ColourMatrix te;
|
||||
// SU3::generator(e, te);
|
||||
tr = trace(dJdX[e] * nMpInv);
|
||||
pokeColour(dJdXe_nMpInv,tr,e);
|
||||
}
|
||||
@ -493,20 +660,25 @@ public:
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Assemble the N matrix
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Computes ALL the staples -- could compute one only here
|
||||
this->StoutSmearing->BaseSmear(C, U);
|
||||
Cmu = peekLorentz(C, mu);
|
||||
double rho=this->StoutSmearing->SmearRho[1];
|
||||
BaseSmear(Cmu, U,mu,rho);
|
||||
|
||||
Umu = peekLorentz(U, mu);
|
||||
Complex ci(0,1);
|
||||
for(int b=0;b<Ngen;b++) {
|
||||
SU3::generator(b, Tb);
|
||||
// Qlat Tb = 2i Tb^Grid
|
||||
Nb = (2.0)*Ta( ci*Tb * Umu * adj(Cmu));
|
||||
// FIXME -- replace this with LieAlgebraProject
|
||||
#if 0
|
||||
SU3::LieAlgebraProject(Ncb,tmp,b);
|
||||
#else
|
||||
for(int c=0;c<Ngen;c++) {
|
||||
SU3::generator(c, Tc);
|
||||
auto tmp = -trace(ci*Tc*Nb); // Luchang's norm: (2Tc) (2Td) N^db = -2 delta cd N^db // - was important
|
||||
PokeIndex<ColourIndex>(Ncb,tmp,c,b);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@ -693,15 +865,19 @@ private:
|
||||
const GaugeField& GaugeK,int level)
|
||||
{
|
||||
GridBase* grid = GaugeK.Grid();
|
||||
GaugeField C(grid), SigmaK(grid), iLambda(grid);
|
||||
GaugeField SigmaK(grid), iLambda(grid);
|
||||
GaugeField SigmaKPrimeA(grid);
|
||||
GaugeField SigmaKPrimeB(grid);
|
||||
GaugeLinkField iLambda_mu(grid);
|
||||
GaugeLinkField iQ(grid), e_iQ(grid);
|
||||
GaugeLinkField SigmaKPrime_mu(grid);
|
||||
GaugeLinkField GaugeKmu(grid), Cmu(grid);
|
||||
|
||||
this->StoutSmearing->BaseSmear(C, GaugeK);
|
||||
|
||||
int mmu= (level/2) %Nd;
|
||||
int cb= (level%2);
|
||||
double rho=this->StoutSmearing->SmearRho[1];
|
||||
|
||||
// Can override this to do one direction only.
|
||||
SigmaK = Zero();
|
||||
iLambda = Zero();
|
||||
|
||||
@ -712,18 +888,38 @@ private:
|
||||
// Could get away with computing only one polarisation here
|
||||
// int mu= (smr/2) %Nd;
|
||||
// SigmaKprime_A has only one component
|
||||
for (int mu = 0; mu < Nd; mu++)
|
||||
#if 0
|
||||
BaseSmear(Cmu, GaugeK,mu,rho);
|
||||
GaugeKmu = peekLorentz(GaugeK, mu);
|
||||
SigmaKPrime_mu = peekLorentz(SigmaKPrimeA, mu);
|
||||
iQ = Ta(Cmu * adj(GaugeKmu));
|
||||
this->set_iLambda(iLambda_mu, e_iQ, iQ, SigmaKPrime_mu, GaugeKmu);
|
||||
pokeLorentz(SigmaK, SigmaKPrime_mu * e_iQ + adj(Cmu) * iLambda_mu, mu);
|
||||
pokeLorentz(iLambda, iLambda_mu, mu);
|
||||
BaseSmearDerivative(SigmaK, iLambda,GaugeK,mu,rho); // derivative of SmearBase
|
||||
#else
|
||||
// GaugeField C(grid);
|
||||
// this->StoutSmearing->BaseSmear(C, GaugeK);
|
||||
// for (int mu = 0; mu < Nd; mu++)
|
||||
int mu =mmu;
|
||||
BaseSmear(Cmu, GaugeK,mu,rho);
|
||||
{
|
||||
Cmu = peekLorentz(C, mu);
|
||||
// Cmu = peekLorentz(C, mu);
|
||||
GaugeKmu = peekLorentz(GaugeK, mu);
|
||||
SigmaKPrime_mu = peekLorentz(SigmaKPrimeA, mu);
|
||||
iQ = Ta(Cmu * adj(GaugeKmu));
|
||||
this->set_iLambda(iLambda_mu, e_iQ, iQ, SigmaKPrime_mu, GaugeKmu);
|
||||
pokeLorentz(SigmaK, SigmaKPrime_mu * e_iQ + adj(Cmu) * iLambda_mu, mu);
|
||||
pokeLorentz(iLambda, iLambda_mu, mu);
|
||||
std::cout << " mu "<<mu<<" SigmaKPrime_mu"<<norm2(SigmaKPrime_mu)<< " iLambda_mu " <<norm2(iLambda_mu)<<std::endl;
|
||||
}
|
||||
this->StoutSmearing->derivative(SigmaK, iLambda,GaugeK); // derivative of SmearBase
|
||||
|
||||
// GaugeField SigmaKcopy(grid);
|
||||
// SigmaKcopy = SigmaK;
|
||||
BaseSmearDerivative(SigmaK, iLambda,GaugeK,mu,rho); // derivative of SmearBase
|
||||
// this->StoutSmearing->derivative(SigmaK, iLambda,GaugeK); // derivative of SmearBase
|
||||
// SigmaKcopy = SigmaKcopy - SigmaK;
|
||||
// std::cout << " BaseSmearDerivative fast path error" <<norm2(SigmaKcopy)<<std::endl;
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// propagate the rest of the force as identity map, just add back
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
389
Grid/qcd/smearing/HISQSmearing.h
Normal file
389
Grid/qcd/smearing/HISQSmearing.h
Normal file
@ -0,0 +1,389 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./lib/qcd/smearing/HISQSmearing.h
|
||||
|
||||
Copyright (C) 2023
|
||||
|
||||
Author: D. A. Clarke <clarke.davida@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution
|
||||
directory
|
||||
*************************************************************************************/
|
||||
/*
|
||||
@file HISQSmearing.h
|
||||
@brief Declares classes related to HISQ smearing
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <Grid/Grid.h>
|
||||
#include <Grid/lattice/PaddedCell.h>
|
||||
#include <Grid/stencil/GeneralLocalStencil.h>
|
||||
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
|
||||
// TODO: find a way to fold this into the stencil header. need to access grid to get
|
||||
// Nd, since you don't want to inherit from QCD.h
|
||||
/*! @brief append arbitrary shift path to shifts */
|
||||
template<typename... Args>
|
||||
void appendShift(std::vector<Coordinate>& shifts, int dir, Args... args) {
|
||||
Coordinate shift(Nd,0);
|
||||
generalShift(shift, dir, args...);
|
||||
// push_back creates an element at the end of shifts and
|
||||
// assigns the data in the argument to it.
|
||||
shifts.push_back(shift);
|
||||
}
|
||||
|
||||
|
||||
/*! @brief figure out the stencil index from mu and nu */
|
||||
accelerator_inline int stencilIndex(int mu, int nu) {
|
||||
// Nshifts depends on how you built the stencil
|
||||
int Nshifts = 6;
|
||||
return Nshifts*nu + Nd*Nshifts*mu;
|
||||
}
|
||||
|
||||
|
||||
/*! @brief structure holding the link treatment */
|
||||
struct SmearingParameters{
|
||||
SmearingParameters(){}
|
||||
Real c_1; // 1 link
|
||||
Real c_naik; // Naik term
|
||||
Real c_3; // 3 link
|
||||
Real c_5; // 5 link
|
||||
Real c_7; // 7 link
|
||||
Real c_lp; // 5 link Lepage
|
||||
SmearingParameters(Real c1, Real cnaik, Real c3, Real c5, Real c7, Real clp)
|
||||
: c_1(c1),
|
||||
c_naik(cnaik),
|
||||
c_3(c3),
|
||||
c_5(c5),
|
||||
c_7(c7),
|
||||
c_lp(clp){}
|
||||
};
|
||||
|
||||
|
||||
/*! @brief create fat links from link variables */
|
||||
template<class Gimpl>
|
||||
class Smear_HISQ : public Gimpl {
|
||||
|
||||
private:
|
||||
GridCartesian* const _grid;
|
||||
SmearingParameters _linkTreatment;
|
||||
|
||||
public:
|
||||
|
||||
INHERIT_GIMPL_TYPES(Gimpl);
|
||||
typedef typename Gimpl::GaugeField GF;
|
||||
typedef typename Gimpl::GaugeLinkField LF;
|
||||
typedef typename Gimpl::ComplexField CF;
|
||||
|
||||
// Don't allow default values here.
|
||||
Smear_HISQ(GridCartesian* grid, Real c1, Real cnaik, Real c3, Real c5, Real c7, Real clp)
|
||||
: _grid(grid),
|
||||
_linkTreatment(c1,cnaik,c3,c5,c7,clp) {
|
||||
assert(Nc == 3 && "HISQ smearing currently implemented only for Nc==3");
|
||||
assert(Nd == 4 && "HISQ smearing only defined for Nd==4");
|
||||
}
|
||||
|
||||
// Allow to pass a pointer to a C-style, double array for MILC convenience
|
||||
Smear_HISQ(GridCartesian* grid, double* coeff)
|
||||
: _grid(grid),
|
||||
_linkTreatment(coeff[0],coeff[1],coeff[2],coeff[3],coeff[4],coeff[5]) {
|
||||
assert(Nc == 3 && "HISQ smearing currently implemented only for Nc==3");
|
||||
assert(Nd == 4 && "HISQ smearing only defined for Nd==4");
|
||||
}
|
||||
|
||||
~Smear_HISQ() {}
|
||||
|
||||
// Intent: OUT--u_smr, u_naik
|
||||
// IN--u_thin
|
||||
void smear(GF& u_smr, GF& u_naik, GF& u_thin) const {
|
||||
|
||||
SmearingParameters lt = this->_linkTreatment;
|
||||
auto grid = this->_grid;
|
||||
|
||||
// Create a padded cell of extra padding depth=1 and fill the padding.
|
||||
int depth = 1;
|
||||
PaddedCell Ghost(depth,grid);
|
||||
GF Ughost = Ghost.Exchange(u_thin);
|
||||
|
||||
// This is where auxiliary N-link fields and the final smear will be stored.
|
||||
GF Ughost_fat(Ughost.Grid());
|
||||
GF Ughost_3link(Ughost.Grid());
|
||||
GF Ughost_5linkA(Ughost.Grid());
|
||||
GF Ughost_5linkB(Ughost.Grid());
|
||||
|
||||
// mu-nu plane stencil. We allow mu==nu to make indexing the stencil easier,
|
||||
// but these entries will not be used.
|
||||
std::vector<Coordinate> shifts;
|
||||
for(int mu=0;mu<Nd;mu++)
|
||||
for(int nu=0;nu<Nd;nu++) {
|
||||
appendShift(shifts,mu);
|
||||
appendShift(shifts,nu);
|
||||
appendShift(shifts,shiftSignal::NO_SHIFT);
|
||||
appendShift(shifts,mu,Back(nu));
|
||||
appendShift(shifts,Back(nu));
|
||||
appendShift(shifts,Back(mu));
|
||||
}
|
||||
|
||||
// A GeneralLocalStencil has two indices: a site and stencil index
|
||||
GeneralLocalStencil gStencil(Ughost.Grid(),shifts);
|
||||
|
||||
// This is where contributions from the smearing get added together
|
||||
Ughost_fat=Zero();
|
||||
|
||||
// This loop handles 3-, 5-, and 7-link constructs, minus Lepage and Naik.
|
||||
for(int mu=0;mu<Nd;mu++) {
|
||||
|
||||
// TODO: This approach is slightly memory inefficient. It uses 25% extra memory
|
||||
Ughost_3link =Zero();
|
||||
Ughost_5linkA=Zero();
|
||||
Ughost_5linkB=Zero();
|
||||
|
||||
// Create the accessors
|
||||
autoView(U_v , Ughost , AcceleratorRead);
|
||||
autoView(U_fat_v , Ughost_fat , AcceleratorWrite);
|
||||
autoView(U_3link_v , Ughost_3link , AcceleratorWrite);
|
||||
autoView(U_5linkA_v, Ughost_5linkA, AcceleratorWrite);
|
||||
autoView(U_5linkB_v, Ughost_5linkB, AcceleratorWrite);
|
||||
|
||||
// We infer some types that will be needed in the calculation.
|
||||
typedef decltype(gStencil.GetEntry(0,0)) stencilElement;
|
||||
typedef decltype(coalescedReadGeneralPermute(U_v[0](0),gStencil.GetEntry(0,0)->_permute,Nd)) U3matrix;
|
||||
|
||||
int Nsites = U_v.size();
|
||||
auto gStencil_v = gStencil.View();
|
||||
|
||||
accelerator_for(site,Nsites,Simd::Nsimd(),{ // ----------- 3-link constructs
|
||||
stencilElement SE0, SE1, SE2, SE3, SE4, SE5;
|
||||
U3matrix U0, U1, U2, U3, U4, U5, W;
|
||||
for(int nu=0;nu<Nd;nu++) {
|
||||
if(nu==mu) continue;
|
||||
int s = stencilIndex(mu,nu);
|
||||
|
||||
// The stencil gives us support points in the mu-nu plane that we will use to
|
||||
// grab the links we need.
|
||||
SE0 = gStencil_v.GetEntry(s+0,site); int x_p_mu = SE0->_offset;
|
||||
SE1 = gStencil_v.GetEntry(s+1,site); int x_p_nu = SE1->_offset;
|
||||
SE2 = gStencil_v.GetEntry(s+2,site); int x = SE2->_offset;
|
||||
SE3 = gStencil_v.GetEntry(s+3,site); int x_p_mu_m_nu = SE3->_offset;
|
||||
SE4 = gStencil_v.GetEntry(s+4,site); int x_m_nu = SE4->_offset;
|
||||
SE5 = gStencil_v.GetEntry(s+5,site); int x_m_mu = SE5->_offset;
|
||||
|
||||
// When you're deciding whether to take an adjoint, the question is: how is the
|
||||
// stored link oriented compared to the one you want? If I imagine myself travelling
|
||||
// with the to-be-updated link, I have two possible, alternative 3-link paths I can
|
||||
// take, one starting by going to the left, the other starting by going to the right.
|
||||
U0 = coalescedReadGeneralPermute(U_v[x_p_mu ](nu),SE0->_permute,Nd);
|
||||
U1 = coalescedReadGeneralPermute(U_v[x_p_nu ](mu),SE1->_permute,Nd);
|
||||
U2 = coalescedReadGeneralPermute(U_v[x ](nu),SE2->_permute,Nd);
|
||||
U3 = coalescedReadGeneralPermute(U_v[x_p_mu_m_nu](nu),SE3->_permute,Nd);
|
||||
U4 = coalescedReadGeneralPermute(U_v[x_m_nu ](mu),SE4->_permute,Nd);
|
||||
U5 = coalescedReadGeneralPermute(U_v[x_m_nu ](nu),SE4->_permute,Nd);
|
||||
|
||||
// "left" "right"
|
||||
W = U2*U1*adj(U0) + adj(U5)*U4*U3;
|
||||
|
||||
// Save 3-link construct for later and add to smeared field.
|
||||
coalescedWrite(U_3link_v[x](nu), W);
|
||||
|
||||
// The index operator (x) returns the coalesced read on GPU. The view [] index returns
|
||||
// a reference to the vector object. The [x](mu) returns a reference to the densely
|
||||
// packed (contiguous in memory) mu-th element of the vector object. On CPU,
|
||||
// coalescedRead/Write is the identity mapping assigning vector object to vector object.
|
||||
// But on GPU it's non-trivial and maps scalar object to vector object and vice versa.
|
||||
coalescedWrite(U_fat_v[x](mu), U_fat_v(x)(mu) + lt.c_3*W);
|
||||
}
|
||||
})
|
||||
|
||||
accelerator_for(site,Nsites,Simd::Nsimd(),{ // ----------- 5-link
|
||||
stencilElement SE0, SE1, SE2, SE3, SE4, SE5;
|
||||
U3matrix U0, U1, U2, U3, U4, U5, W;
|
||||
int sigmaIndex = 0;
|
||||
for(int nu=0;nu<Nd;nu++) {
|
||||
if(nu==mu) continue;
|
||||
int s = stencilIndex(mu,nu);
|
||||
for(int rho=0;rho<Nd;rho++) {
|
||||
if (rho == mu || rho == nu) continue;
|
||||
|
||||
SE0 = gStencil_v.GetEntry(s+0,site); int x_p_mu = SE0->_offset;
|
||||
SE1 = gStencil_v.GetEntry(s+1,site); int x_p_nu = SE1->_offset;
|
||||
SE2 = gStencil_v.GetEntry(s+2,site); int x = SE2->_offset;
|
||||
SE3 = gStencil_v.GetEntry(s+3,site); int x_p_mu_m_nu = SE3->_offset;
|
||||
SE4 = gStencil_v.GetEntry(s+4,site); int x_m_nu = SE4->_offset;
|
||||
|
||||
U0 = coalescedReadGeneralPermute( U_v[x_p_mu ](nu ),SE0->_permute,Nd);
|
||||
U1 = coalescedReadGeneralPermute(U_3link_v[x_p_nu ](rho),SE1->_permute,Nd);
|
||||
U2 = coalescedReadGeneralPermute( U_v[x ](nu ),SE2->_permute,Nd);
|
||||
U3 = coalescedReadGeneralPermute( U_v[x_p_mu_m_nu](nu ),SE3->_permute,Nd);
|
||||
U4 = coalescedReadGeneralPermute(U_3link_v[x_m_nu ](rho),SE4->_permute,Nd);
|
||||
U5 = coalescedReadGeneralPermute( U_v[x_m_nu ](nu ),SE4->_permute,Nd);
|
||||
|
||||
W = U2*U1*adj(U0) + adj(U5)*U4*U3;
|
||||
|
||||
if(sigmaIndex<3) {
|
||||
coalescedWrite(U_5linkA_v[x](rho), W);
|
||||
} else {
|
||||
coalescedWrite(U_5linkB_v[x](rho), W);
|
||||
}
|
||||
|
||||
coalescedWrite(U_fat_v[x](mu), U_fat_v(x)(mu) + lt.c_5*W);
|
||||
sigmaIndex++;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
accelerator_for(site,Nsites,Simd::Nsimd(),{ // ----------- 7-link
|
||||
stencilElement SE0, SE1, SE2, SE3, SE4, SE5;
|
||||
U3matrix U0, U1, U2, U3, U4, U5, W;
|
||||
int sigmaIndex = 0;
|
||||
for(int nu=0;nu<Nd;nu++) {
|
||||
if(nu==mu) continue;
|
||||
int s = stencilIndex(mu,nu);
|
||||
for(int rho=0;rho<Nd;rho++) {
|
||||
if (rho == mu || rho == nu) continue;
|
||||
|
||||
SE0 = gStencil_v.GetEntry(s+0,site); int x_p_mu = SE0->_offset;
|
||||
SE1 = gStencil_v.GetEntry(s+1,site); int x_p_nu = SE1->_offset;
|
||||
SE2 = gStencil_v.GetEntry(s+2,site); int x = SE2->_offset;
|
||||
SE3 = gStencil_v.GetEntry(s+3,site); int x_p_mu_m_nu = SE3->_offset;
|
||||
SE4 = gStencil_v.GetEntry(s+4,site); int x_m_nu = SE4->_offset;
|
||||
|
||||
U0 = coalescedReadGeneralPermute(U_v[x_p_mu](nu),SE0->_permute,Nd);
|
||||
if(sigmaIndex<3) {
|
||||
U1 = coalescedReadGeneralPermute(U_5linkB_v[x_p_nu](rho),SE1->_permute,Nd);
|
||||
} else {
|
||||
U1 = coalescedReadGeneralPermute(U_5linkA_v[x_p_nu](rho),SE1->_permute,Nd);
|
||||
}
|
||||
U2 = coalescedReadGeneralPermute(U_v[x](nu),SE2->_permute,Nd);
|
||||
U3 = coalescedReadGeneralPermute(U_v[x_p_mu_m_nu](nu),SE3->_permute,Nd);
|
||||
if(sigmaIndex<3) {
|
||||
U4 = coalescedReadGeneralPermute(U_5linkB_v[x_m_nu](rho),SE4->_permute,Nd);
|
||||
} else {
|
||||
U4 = coalescedReadGeneralPermute(U_5linkA_v[x_m_nu](rho),SE4->_permute,Nd);
|
||||
}
|
||||
U5 = coalescedReadGeneralPermute(U_v[x_m_nu](nu),SE4->_permute,Nd);
|
||||
|
||||
W = U2*U1*adj(U0) + adj(U5)*U4*U3;
|
||||
|
||||
coalescedWrite(U_fat_v[x](mu), U_fat_v(x)(mu) + lt.c_7*W);
|
||||
sigmaIndex++;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
} // end mu loop
|
||||
|
||||
// c1, c3, c5, c7 construct contributions
|
||||
u_smr = Ghost.Extract(Ughost_fat) + lt.c_1*u_thin;
|
||||
|
||||
// Load up U and V std::vectors to access thin and smeared links.
|
||||
std::vector<LF> U(Nd, grid);
|
||||
std::vector<LF> V(Nd, grid);
|
||||
std::vector<LF> Vnaik(Nd, grid);
|
||||
for (int mu = 0; mu < Nd; mu++) {
|
||||
U[mu] = PeekIndex<LorentzIndex>(u_thin, mu);
|
||||
V[mu] = PeekIndex<LorentzIndex>(u_smr, mu);
|
||||
}
|
||||
|
||||
for(int mu=0;mu<Nd;mu++) {
|
||||
|
||||
// Naik
|
||||
Vnaik[mu] = lt.c_naik*Gimpl::CovShiftForward(U[mu],mu,
|
||||
Gimpl::CovShiftForward(U[mu],mu,
|
||||
Gimpl::CovShiftIdentityForward(U[mu],mu)));
|
||||
|
||||
// LePage
|
||||
for (int nu_h=1;nu_h<Nd;nu_h++) {
|
||||
int nu=(mu+nu_h)%Nd;
|
||||
// nu, nu, mu, Back(nu), Back(nu)
|
||||
V[mu] = V[mu] + lt.c_lp*Gimpl::CovShiftForward(U[nu],nu,
|
||||
Gimpl::CovShiftForward(U[nu],nu,
|
||||
Gimpl::CovShiftForward(U[mu],mu,
|
||||
Gimpl::CovShiftBackward(U[nu],nu,
|
||||
Gimpl::CovShiftIdentityBackward(U[nu],nu)))))
|
||||
// Back(nu), Back(nu), mu, nu, nu
|
||||
+ lt.c_lp*Gimpl::CovShiftBackward(U[nu],nu,
|
||||
Gimpl::CovShiftBackward(U[nu],nu,
|
||||
Gimpl::CovShiftForward(U[mu],mu,
|
||||
Gimpl::CovShiftForward(U[nu],nu,
|
||||
Gimpl::CovShiftIdentityForward(U[nu],nu)))));
|
||||
}
|
||||
}
|
||||
|
||||
// Put V back into u_smr.
|
||||
for (int mu = 0; mu < Nd; mu++) {
|
||||
PokeIndex<LorentzIndex>(u_smr , V[mu] , mu);
|
||||
PokeIndex<LorentzIndex>(u_naik, Vnaik[mu], mu);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Intent: OUT--u_proj
|
||||
// IN--u_mu
|
||||
void projectU3(GF& u_proj, GF& u_mu) const {
|
||||
|
||||
auto grid = this->_grid;
|
||||
|
||||
LF V(grid), Q(grid), sqrtQinv(grid), id_3(grid), diff(grid);
|
||||
CF c0(grid), c1(grid), c2(grid), g0(grid), g1(grid), g2(grid), S(grid), R(grid), theta(grid),
|
||||
u(grid), v(grid), w(grid), den(grid), f0(grid), f1(grid), f2(grid);
|
||||
|
||||
// Follow MILC 10.1103/PhysRevD.82.074501, eqs (B2-B3) and (C1-C8)
|
||||
for (int mu = 0; mu < Nd; mu++) {
|
||||
V = PeekIndex<LorentzIndex>(u_mu, mu);
|
||||
Q = adj(V)*V;
|
||||
c0 = real(trace(Q));
|
||||
c1 = (1/2.)*real(trace(Q*Q));
|
||||
c2 = (1/3.)*real(trace(Q*Q*Q));
|
||||
S = (1/3.)*c1-(1/18.)*c0*c0;
|
||||
if (norm2(S)<1e-28) {
|
||||
g0 = (1/3.)*c0; g1 = g0; g2 = g1;
|
||||
} else {
|
||||
R = (1/2.)*c2-(1/3. )*c0*c1+(1/27.)*c0*c0*c0;
|
||||
theta = acos(R*pow(S,-1.5));
|
||||
g0 = (1/3.)*c0+2.*sqrt(S)*cos((1/3.)*theta-2*M_PI/3.);
|
||||
g1 = (1/3.)*c0+2.*sqrt(S)*cos((1/3.)*theta );
|
||||
g2 = (1/3.)*c0+2.*sqrt(S)*cos((1/3.)*theta+2*M_PI/3.);
|
||||
}
|
||||
// if (fabs(Q.determinant()/(g0*g1*g2)-1.0) > 1e-5) { SVD }
|
||||
u = sqrt(g0) + sqrt(g1) + sqrt(g2);
|
||||
v = sqrt(g0*g1) + sqrt(g0*g2) + sqrt(g1*g2);
|
||||
w = sqrt(g0*g1*g2);
|
||||
den = w*(u*v-w);
|
||||
f0 = (-w*(u*u+v)+u*v*v)/den;
|
||||
f1 = (-w-u*u*u+2.*u*v)/den;
|
||||
f2 = u/den;
|
||||
id_3 = 1.;
|
||||
|
||||
sqrtQinv = f0*id_3 + f1*Q + f2*Q*Q;
|
||||
|
||||
PokeIndex<LorentzIndex>(u_proj, V*sqrtQinv, mu);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// void derivative(const GaugeField& Gauge) const {
|
||||
// };
|
||||
};
|
||||
|
||||
|
||||
NAMESPACE_END(Grid);
|
@ -5,4 +5,5 @@
|
||||
#include <Grid/qcd/smearing/StoutSmearing.h>
|
||||
#include <Grid/qcd/smearing/GaugeConfiguration.h>
|
||||
#include <Grid/qcd/smearing/WilsonFlow.h>
|
||||
#include <Grid/qcd/smearing/HISQSmearing.h>
|
||||
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
/*! Construct stout smearing object from explicitly specified rho matrix */
|
||||
Smear_Stout(const std::vector<double>& rho_)
|
||||
: OwnedBase{new Smear_APE<Gimpl>(rho_)}, SmearBase{OwnedBase.get()} {
|
||||
std::cout << GridLogDebug << "Stout smearing constructor : Smear_Stout(const std::vector<double>& " << rho_ << " )" << std::endl
|
||||
std::cout << GridLogDebug << "Stout smearing constructor : Smear_Stout(const std::vector<double>& " << rho_ << " )" << std::endl;
|
||||
assert(Nc == 3 && "Stout smearing currently implemented only for Nc==3");
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,9 @@ class GaugeGroup {
|
||||
using iGroupMatrix = iScalar<iScalar<iMatrix<vtype, ncolour> > >;
|
||||
template <typename vtype>
|
||||
using iAlgebraVector = iScalar<iScalar<iVector<vtype, AdjointDimension> > >;
|
||||
template <typename vtype>
|
||||
using iSUnAlgebraMatrix =
|
||||
iScalar<iScalar<iMatrix<vtype, AdjointDimension> > >;
|
||||
static int su2subgroups(void) { return su2subgroups(group_name()); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -128,10 +131,19 @@ class GaugeGroup {
|
||||
typedef Lattice<vMatrix> LatticeMatrix;
|
||||
typedef Lattice<vMatrixF> LatticeMatrixF;
|
||||
typedef Lattice<vMatrixD> LatticeMatrixD;
|
||||
|
||||
|
||||
typedef Lattice<vAlgebraVector> LatticeAlgebraVector;
|
||||
typedef Lattice<vAlgebraVectorF> LatticeAlgebraVectorF;
|
||||
typedef Lattice<vAlgebraVectorD> LatticeAlgebraVectorD;
|
||||
|
||||
typedef iSUnAlgebraMatrix<vComplex> vAlgebraMatrix;
|
||||
typedef iSUnAlgebraMatrix<vComplexF> vAlgebraMatrixF;
|
||||
typedef iSUnAlgebraMatrix<vComplexD> vAlgebraMatrixD;
|
||||
|
||||
typedef Lattice<vAlgebraMatrix> LatticeAlgebraMatrix;
|
||||
typedef Lattice<vAlgebraMatrixF> LatticeAlgebraMatrixF;
|
||||
typedef Lattice<vAlgebraMatrixD> LatticeAlgebraMatrixD;
|
||||
|
||||
|
||||
typedef iSU2Matrix<Complex> SU2Matrix;
|
||||
typedef iSU2Matrix<ComplexF> SU2MatrixF;
|
||||
@ -160,7 +172,7 @@ class GaugeGroup {
|
||||
return generator(lieIndex, ta, group_name());
|
||||
}
|
||||
|
||||
static void su2SubGroupIndex(int &i1, int &i2, int su2_index) {
|
||||
static accelerator_inline void su2SubGroupIndex(int &i1, int &i2, int su2_index) {
|
||||
return su2SubGroupIndex(i1, i2, su2_index, group_name());
|
||||
}
|
||||
|
||||
@ -389,6 +401,52 @@ class GaugeGroup {
|
||||
}
|
||||
}
|
||||
|
||||
// Ta are hermitian (?)
|
||||
// Anti herm is i Ta basis
|
||||
static void LieAlgebraProject(LatticeAlgebraMatrix &out,const LatticeMatrix &in, int b)
|
||||
{
|
||||
conformable(in, out);
|
||||
GridBase *grid = out.Grid();
|
||||
LatticeComplex tmp(grid);
|
||||
Matrix ta;
|
||||
// Using Luchang's projection convention
|
||||
// 2 Tr{Ta Tb} A_b= 2/2 delta ab A_b = A_a
|
||||
autoView(out_v,out,AcceleratorWrite);
|
||||
autoView(in_v,in,AcceleratorRead);
|
||||
int N = ncolour;
|
||||
int NNm1 = N * (N - 1);
|
||||
int hNNm1= NNm1/2;
|
||||
RealD sqrt_2 = sqrt(2.0);
|
||||
Complex ci(0.0,1.0);
|
||||
for(int su2Index=0;su2Index<hNNm1;su2Index++){
|
||||
int i1, i2;
|
||||
su2SubGroupIndex(i1, i2, su2Index);
|
||||
int ax = su2Index*2;
|
||||
int ay = su2Index*2+1;
|
||||
accelerator_for(ss,grid->oSites(),1,{
|
||||
// in is traceless ANTI-hermitian whereas Grid generators are Hermitian.
|
||||
// trace( Ta x Ci in)
|
||||
// Bet I need to move to real part with mult by -i
|
||||
out_v[ss]()()(ax,b) = 0.5*(real(in_v[ss]()()(i2,i1)) - real(in_v[ss]()()(i1,i2)));
|
||||
out_v[ss]()()(ay,b) = 0.5*(imag(in_v[ss]()()(i1,i2)) + imag(in_v[ss]()()(i2,i1)));
|
||||
});
|
||||
}
|
||||
for(int diagIndex=0;diagIndex<N-1;diagIndex++){
|
||||
int k = diagIndex + 1; // diagIndex starts from 0
|
||||
int a = NNm1+diagIndex;
|
||||
RealD scale = 1.0/sqrt(2.0*k*(k+1));
|
||||
accelerator_for(ss,grid->oSites(),vComplex::Nsimd(),{
|
||||
auto tmp = in_v[ss]()()(0,0);
|
||||
for(int i=1;i<k;i++){
|
||||
tmp=tmp+in_v[ss]()()(i,i);
|
||||
}
|
||||
tmp = tmp - in_v[ss]()()(k,k)*k;
|
||||
out_v[ss]()()(a,b) =imag(tmp) * scale;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
template <int ncolour>
|
||||
|
@ -10,6 +10,7 @@
|
||||
// doesn't get found by the scripts/filelist during bootstrapping.
|
||||
|
||||
private:
|
||||
|
||||
template <ONLY_IF_SU>
|
||||
static int su2subgroups(GroupName::SU) { return (ncolour * (ncolour - 1)) / 2; }
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -576,3 +577,4 @@ static void RandomGaugeTransform(GridParallelRNG &pRNG, typename Gimpl::GaugeFie
|
||||
LieRandomize(pRNG,g,1.0);
|
||||
GaugeTransform<Gimpl>(Umu,g);
|
||||
}
|
||||
|
||||
|
@ -464,7 +464,8 @@ public:
|
||||
//U_padded: the gauge link fields padded out using the PaddedCell class
|
||||
//Cell: the padded cell class
|
||||
//gStencil: the precomputed generalized local stencil for the staple
|
||||
static void StaplePaddedAll(std::vector<GaugeMat> &staple, const std::vector<GaugeMat> &U_padded, const PaddedCell &Cell, const GeneralLocalStencil &gStencil) {
|
||||
static void StaplePaddedAll(std::vector<GaugeMat> &staple, const std::vector<GaugeMat> &U_padded, const PaddedCell &Cell, const GeneralLocalStencil &gStencil)
|
||||
{
|
||||
double t0 = usecond();
|
||||
assert(U_padded.size() == Nd); assert(staple.size() == Nd);
|
||||
assert(U_padded[0].Grid() == (GridBase*)Cell.grids.back());
|
||||
@ -489,7 +490,7 @@ public:
|
||||
autoView( gStaple_v , gStaple, AcceleratorWrite);
|
||||
auto gStencil_v = gStencil.View(AcceleratorRead);
|
||||
|
||||
accelerator_for(ss, ggrid->oSites(), ggrid->Nsimd(), {
|
||||
accelerator_for(ss, ggrid->oSites(), (size_t)ggrid->Nsimd(), {
|
||||
decltype(coalescedRead(Ug_dirs_v[0][0])) stencil_ss;
|
||||
stencil_ss = Zero();
|
||||
int off = outer_off;
|
||||
@ -1201,7 +1202,7 @@ public:
|
||||
autoView( gStaple_v , gStaple, AcceleratorWrite);
|
||||
auto gStencil_v = gStencil.View(AcceleratorRead);
|
||||
|
||||
accelerator_for(ss, ggrid->oSites(), ggrid->Nsimd(), {
|
||||
accelerator_for(ss, ggrid->oSites(), (size_t)ggrid->Nsimd(), {
|
||||
decltype(coalescedRead(Ug_dirs_v[0][0])) stencil_ss;
|
||||
stencil_ss = Zero();
|
||||
int s=offset;
|
||||
|
Reference in New Issue
Block a user