void BerendsenThermostatOptimizerState::rescale_velocities() const
{
  MolecularDynamics *md = dynamic_cast<MolecularDynamics *>(get_optimizer());
  IMP_INTERNAL_CHECK(md, "Can only use velocity scaling with "
             "the molecular dynamics optimizer.");

  double kinetic_temp = md->get_kinetic_temperature(md->get_kinetic_energy());
  double rescale = std::sqrt(1.0 + (md->get_last_time_step() / tau_)
                             * (temperature_ / kinetic_temp - 1.0));

  for (unsigned int i=0; i< pis_.size(); ++i) {
    Particle *p = pis_[i];
    for (int i = 0; i < 3; ++i) {
      double velocity = p->get_value(vs_[i]);
      velocity *= rescale;
      p->set_value(vs_[i], velocity);
   }
 }
}
void LangevinThermostatOptimizerState::rescale_velocities() const {
  static const double gas_constant = 8.31441e-7;
  MolecularDynamics *md = dynamic_cast<MolecularDynamics *>(get_optimizer());
  double c1 = exp(-gamma_ * md->get_last_time_step());
  double c2 = sqrt((1.0 - c1) * gas_constant * temperature_);
  IMP_INTERNAL_CHECK(md,
                     "Can only use velocity scaling with "
                     "the molecular dynamics optimizer.");
  boost::normal_distribution<Float> mrng(0., 1.);
  boost::variate_generator<RandomNumberGenerator &,
                           boost::normal_distribution<Float> >
      sampler(random_number_generator, mrng);
  for (unsigned int i = 0; i < pis_.size(); ++i) {
    Particle *p = pis_[i];
    double mass = Mass(p).get_mass();
    LinearVelocity lv(p);
    lv.set_velocity(c1 * lv.get_velocity()
                    + c2 * sqrt((c1 + 1.0) / mass)
                      * algebra::Vector3D(sampler(), sampler(), sampler()));
  }
}