////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2008 The Regents of the University of California
//
// This file is part of Qbox
//
// Qbox is distributed 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.
// See the file COPYING in the root directory of this distribution
// or .
//
////////////////////////////////////////////////////////////////////////////////
//
// BMDIonicStepper.C
//
////////////////////////////////////////////////////////////////////////////////
#include "BMDIonicStepper.h"
using namespace std;
////////////////////////////////////////////////////////////////////////////////
void BMDIonicStepper::compute_r(double e0, const vector >& f0)
{
// f0 contains forces at r0
// e0 contains energy at r0
// Compute new positions rp using the velocity Verlet algorithm
// enforce constraints for rp
// update rm <- r0, r0 <- rp, and update atomset
// compute rp
for ( int is = 0; is < r0_.size(); is++ )
for ( int i = 0; i < r0_[is].size(); i++ )
rp_[is][i] = r0_[is][i] + v0_[is][i] + bmd_fac_ * f0[is][i];
constraints_.enforce_r(r0_,rp_);
rm_ = r0_;
fm_ = f0;
em_ = e0_;
r0_ = rp_;
atoms_.set_positions(r0_);
}
////////////////////////////////////////////////////////////////////////////////
void BMDIonicStepper::compute_v(double e0, const vector >& f0)
{
// compute velocities v0_ using r0_, rm_ and f0(r0)
// enforce constraints for vp
// adjust velocities with the thermostat
e0_ = e0;
for ( int is = 0; is < v0_.size(); is++ )
for ( int i = 0; i < v0_[is].size(); i++ )
v0_[is][i] = r0_[is][i] - rm_[is][i] + bmd_fac_ * f0[is][i];
// check if energy increased
if ( e0_ > em_ )
{
// rescale velocity or reset to zero
for ( int is = 0; is < r0_.size(); is++ )
for ( int i = 0; i < r0_[is].size(); i++ )
{
// stop if velocity component is opposed to force
if ( v0_[is][i] * f0[is][i] < 0.0 )
v0_[is][i] = 0.0;
}
}
else
{
// accelerate
for ( int is = 0; is < r0_.size(); is++ )
for ( int i = 0; i < r0_[is].size(); i++ )
v0_[is][i] *= 1.05;
}
constraints_.enforce_v(r0_,v0_);
compute_ekin();
}
////////////////////////////////////////////////////////////////////////////////
void BMDIonicStepper::compute_ekin(void)
{
ekin_ = 0.0;
for ( int is = 0; is < v0_.size(); is++ )
{
for ( int i = 0; i < v0_[is].size(); i++ )
{
const double v = v0_[is][i];
ekin_ += v * v / ( 4.0 * bmd_fac_ );
}
}
}