45#include "integrators/LangevinPiston.hpp"
55#include "brains/Thermo.hpp"
56#include "integrators/IntegratorCreator.hpp"
58#include "utils/Constants.hpp"
59#include "utils/simError.h"
63 LangevinPiston::LangevinPiston(
SimInfo* info) :
NPT(info) {
65 NkBT = info_->getNGlobalIntegrableObjects() * Constants::kB * targetTemp;
72 if (!simParams->haveLangevinPistonDrag()) {
73 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
74 "To use the LangevinPiston integrator, you must "
75 "set langevinPistonDrag "
77 painCave.severity = OPENMD_ERROR;
81 gamma_ = simParams->getLangevinPistonDrag();
87 randNumGen_ = info->getRandomNumberGenerator();
91 std::sqrt(2.0 * W_ * gamma_ * Constants::kB * targetTemp / dt);
93 forceDistribution_ = std::normal_distribution<RealType>(0.0, stdDev);
99 genRandomForce(randomForce_);
102 void LangevinPiston::moveA() {
103 SimInfo::MoleculeIterator i;
104 Molecule::IntegrableObjectIterator j;
117 instaTemp = thermo.getTemperature();
119 instaPress = Constants::pressureConvert *
120 (press(0, 0) + press(1, 1) + press(2, 2)) / 3.0;
121 instaVol = thermo.getVolume();
131 for (sd = mol->beginIntegrableObject(j); sd != NULL;
132 sd = mol->nextIntegrableObject(j)) {
138 getVelScaleA(sc, vel);
142 vel += dt2 * Constants::energyConvert / mass * frc - dt2 * sc;
154 ji += dt2 * Constants::energyConvert * Tb;
156 rotAlgo_->rotate(sd, ji, dt);
170 for (sd = mol->beginIntegrableObject(j); sd != NULL;
171 sd = mol->nextIntegrableObject(j)) {
172 oldPos[index++] = sd->
getPos();
178 for (
int k = 0; k < maxIterNum_; k++) {
182 for (sd = mol->beginIntegrableObject(j); sd != NULL;
183 sd = mol->nextIntegrableObject(j)) {
187 this->getPosScale(pos, COM, index, sc);
189 pos = oldPos[index] + dt * (vel + sc);
196 rattle_->constraintA();
206 void LangevinPiston::moveB(
void) {
207 SimInfo::MoleculeIterator i;
208 Molecule::IntegrableObjectIterator j;
225 for (sd = mol->beginIntegrableObject(j); sd != NULL;
226 sd = mol->nextIntegrableObject(j)) {
227 oldVel[index] = sd->
getVel();
235 instaVol = thermo.getVolume();
237 for (
int k = 0; k < maxIterNum_; k++) {
238 instaTemp = thermo.getTemperature();
239 instaPress = thermo.getPressure();
243 this->calcVelScale();
248 for (sd = mol->beginIntegrableObject(j); sd != NULL;
249 sd = mol->nextIntegrableObject(j)) {
253 getVelScaleB(sc, index);
256 vel = oldVel[index] + dt2 * Constants::energyConvert / mass * frc -
265 ji = oldJi[index] + dt2 * Constants::energyConvert * Tb;
274 rattle_->constraintB();
275 if (this->etaConverged())
break;
282 void LangevinPiston::evolveEtaA() {
286 eta += dt2 * (instaVol * (instaPress - targetPressure) /
287 (Constants::pressureConvert * W_) -
288 gamma_ * eta + randomForce_ / W_);
292 void LangevinPiston::evolveEtaB() {
295 genRandomForce(randomForce_);
297 eta = oldEta + dt2 * (instaVol * (instaPress - targetPressure) /
298 (Constants::pressureConvert * W_) -
299 gamma_ * eta + randomForce_ / W_);
302 void LangevinPiston::calcVelScale() { vScale = eta; }
308 void LangevinPiston::getVelScaleB(
Vector3d& sc,
int index) {
309 sc = vScale * oldVel[index];
314 Vector3d rj = (oldPos[index] + pos) / (RealType)2.0 - COM;
318 void LangevinPiston::scaleSimBox() {
319 RealType scaleFactor;
322 scaleFactor = exp(dt * eta);
324 if ((scaleFactor > 1.1) || (scaleFactor < 0.9)) {
325 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
326 "LangevinPiston error: Attempting a Box scaling of more than 10 "
328 " check your tauBarostat, as it is probably too small!\n"
329 " eta = %lf, scaleFactor = %lf\n",
331 painCave.isFatal = 1;
340 bool LangevinPiston::etaConverged() {
341 return (fabs(prevEta - eta) <= etaTolerance);
344 void LangevinPiston::loadEta() {
345 Mat3x3d etaMat = snap->getBarostat();
349 void LangevinPiston::saveEta() {
354 snap->setBarostat(etaMat);
357 void LangevinPiston::genRandomForce(RealType& randomForce) {
359 if (worldRank == 0) {
361 randomForce = forceDistribution_(*randNumGen_);
366 MPI_Bcast(&randomForce, 1, MPI_REALTYPE, 0, MPI_COMM_WORLD);
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Molecule * beginMolecule(MoleculeIterator &i)
Returns the first molecule in this SimInfo and intialize the iterator.
Molecule * nextMolecule(MoleculeIterator &i)
Returns the next avaliable Molecule based on the iterator.
Mat3x3d getHmat()
Returns the H-Matrix.
void setHmat(const Mat3x3d &m)
Sets the H-Matrix.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
Vector3d getTrq()
Returns the current torque of this stuntDouble.
Vector3d lab2Body(const Vector3d &v)
Converts a lab fixed vector to a body fixed vector.
Vector3d getVel()
Returns the current velocity of this stuntDouble.
RealType getMass()
Returns the mass of this stuntDouble.
Vector3d getPos()
Returns the current position of this stuntDouble.
void setPos(const Vector3d &pos)
Sets the current position of this stuntDouble.
void setVel(const Vector3d &vel)
Sets the current velocity of this stuntDouble.
Vector3d getJ()
Returns the current angular momentum of this stuntDouble (body -fixed).
bool isDirectional()
Tests if this stuntDouble is a directional one.
Vector3d getFrc()
Returns the current force of this stuntDouble.
void setJ(const Vector3d &angMom)
Sets the current angular momentum of this stuntDouble (body-fixed).
Mat3x3d getPressureTensor()
gives the pressure tensor in amu*fs^-2*Ang^-1
Vector3d getCom()
Returns the center of the mass of the whole system.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.