/* * Langevin.cpp * * Created on: Aug 20, 2010 * Author: crueger */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include "Langevin.hpp" #include "element.hpp" #include "config.hpp" #include "CodePatterns/Verbose.hpp" #include "CodePatterns/Log.hpp" #include "ThermoStatContainer.hpp" #include #include #include #include "RandomNumbers/RandomNumberGeneratorFactory.hpp" #include "RandomNumbers/RandomNumberGenerator.hpp" Langevin::Langevin(double _TempFrequency,double _alpha) : TempFrequency(_TempFrequency), alpha(_alpha), rng_engine(new boost::mt19937), rng_distribution(NULL) {} Langevin::Langevin() : TempFrequency(2.5), alpha(0.), rng_engine(new boost::mt19937), rng_distribution(NULL) {} Langevin::~Langevin() { delete rng_engine; delete rng_distribution; } const char *ThermostatTraits::name = "Langevin"; std::string ThermostatTraits::getName(){ return ThermostatTraits::name; } Thermostat *ThermostatTraits::make(class ConfigFileBuffer * const fb){ double TempFrequency; double alpha; const int verbose = 0; ParseForParameter(verbose,fb,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read gamma if (ParseForParameter(verbose,fb,"Thermostat", 0, 3, 1, double_type, &alpha, 1, optional)) { DoLog(2) && (Log() << Verbose(2) << "Extended Stochastic Thermostat detected with interpolation coefficient " << alpha << "." << endl); } else { alpha = 1.; } return new Langevin(TempFrequency,alpha); } double Langevin::scaleAtoms(unsigned int step,double ActualTemp,ATOMSET(std::list) atoms){ return doScaleAtoms(step,ActualTemp,atoms.begin(),atoms.end()); } double Langevin::scaleAtoms(unsigned int step,double ActualTemp,ATOMSET(std::vector) atoms){ return doScaleAtoms(step,ActualTemp,atoms.begin(),atoms.end()); } double Langevin::scaleAtoms(unsigned int step,double ActualTemp,ATOMSET(std::set) atoms){ return doScaleAtoms(step,ActualTemp,atoms.begin(),atoms.end()); } template double Langevin::doScaleAtoms(unsigned int step,double ActualTemp,ForwardIterator begin, ForwardIterator end){ DoLog(2) && (Log() << Verbose(2) << "Applying Langevin thermostat..." << endl); RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator("mt19937", "normal_distribution"); const double rng_min = random.min(); const double rng_max = random.max(); double ekin=0; for(ForwardIterator iter=begin;iter!=end;++iter){ double sigma = sqrt(getContainer().TargetTemp/(*iter)->getType()->getMass()); // sigma = (k_b T)/m (Hartree/atomicmass = atomiclength/atomictime) rng_distribution = new boost::normal_distribution<>(0,sigma); boost::variate_generator > rng(*rng_engine, *rng_distribution); Vector U = (*iter)->getAtomicVelocityAtStep(step); if ((*iter)->getFixedIon() == 0) { // even FixedIon moves, only not by other's forces // throw a dice to determine whether it gets hit by a heat bath particle if (((((random()/(rng_max-rng_min)))*TempFrequency) < 1.)) { DoLog(3) && (Log() << Verbose(3) << "Particle " << (**iter) << " was hit (sigma " << sigma << "): " << U.Norm() << " -> "); // pick three random numbers from a Boltzmann distribution around the desired temperature T for each momenta axis for (int d=0; dgetType()->getMass() * U.NormSquared(); } (*iter)->setAtomicVelocityAtStep(step, U); delete rng_distribution; rng_distribution = NULL; } return ekin; } std::string Langevin::name(){ return ThermostatTraits::name; } std::string Langevin::writeParams(){ stringstream sstr; sstr << TempFrequency << "\t" << alpha; return sstr.str(); }