1
0
mirror of https://github.com/paboyle/Grid.git synced 2024-11-16 02:35:36 +00:00
Grid/lib/qcd/hmc/integrators/Integrator.h

315 lines
11 KiB
C
Raw Normal View History

/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: ./lib/qcd/hmc/integrators/Integrator.h
Copyright (C) 2015
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
2016-10-10 11:54:58 +01:00
Author: Guido Cossu <cossu@post.kek.jp>
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
*************************************************************************************/
2018-01-14 22:26:11 +00:00
/* END LEGAL */
//--------------------------------------------------------------------
2015-07-06 08:46:43 +01:00
#ifndef INTEGRATOR_INCLUDED
#define INTEGRATOR_INCLUDED
#include <memory>
2018-01-14 22:26:11 +00:00
NAMESPACE_BEGIN(Grid);
2017-01-16 10:18:09 +00:00
class IntegratorParameters: Serializable {
public:
2018-01-14 22:26:11 +00:00
GRID_SERIALIZABLE_CLASS_MEMBERS(IntegratorParameters,
std::string, name, // name of the integrator
unsigned int, MDsteps, // number of outer steps
RealD, trajL, // trajectory length
)
IntegratorParameters(int MDsteps_ = 10, RealD trajL_ = 1.0)
2018-01-14 22:26:11 +00:00
: MDsteps(MDsteps_),
trajL(trajL_){
// empty body constructor
};
2017-01-16 10:18:09 +00:00
template <class ReaderClass, typename std::enable_if<isReader<ReaderClass>::value, int >::type = 0 >
IntegratorParameters(ReaderClass & Reader){
2017-01-17 13:22:18 +00:00
std::cout << "Reading integrator\n";
2018-01-14 22:26:11 +00:00
read(Reader, "Integrator", *this);
2017-01-16 10:18:09 +00:00
}
2017-01-17 13:22:18 +00:00
void print_parameters() const {
std::cout << GridLogMessage << "[Integrator] Type : " << name << std::endl;
2016-12-22 12:41:56 +00:00
std::cout << GridLogMessage << "[Integrator] Trajectory length : " << trajL << std::endl;
std::cout << GridLogMessage << "[Integrator] Number of MD steps : " << MDsteps << std::endl;
2017-01-16 10:18:09 +00:00
std::cout << GridLogMessage << "[Integrator] Step size : " << trajL/MDsteps << std::endl;
}
};
/*! @brief Class for Molecular Dynamics management */
template <class FieldImplementation, class SmearingPolicy, class RepresentationPolicy>
class Integrator {
2018-01-14 22:26:11 +00:00
protected:
typedef typename FieldImplementation::Field MomentaField; //for readability
typedef typename FieldImplementation::Field Field;
2015-07-06 08:46:43 +01:00
int levels; // number of integration levels
double t_U; // Track time passing on each level and for U and for P
std::vector<double> t_P;
2017-03-10 14:54:53 +00:00
MomentaField P;
SmearingPolicy& Smearer;
RepresentationPolicy Representations;
IntegratorParameters Params;
const ActionSet<Field, RepresentationPolicy> as;
void update_P(Field& U, int level, double ep) {
t_P[level] += ep;
2017-03-10 14:54:53 +00:00
update_P(P, U, level, ep);
2015-07-06 08:46:43 +01:00
std::cout << GridLogIntegrator << "[" << level << "] P "
<< " dt " << ep << " : t_P " << t_P[level] << std::endl;
}
// to be used by the actionlevel class to iterate
// over the representations
struct _updateP {
template <class FieldType, class GF, class Repr>
void operator()(std::vector<Action<FieldType>*> repr_set, Repr& Rep,
GF& Mom, GF& U, double ep) {
for (int a = 0; a < repr_set.size(); ++a) {
2018-01-27 00:04:12 +00:00
FieldType forceR(U.Grid());
// Implement smearing only for the fundamental representation now
repr_set.at(a)->deriv(Rep.U, forceR);
GF force = Rep.RtoFundamentalProject(forceR); // Ta for the fundamental rep
2018-01-27 00:04:12 +00:00
Real force_abs = std::sqrt(norm2(force)/(U.Grid()->gSites()));
std::cout << GridLogIntegrator << "Hirep Force average: " << force_abs << std::endl;
Mom -= force * ep ;
}
}
} update_P_hireps{};
void update_P(MomentaField& Mom, Field& U, int level, double ep) {
// input U actually not used in the fundamental case
// Fundamental updates, include smearing
2017-03-01 11:56:35 +00:00
2018-01-14 22:26:11 +00:00
for (int a = 0; a < as[level].actions.size(); ++a) {
2018-01-27 00:04:12 +00:00
Field force(U.Grid());
conformable(U.Grid(), Mom.Grid());
Field& 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 = FieldImplementation::projectForce(force); // Ta for gauge fields
2018-01-27 00:04:12 +00:00
Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites());
std::cout << GridLogIntegrator << "Force average: " << force_abs << std::endl;
2017-02-24 17:03:42 +00:00
Mom -= force * ep;
}
// Force from the other representations
as[level].apply(update_P_hireps, Representations, Mom, U, ep);
}
void update_U(Field& U, double ep) {
2017-03-10 14:54:53 +00:00
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(MomentaField& Mom, Field& U, double ep) {
// exponential of Mom*U in the gauge fields case
FieldImplementation::update_field(Mom, U, ep);
// Update the smeared fields, can be implemented as observer
Smearer.set_Field(U);
// Update the higher representations fields
Representations.update(U); // void functions if fundamental representation
}
virtual void step(Field& U, int level, int first, int last) = 0;
2015-07-06 08:46:43 +01:00
2018-01-14 22:26:11 +00:00
public:
Integrator(GridBase* grid, IntegratorParameters Par,
ActionSet<Field, RepresentationPolicy>& Aset,
2017-03-10 14:54:53 +00:00
SmearingPolicy& Sm)
2018-01-14 22:26:11 +00:00
: Params(Par),
as(Aset),
P(grid),
levels(Aset.size()),
Smearer(Sm),
Representations(grid) {
t_P.resize(levels, 0.0);
t_U = 0.0;
// initialization of smearer delegated outside of Integrator
};
virtual ~Integrator() {}
virtual std::string integrator_name() = 0;
void print_parameters(){
std::cout << GridLogMessage << "[Integrator] Name : "<< integrator_name() << std::endl;
Params.print_parameters();
}
2016-12-22 12:41:56 +00:00
void print_actions(){
2018-01-14 22:26:11 +00:00
std::cout << GridLogMessage << ":::::::::::::::::::::::::::::::::::::::::" << std::endl;
std::cout << GridLogMessage << "[Integrator] Action summary: "<<std::endl;
for (int level = 0; level < as.size(); ++level) {
std::cout << GridLogMessage << "[Integrator] ---- Level: "<< level << std::endl;
for (int actionID = 0; actionID < as[level].actions.size(); ++actionID) {
std::cout << GridLogMessage << "["<< as[level].actions.at(actionID)->action_name() << "] ID: " << actionID << std::endl;
std::cout << as[level].actions.at(actionID)->LogParameters();
}
}
std::cout << GridLogMessage << ":::::::::::::::::::::::::::::::::::::::::"<< std::endl;
2016-12-22 12:41:56 +00:00
}
2017-02-24 17:03:42 +00:00
void reverse_momenta(){
2017-03-10 14:54:53 +00:00
P *= -1.0;
2017-02-24 17:03:42 +00:00
}
// to be used by the actionlevel class to iterate
// over the representations
struct _refresh {
template <class FieldType, class Repr>
void operator()(std::vector<Action<FieldType>*> repr_set, Repr& Rep,
GridParallelRNG& pRNG) {
for (int a = 0; a < repr_set.size(); ++a){
repr_set.at(a)->refresh(Rep.U, pRNG);
2018-01-14 22:26:11 +00:00
std::cout << GridLogDebug << "Hirep refreshing pseudofermions" << std::endl;
}
}
} refresh_hireps{};
// Initialization of momenta and actions
void refresh(Field& U, GridParallelRNG& pRNG) {
2018-01-27 00:04:12 +00:00
assert(P.Grid() == U.Grid());
std::cout << GridLogIntegrator << "Integrator refresh\n";
2017-02-24 17:03:42 +00:00
2017-03-10 14:54:53 +00:00
FieldImplementation::generate_momenta(P, pRNG);
2017-02-21 11:30:57 +00: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_Field(U);
// Set the (eventual) representations gauge fields
Representations.update(U);
// The Smearer is attached to a pointer of the gauge field
// automatically gets the correct field
// whether or not has been accepted in the previous sweep
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
Field& Us =
2018-01-14 22:26:11 +00:00
Smearer.get_U(as[level].actions.at(actionID)->is_smeared);
as[level].actions.at(actionID)->refresh(Us, pRNG);
}
2016-07-28 16:44:41 +01:00
// Refresh the higher representation actions
as[level].apply(refresh_hireps, Representations, pRNG);
}
}
// to be used by the actionlevel class to iterate
// over the representations
struct _S {
template <class FieldType, class Repr>
void operator()(std::vector<Action<FieldType>*> repr_set, Repr& Rep,
int level, RealD& H) {
2016-07-28 16:44:41 +01:00
for (int a = 0; a < repr_set.size(); ++a) {
RealD Hterm = repr_set.at(a)->S(Rep.U);
std::cout << GridLogMessage << "S Level " << level << " term " << a
<< " H Hirep = " << Hterm << std::endl;
H += Hterm;
2016-07-28 16:44:41 +01:00
}
}
} S_hireps{};
// Calculate action
RealD S(Field& U) { // here also U not used
2017-03-10 14:54:53 +00:00
RealD H = - FieldImplementation::FieldSquareNorm(P); // - trace (P*P)
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
Field& Us =
2018-01-14 22:26:11 +00:00
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;
}
as[level].apply(S_hireps, Representations, level, H);
}
return H;
}
void integrate(Field& U) {
// reset the clocks
t_U = 0;
for (int level = 0; level < as.size(); ++level) {
t_P[level] = 0;
}
for (int step = 0; step < Params.MDsteps; ++step) { // MD step
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);
2017-02-24 17:03:42 +00:00
}
2018-01-14 22:26:11 +00:00
};
2018-01-14 22:26:11 +00:00
NAMESPACE_END(Grid);
#endif // INTEGRATOR_INCLUDED