2016-07-08 15:40:11 +01:00
|
|
|
/*************************************************************************************
|
2016-01-02 14:51:32 +00:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
Grid physics library, www.github.com/paboyle/Grid
|
2016-01-02 14:51:32 +00:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
Source file: ./lib/qcd/hmc/integrators/Integrator.h
|
2016-01-02 14:51:32 +00:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
Copyright (C) 2015
|
2016-01-02 14:51:32 +00:00
|
|
|
|
|
|
|
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
|
|
|
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
|
|
|
Author: neo <cossu@post.kek.jp>
|
|
|
|
Author: paboyle <paboyle@ph.ed.ac.uk>
|
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
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.
|
2016-01-02 14:51:32 +00:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
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.
|
2016-01-02 14:51:32 +00:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
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.
|
2016-01-02 14:51:32 +00:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
See the full license in the file "LICENSE" in the top level distribution
|
|
|
|
directory
|
|
|
|
*************************************************************************************/
|
|
|
|
/* END LEGAL */
|
2015-07-06 08:46:43 +01:00
|
|
|
//--------------------------------------------------------------------
|
|
|
|
/*! @file Integrator.h
|
2015-07-07 06:59:37 +01:00
|
|
|
* @brief Classes for the Molecular Dynamics integrator
|
2015-07-06 08:46:43 +01:00
|
|
|
*
|
|
|
|
* @author Guido Cossu
|
2015-07-30 09:16:04 +01:00
|
|
|
* Time-stamp: <2015-07-30 16:21:29 neo>
|
2015-07-06 08:46:43 +01:00
|
|
|
*/
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
|
|
|
|
#ifndef INTEGRATOR_INCLUDED
|
|
|
|
#define INTEGRATOR_INCLUDED
|
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
// class Observer;
|
2015-07-06 08:46:43 +01:00
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
namespace Grid {
|
|
|
|
namespace QCD {
|
|
|
|
|
|
|
|
struct IntegratorParameters {
|
|
|
|
int Nexp;
|
|
|
|
int MDsteps; // number of outer steps
|
|
|
|
RealD trajL; // trajectory length
|
|
|
|
RealD stepsize;
|
|
|
|
|
|
|
|
IntegratorParameters(int MDsteps_, RealD trajL_ = 1.0, int Nexp_ = 12)
|
|
|
|
: Nexp(Nexp_),
|
|
|
|
MDsteps(MDsteps_),
|
|
|
|
trajL(trajL_),
|
|
|
|
stepsize(trajL / MDsteps){
|
|
|
|
// empty body constructor
|
|
|
|
};
|
|
|
|
};
|
2015-08-30 12:18:34 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
/*! @brief Class for Molecular Dynamics management */
|
2016-07-13 17:51:18 +01:00
|
|
|
template <class GaugeField, class SmearingPolicy ,class RepresentationPolicy >
|
2016-07-08 15:40:11 +01:00
|
|
|
class Integrator {
|
|
|
|
protected:
|
|
|
|
typedef IntegratorParameters ParameterType;
|
2015-07-06 08:46:43 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
IntegratorParameters Params;
|
2015-08-30 12:18:34 +01:00
|
|
|
|
2016-07-15 13:39:47 +01:00
|
|
|
const ActionSetHirep<GaugeField, RepresentationPolicy> as;
|
2015-07-06 08:46:43 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
int levels; //
|
|
|
|
double t_U; // Track time passing on each level and for U and for P
|
|
|
|
std::vector<double> t_P; //
|
2015-08-29 17:18:43 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
GaugeField P;
|
2015-08-30 13:39:19 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
SmearingPolicy& Smearer;
|
2015-08-29 17:18:43 +01:00
|
|
|
|
2016-07-13 17:51:18 +01:00
|
|
|
RepresentationPolicy Representations;
|
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
// Should match any legal (SU(n)) gauge field
|
|
|
|
// Need to use this template to match Ncol to pass to SU<N> class
|
|
|
|
template <int Ncol, class vec>
|
|
|
|
void generate_momenta(Lattice<iVector<iScalar<iMatrix<vec, Ncol> >, Nd> >& P,
|
|
|
|
GridParallelRNG& pRNG) {
|
|
|
|
typedef Lattice<iScalar<iScalar<iMatrix<vec, Ncol> > > > GaugeLinkField;
|
|
|
|
GaugeLinkField Pmu(P._grid);
|
|
|
|
Pmu = zero;
|
|
|
|
for (int mu = 0; mu < Nd; mu++) {
|
|
|
|
SU<Ncol>::GaussianFundamentalLieAlgebraMatrix(pRNG, Pmu);
|
|
|
|
PokeIndex<LorentzIndex>(P, Pmu, mu);
|
|
|
|
}
|
|
|
|
}
|
2015-08-29 17:18:43 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
// ObserverList observers; // not yet
|
|
|
|
// typedef std::vector<Observer*> ObserverList;
|
|
|
|
// void register_observers();
|
|
|
|
// void notify_observers();
|
2015-08-30 12:18:34 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
void update_P(GaugeField& U, int level, double ep) {
|
|
|
|
t_P[level] += ep;
|
|
|
|
update_P(P, U, level, ep);
|
2015-07-06 08:46:43 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
std::cout << GridLogIntegrator << "[" << level << "] P "
|
|
|
|
<< " dt " << ep << " : t_P " << t_P[level] << std::endl;
|
|
|
|
}
|
2015-08-30 13:39:19 +01:00
|
|
|
|
2016-07-13 17:51:18 +01:00
|
|
|
// to be used by the actionlevel class to iterate
|
|
|
|
// over the representations
|
|
|
|
template <class Level>
|
2016-07-15 13:39:47 +01:00
|
|
|
void update_P_hireps(Level repr_level, GaugeField& Mom, GaugeField& U,
|
2016-07-13 17:51:18 +01:00
|
|
|
double ep) {
|
|
|
|
typedef typename Level::LatticeField FieldType;
|
|
|
|
FieldType Ur = repr_level->getRepresentation();// update U is better
|
|
|
|
for (int a = 0; a < repr_level.size(); ++a) {
|
|
|
|
FieldType forceR(U._grid);
|
|
|
|
// Implement smearing only for the fundamental representation now
|
|
|
|
repr_level.at(a)->deriv(Ur, forceR);
|
|
|
|
GaugeField force = repr_level.at(a)->RtoFundamentalProject(forceR);
|
|
|
|
std::cout << GridLogIntegrator
|
|
|
|
<< "Hirep Force average: " << norm2(force) / (U._grid->gSites())
|
|
|
|
<< std::endl;
|
|
|
|
Mom -= force * ep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
void update_P(GaugeField& Mom, GaugeField& U, int level, double ep) {
|
2016-07-13 17:51:18 +01:00
|
|
|
// input U actually not used in the fundamental case
|
2016-07-15 13:39:47 +01:00
|
|
|
// Fundamental updates, include smearing
|
2016-07-08 15:40:11 +01:00
|
|
|
for (int a = 0; a < as[level].actions.size(); ++a) {
|
|
|
|
GaugeField force(U._grid);
|
|
|
|
GaugeField& Us = Smearer.get_U(as[level].actions.at(a)->is_smeared);
|
|
|
|
as[level].actions.at(a)->deriv(Us, force); // deriv should NOT include Ta
|
|
|
|
|
|
|
|
std::cout << GridLogIntegrator
|
|
|
|
<< "Smearing (on/off): " << as[level].actions.at(a)->is_smeared
|
|
|
|
<< std::endl;
|
|
|
|
if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force);
|
|
|
|
force = Ta(force);
|
|
|
|
std::cout << GridLogIntegrator
|
|
|
|
<< "Force average: " << norm2(force) / (U._grid->gSites())
|
|
|
|
<< std::endl;
|
|
|
|
Mom -= force * ep;
|
|
|
|
}
|
2016-07-13 17:51:18 +01:00
|
|
|
// Add here the other representations
|
2016-07-15 13:39:47 +01:00
|
|
|
//apply(update_P_hireps, as[level], Args...)
|
2016-07-04 15:35:37 +01:00
|
|
|
}
|
2015-08-30 13:39:19 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
void update_U(GaugeField& U, double ep) {
|
|
|
|
update_U(P, U, ep);
|
|
|
|
|
|
|
|
t_U += ep;
|
|
|
|
int fl = levels - 1;
|
|
|
|
std::cout << GridLogIntegrator << " "
|
|
|
|
<< "[" << fl << "] U "
|
|
|
|
<< " dt " << ep << " : t_U " << t_U << std::endl;
|
|
|
|
}
|
|
|
|
void update_U(GaugeField& Mom, GaugeField& U, double ep) {
|
|
|
|
// rewrite exponential to deal automatically with the lorentz index?
|
|
|
|
for (int mu = 0; mu < Nd; mu++) {
|
|
|
|
auto Umu = PeekIndex<LorentzIndex>(U, mu);
|
|
|
|
auto Pmu = PeekIndex<LorentzIndex>(Mom, mu);
|
|
|
|
Umu = expMat(Pmu, ep, Params.Nexp) * Umu;
|
|
|
|
ProjectOnGroup(Umu);
|
|
|
|
PokeIndex<LorentzIndex>(U, Umu, mu);
|
|
|
|
}
|
|
|
|
// Update the smeared fields, can be implemented as observer
|
|
|
|
Smearer.set_GaugeField(U);
|
2016-07-13 17:51:18 +01:00
|
|
|
// Update the higher representations fields
|
|
|
|
//Representations.update(U);// void functions if fundamental representation
|
2016-07-08 15:40:11 +01:00
|
|
|
}
|
2015-08-29 17:18:43 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
virtual void step(GaugeField& U, int level, int first, int last) = 0;
|
2015-07-06 08:46:43 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
public:
|
|
|
|
Integrator(GridBase* grid, IntegratorParameters Par,
|
2016-07-15 13:39:47 +01:00
|
|
|
ActionSetHirep<GaugeField, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
|
2016-07-13 17:51:18 +01:00
|
|
|
: Params(Par), as(Aset), P(grid), levels(Aset.size()), Smearer(Sm), Representations(grid) {
|
2016-07-08 15:40:11 +01:00
|
|
|
t_P.resize(levels, 0.0);
|
|
|
|
t_U = 0.0;
|
|
|
|
// initialization of smearer delegated outside of Integrator
|
|
|
|
};
|
2015-08-30 12:18:34 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
virtual ~Integrator() {}
|
|
|
|
|
|
|
|
// Initialization of momenta and actions
|
|
|
|
void refresh(GaugeField& U, GridParallelRNG& pRNG) {
|
|
|
|
std::cout << GridLogIntegrator << "Integrator refresh\n";
|
|
|
|
generate_momenta(P, pRNG);
|
2016-07-13 17:51:18 +01:00
|
|
|
|
|
|
|
// Update the smeared fields, can be implemented as observer
|
|
|
|
// necessary to keep the fields updated even after a reject
|
|
|
|
// of the Metropolis
|
|
|
|
Smearer.set_GaugeField(U);
|
|
|
|
// Set the (eventual) representations gauge fields
|
|
|
|
// Representations.update(U);
|
|
|
|
|
2016-07-12 13:36:10 +01:00
|
|
|
// The Smearer is attached to a pointer of the gauge field
|
2016-07-13 17:51:18 +01:00
|
|
|
// automatically gets the correct field
|
2016-07-12 13:36:10 +01:00
|
|
|
// whether or not has been accepted in the previous sweep
|
2016-07-08 15:40:11 +01:00
|
|
|
for (int level = 0; level < as.size(); ++level) {
|
|
|
|
for (int actionID = 0; actionID < as[level].actions.size(); ++actionID) {
|
|
|
|
// get gauge field from the SmearingPolicy and
|
|
|
|
// based on the boolean is_smeared in actionID
|
|
|
|
GaugeField& Us =
|
|
|
|
Smearer.get_U(as[level].actions.at(actionID)->is_smeared);
|
|
|
|
as[level].actions.at(actionID)->refresh(Us, pRNG);
|
|
|
|
}
|
|
|
|
}
|
2016-07-13 17:51:18 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-04 15:35:37 +01:00
|
|
|
}
|
2015-08-31 16:32:04 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
// Calculate action
|
|
|
|
RealD S(GaugeField& U) { // here also U not used
|
|
|
|
|
|
|
|
LatticeComplex Hloc(U._grid);
|
|
|
|
Hloc = zero;
|
|
|
|
// Momenta
|
|
|
|
for (int mu = 0; mu < Nd; mu++) {
|
|
|
|
auto Pmu = PeekIndex<LorentzIndex>(P, mu);
|
|
|
|
Hloc -= trace(Pmu * Pmu);
|
|
|
|
}
|
|
|
|
Complex Hsum = sum(Hloc);
|
|
|
|
|
|
|
|
RealD H = Hsum.real();
|
|
|
|
RealD Hterm;
|
|
|
|
std::cout << GridLogMessage << "Momentum action H_p = " << H << "\n";
|
|
|
|
|
|
|
|
// Actions
|
|
|
|
for (int level = 0; level < as.size(); ++level) {
|
|
|
|
for (int actionID = 0; actionID < as[level].actions.size(); ++actionID) {
|
|
|
|
// get gauge field from the SmearingPolicy and
|
|
|
|
// based on the boolean is_smeared in actionID
|
|
|
|
GaugeField& Us =
|
|
|
|
Smearer.get_U(as[level].actions.at(actionID)->is_smeared);
|
|
|
|
Hterm = as[level].actions.at(actionID)->S(Us);
|
|
|
|
std::cout << GridLogMessage << "S Level " << level << " term "
|
|
|
|
<< actionID << " H = " << Hterm << std::endl;
|
|
|
|
H += Hterm;
|
|
|
|
}
|
|
|
|
}
|
2015-08-31 16:32:04 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
return H;
|
|
|
|
}
|
2015-08-31 16:32:04 +01:00
|
|
|
|
2016-07-08 15:40:11 +01:00
|
|
|
void integrate(GaugeField& U) {
|
|
|
|
// reset the clocks
|
|
|
|
t_U = 0;
|
|
|
|
for (int level = 0; level < as.size(); ++level) {
|
|
|
|
t_P[level] = 0;
|
|
|
|
}
|
|
|
|
|
2016-07-13 17:51:18 +01:00
|
|
|
|
|
|
|
for (int step = 0; step < Params.MDsteps; ++step) { // MD step
|
2016-07-08 15:40:11 +01:00
|
|
|
int first_step = (step == 0);
|
|
|
|
int last_step = (step == Params.MDsteps - 1);
|
|
|
|
this->step(U, 0, first_step, last_step);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the clocks all match on all levels
|
|
|
|
for (int level = 0; level < as.size(); ++level) {
|
|
|
|
assert(fabs(t_U - t_P[level]) < 1.0e-6); // must be the same
|
|
|
|
std::cout << GridLogIntegrator << " times[" << level
|
|
|
|
<< "]= " << t_P[level] << " " << t_U << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// and that we indeed got to the end of the trajectory
|
|
|
|
assert(fabs(t_U - Params.trajL) < 1.0e-6);
|
|
|
|
}
|
2016-07-04 15:35:37 +01:00
|
|
|
};
|
|
|
|
}
|
2015-07-06 08:46:43 +01:00
|
|
|
}
|
2016-07-08 15:40:11 +01:00
|
|
|
#endif // INTEGRATOR_INCLUDED
|