//-------------------------------------------------------------------- /*! @file Integrator_base.h * @brief Declaration of classes for the abstract Molecular Dynamics integrator * * @author Guido Cossu */ //-------------------------------------------------------------------- #ifndef INTEGRATOR_INCLUDED #define INTEGRATOR_INCLUDED #include class Observer; /*! @brief Abstract base class for Molecular Dynamics management */ namespace Grid{ namespace QCD{ typedef Action* ActPtr; // now force the same size as the rest of the code typedef std::vector ActionLevel; typedef std::vector ActionSet; typedef std::vector ObserverList; struct IntegratorParameters{ int Nexp; int MDsteps; // number of outer steps RealD trajL; // trajectory length RealD stepsize; IntegratorParameters(int Nexp_, int MDsteps_, RealD trajL_): Nexp(Nexp_),MDsteps(MDsteps_),trajL(trajL_),stepsize(trajL/MDsteps){}; }; namespace MDutils{ void generate_momenta(LatticeLorentzColourMatrix&,GridParallelRNG&); void generate_momenta_su3(LatticeLorentzColourMatrix&,GridParallelRNG&); } template< class IntegratorPolicy > class Integrator{ private: IntegratorParameters Params; const ActionSet as; const std::vector Nrel; //relative step size per level std::unique_ptr P; GridParallelRNG pRNG; //ObserverList observers; // not yet IntegratorPolicy TheIntegrator; void register_observers(); void notify_observers(); void update_P(LatticeLorentzColourMatrix&U, int level,double ep){ for(int a=0; aderiv(U,force); *P -= force*ep; } } void update_U(LatticeLorentzColourMatrix&U, double ep){ //rewrite exponential to deal automatically with the lorentz index? LatticeColourMatrix Umu(U._grid); LatticeColourMatrix Pmu(U._grid); for (int mu = 0; mu < Nd; mu++){ Umu=peekLorentz(U, mu); Pmu=peekLorentz(*P, mu); Umu = expMat(Pmu, ep, Params.Nexp)*Umu; pokeLorentz(U, Umu, mu); } } friend void IntegratorPolicy::step (LatticeLorentzColourMatrix& U, int level, std::vector& clock, Integrator* Integ); public: Integrator(GridBase* grid, IntegratorParameters Par, ActionSet& Aset, std::vector Nrel_): Params(Par),as(Aset),Nrel(Nrel_),P(new LatticeLorentzColourMatrix(grid)),pRNG(grid){ assert(as.size() == Nrel.size()); pRNG.SeedRandomDevice(); }; ~Integrator(){} //Initialization of momenta and actions void init(LatticeLorentzColourMatrix& U){ std::cout<< "Integrator init\n"; MDutils::generate_momenta(*P,pRNG); for(int level=0; level< as.size(); ++level){ for(int actionID=0; actionIDinit(U, pRNG); } } } // Calculate action RealD S(LatticeLorentzColourMatrix& U){ LatticeComplex Hloc(U._grid); Hloc = zero; // Momenta for (int mu=0; mu S(U); return H; } void integrate(LatticeLorentzColourMatrix& U, int level){ std::vector clock; clock.resize(as.size(),0); for(int step=0; step< Params.MDsteps; ++step) // MD step TheIntegrator.step(U,0,clock, (this)); } }; class MinimumNorm2{ const double lambda = 0.1931833275037836; public: void step (LatticeLorentzColourMatrix& U, int level, std::vector& clock, Integrator* Integ){ // level : current level // fl : final level // eps : current step size int fl = Integ->as.size() -1; double eps = Integ->Params.stepsize; for(int l=0; l<=level; ++l) eps/= 2.0*Integ->Nrel[l]; int fin = Integ->Nrel[0]; for(int l=1; l<=level; ++l) fin*= 2.0*Integ->Nrel[l]; fin = 3*Integ->Params.MDsteps*fin -1; for(int e=0; eNrel[level]; ++e){ if(clock[level] == 0){ // initial half step Integ->update_P(U,level,lambda*eps); ++clock[level]; for(int l=0; lupdate_U(U,0.5*eps); for(int l=0; lupdate_P(U,level,(1.0-2.0*lambda)*eps); ++clock[level]; for(int l=0; lupdate_U(U,0.5*eps); for(int l=0; lupdate_P(U,level,lambda*eps); ++clock[level]; for(int l=0; lupdate_P(U,level,lambda*2.0*eps); clock[level]+=2; for(int l=0; l& clock, Integrator* Integ){ // fl : final level // eps : current step size int fl = Integ->as.size() -1; double eps = Integ->Params.stepsize; // Get current level step size for(int l=0; l<=level; ++l) eps/= Integ->Nrel[l]; int fin = 1; for(int l=0; l<=level; ++l) fin*= Integ->Nrel[l]; fin = 2*Integ->Params.MDsteps*fin - 1; for(int e=0; eNrel[level]; ++e){ if(clock[level] == 0){ // initial half step Integ->update_P(U, level,eps/2.0); ++clock[level]; for(int l=0; lupdate_U(U, eps); for(int l=0; lupdate_P(U, level,eps/2.0); ++clock[level]; for(int l=0; lupdate_P(U, level,eps); clock[level]+=2; for(int l=0; l