48#include "integrators/BAOAB.hpp"
50#include "utils/Constants.hpp"
52#include "math/CholeskyDecomposition.hpp"
53#include "utils/Constants.hpp"
54#include "hydrodynamics/Sphere.hpp"
55#include "hydrodynamics/Ellipsoid.hpp"
57#include "types/LennardJonesAdapter.hpp"
58#include "types/GayBerneAdapter.hpp"
63 simParams = info->getSimParams();
66 sphericalBoundaryConditions_ =
false;
67 if (simParams->getUseSphericalBoundaryConditions()) {
68 sphericalBoundaryConditions_ =
true;
69 if (simParams->haveLangevinBufferRadius()) {
70 langevinBufferRadius_ = simParams->getLangevinBufferRadius();
72 sprintf( painCave.errMsg,
73 "langevinBufferRadius must be specified "
74 "when useSphericalBoundaryConditions is turned on.\n");
75 painCave.severity = OPENMD_ERROR;
80 if (simParams->haveFrozenBufferRadius()) {
81 frozenBufferRadius_ = simParams->getFrozenBufferRadius();
83 sprintf( painCave.errMsg,
84 "frozenBufferRadius must be specified "
85 "when useSphericalBoundaryConditions is turned on.\n");
86 painCave.severity = OPENMD_ERROR;
91 if (frozenBufferRadius_ < langevinBufferRadius_) {
92 sprintf( painCave.errMsg,
93 "frozenBufferRadius has been set smaller than the "
94 "langevinBufferRadius. This is probably an error.\n");
95 painCave.severity = OPENMD_WARNING;
105 SimInfo::MoleculeIterator i;
106 Molecule::IntegrableObjectIterator j;
107 bool needHydroPropFile =
false;
112 for (sd = mol->beginIntegrableObject(j); sd != NULL;
113 sd = mol->nextIntegrableObject(j)) {
117 if (rb->
getNumAtoms() > 1) needHydroPropFile =
true;
123 if (needHydroPropFile) {
124 if (simParams->haveHydroPropFile()) {
125 hydroPropMap_ = parseFrictionFile(simParams->getHydroPropFile());
127 sprintf( painCave.errMsg,
128 "HydroPropFile must be set to a file name if Langevin Dynamics\n"
129 "\tis specified for rigidBodies which contain more than one atom\n"
130 "\tTo create a HydroPropFile, run the \"Hydro\" program.\n");
131 painCave.severity = OPENMD_ERROR;
132 painCave.isFatal = 1;
139 for (sd = mol->beginIntegrableObject(j); sd != NULL;
140 sd = mol->nextIntegrableObject(j)) {
142 map<string, HydroProp*>::iterator iter = hydroPropMap_.find(sd->
getType());
143 if (iter != hydroPropMap_.end()) {
145 hydroProps_.push_back(iter->second);
146 moments_.push_back(getMomentData(sd));
149 sprintf( painCave.errMsg,
150 "Can not find resistance tensor for atom [%s]\n",
152 painCave.severity = OPENMD_ERROR;
153 painCave.isFatal = 1;
164 for (sd = mol->beginIntegrableObject(j); sd != NULL;
165 sd = mol->nextIntegrableObject(j)) {
167 Shape* currShape = NULL;
170 Atom* atom =
static_cast<Atom*
>(sd);
173 if (gba.isGayBerne()) {
174 currShape =
new Ellipsoid(V3Zero, gba.getL() / 2.0,
179 if (lja.isLennardJones()){
180 currShape =
new Sphere(atom->
getPos(), lja.getSigma()/2.0);
184 vector<AtomType*> atChain = atomType->allYourBase();
185 vector<AtomType*>::iterator i;
186 for (i = atChain.begin(); i != atChain.end(); ++i) {
195 sprintf( painCave.errMsg,
196 "Could not find atom type in default element.txt\n");
197 painCave.severity = OPENMD_ERROR;
198 painCave.isFatal = 1;
205 if (!simParams->haveTargetTemp()) {
206 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
207 "You can't use BAOAB without a targetTemp!\n");
208 painCave.isFatal = 1;
209 painCave.severity = OPENMD_ERROR;
213 if (!simParams->haveViscosity()) {
214 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
215 "You can't use BAOAB without a viscosity!\n");
216 painCave.isFatal = 1;
217 painCave.severity = OPENMD_ERROR;
222 HydroProp* currHydroProp = currShape->getHydroProp(simParams->getViscosity(),simParams->getTargetTemp());
223 map<string, HydroProp*>::iterator iter = hydroPropMap_.find(sd->
getType());
224 if (iter != hydroPropMap_.end()) {
226 hydroProps_.push_back(iter->second);
227 moments_.push_back(getMomentData(sd));
230 currHydroProp->complete();
231 hydroPropMap_.insert(map<string, HydroProp*>::value_type(sd->
getType(), currHydroProp));
232 hydroProps_.push_back(currHydroProp);
233 moments_.push_back(getMomentData(sd));
239 variance_ = 2.0 * Constants::kb*simParams->getTargetTemp()/simParams->getDt();
243 if (method == LANGEVIN_METHOD_BAOAB) {
245 VelocityStep(0.5 * dt);
246 ResolveVelocityConstraints(0.5 * dt);
249 PositionStep(0.5 * dt);
250 ResolvePositionConstraints(0.5 * dt);
251 ResolveVelocityConstraints(0.5 * dt);
255 ResolveVelocityConstraints(dt);
258 PositionStep(0.5 * dt);
259 ResolvePositionConstraints(0.5 * dt);
260 ResolveVelocityConstraints(0.5 * dt);
265 VelocityStep(0.5 * dt);
266 ResolveVelocityConstraints(0.5 * dt);
268 }
else if (method == LANGEVIN_METHOD_ABOBA) {
270 PositionStep(0.5 * dt);
271 ResolvePositionConstraints(0.5 * dt);
272 ResolveVelocityConstraints(0.5 * dt);
277 VelocityStep(0.5 * dt);
278 ResolveVelocityConstraints(0.5 * dt);
282 ResolveVelocityConstraints(dt);
285 VelocityStep(0.5 * dt);
286 ResolveVelocityConstraints(0.5 * dt);
289 PositionStep(0.5 * dt);
290 ResolvePositionConstraints(0.5 * dt);
291 ResolveVelocityConstraints(0.5 * dt);
296 void BAOAB::PositionStep(RealType dt) {
297 SimInfo::MoleculeIterator i;
298 Molecule::IntegrableObjectIterator j;
308 for (sd = mol->beginIntegrableObject(j); sd != NULL;
309 sd = mol->nextIntegrableObject(j)) {
323 rotAlgo_->rotate(sd, ji, dt);
332 SimInfo::MoleculeIterator i;
333 Molecule::IntegrableObjectIterator j;
343 unsigned int index = 0;
344 bool doLangevinForces;
353 doLangevinForces =
true;
354 freezeMolecule =
false;
356 if (sphericalBoundaryConditions_) {
359 RealType molRad = molPos.
length();
361 doLangevinForces =
false;
363 if (molRad > langevinBufferRadius_) {
364 doLangevinForces =
true;
365 freezeMolecule =
false;
367 if (molRad > frozenBufferRadius_) {
368 doLangevinForces =
false;
369 freezeMolecule =
true;
373 for (sd = mol->beginIntegrableObject(j); sd != NULL;
374 sd = mol->nextIntegrableObject(j)) {
379 if (doLangevinForces) {
387 Atrans = A.transpose();
389 Vector3d rcrLab = Atrans * moments_[index]->rcr;
395 genRandomForceAndTorque(randomForceBody, randomTorqueBody,
397 Vector3d randomForceLab = Atrans * randomForceBody;
398 Vector3d randomTorqueLab = Atrans * randomTorqueBody;
399 sd->
addFrc(randomForceLab);
400 sd->
addTrq(randomTorqueLab +
cross(rcrLab, randomForceLab ));
419 Vector3d velStep = vel + (dt2_ /mass * Constants::energyConvert) * frc;
422 Vector3d angMomStep = angMom + (dt2_ * Constants::energyConvert) * Tb;
438 for (
int k = 0; k < maxIterNum_; k++) {
442 int l = (linearAxis +1 )%3;
443 int m = (linearAxis +2 )%3;
444 omegaBody[l] = angMomStep[l] /moments_[index]->Icr(l, l);
445 omegaBody[m] = angMomStep[m] /moments_[index]->Icr(m, m);
448 omegaBody = moments_[index]->IcrInv * angMomStep;
454 omegaLab = Atrans * omegaBody;
458 vcdLab = velStep +
cross(omegaLab, rcrLab);
459 vcdBody = A * vcdLab;
460 frictionForceBody = -(hydroProps_[index]->getXitt() * vcdBody +
461 hydroProps_[index]->getXirt() * omegaBody);
462 oldFFL = frictionForceLab;
463 frictionForceLab = Atrans * frictionForceBody;
464 oldFTB = frictionTorqueBody;
465 frictionTorqueBody = -(hydroProps_[index]->getXitr() * vcdBody +
466 hydroProps_[index]->getXirr() * omegaBody);
467 frictionTorqueLab = Atrans * frictionTorqueBody;
471 velStep = vel + (dt2_ / mass * Constants::energyConvert) * (frc + frictionForceLab);
472 angMomStep = angMom + (dt2_ * Constants::energyConvert) * (Tb + frictionTorqueBody);
476 fdot =
dot(frictionForceLab, oldFFL) / frictionForceLab.lengthSquare();
477 tdot =
dot(frictionTorqueBody, oldFTB) / frictionTorqueBody.lengthSquare();
479 if (fabs(1.0 - fdot) <= forceTolerance_ &&
480 fabs(1.0 - tdot) <= forceTolerance_)
484 sd->
addFrc(frictionForceLab);
485 sd->
addTrq(frictionTorqueLab +
cross(rcrLab, frictionForceLab));
493 genRandomForceAndTorque(randomForce, randomTorque,
511 Vector3d velStep = vel + (dt2_ / mass * Constants::energyConvert) * frc;
519 for (
int k = 0; k < maxIterNum_; k++) {
521 oldFF = frictionForce;
522 frictionForce = -hydroProps_[index]->getXitt() * velStep;
526 velStep = vel + (dt2_ / mass * Constants::energyConvert) * (frc + frictionForce);
531 fdot =
dot(frictionForce, oldFF) / frictionForce.lengthSquare();
533 if (fabs(1.0 - fdot) <= forceTolerance_)
537 sd->
addFrc(frictionForce);
550 if(!simParams->getUsePeriodicBoundaryConditions())
553 ForceManager::postCalculation();
557 void BAOAB::VelocityStep(RealType dt) {
558 SimInfo::MoleculeIterator i;
559 Molecule::IntegrableObjectIterator j;
571 for (sd = mol->beginIntegrableObject(j); sd != NULL;
572 sd = mol->nextIntegrableObject(j)) {
578 vel += (dt * Constants::energyConvert / mass) * frc;
592 ji += (dt * Constants::energyConvert) * Tb;
600 map<string, HydroProp*> BAOAB::parseFrictionFile(
const string& filename) {
601 map<string, HydroProp*> props;
602 ifstream ifs(filename.c_str());
607 const unsigned int BufferSize = 65535;
608 char buffer[BufferSize];
609 while (ifs.getline(buffer, BufferSize)) {
611 props.insert(map<string, HydroProp*>::value_type(currProp->getName(),
620 map<string, MomentData*>::iterator j = momentsMap_.find(sd->
getType());
621 if (j != momentsMap_.end()) {
626 map<string, HydroProp*>::iterator i = hydroPropMap_.find(sd->
getType());
628 if (i != hydroPropMap_.end()) {
630 moment->
rcr = i->second->getCOR();
632 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
633 "LDForceManager createMomentData: Couldn't find HydroProp for\n"
634 "object type %s!\n", sd->
getType().c_str());
635 painCave.isFatal = 1;
636 painCave.severity = OPENMD_ERROR;
641 moment->
rcr -=
dynamic_cast<RigidBody*
>(sd)->getRefCOM();
646 moment->Ir = sd->
getI();
648 outProduct(moment->
rcr, moment->
rcr));
655 Mr.setSubMatrix(3,3, moment->Ir);
660 CholeskyDecomposition(Mr, mr);
662 Mat6x6d GammaR = -(i->second->getXi() * MrInv);
665 Mat6x6d sigma = sqrt(2.0*Constants::kb*simParams->getTargetTemp()) * S*mr;
674 eigensystem.getRealEigenvalues(evals);
675 eigensystem.getV(evects);
680 momentsMap_.insert(map<string, MomentData*>::value_type(sd->
getType(),
687 void BAOAB::genRandomForceAndTorque(
Vector3d& force,
694 Z[0] = randNumGen_.randNorm(0, variance);
695 Z[1] = randNumGen_.randNorm(0, variance);
696 Z[2] = randNumGen_.randNorm(0, variance);
697 Z[3] = randNumGen_.randNorm(0, variance);
698 Z[4] = randNumGen_.randNorm(0, variance);
699 Z[5] = randNumGen_.randNorm(0, variance);
701 generalForce = hydroProps_[index]->getS()*Z;
703 force[0] = generalForce[0];
704 force[1] = generalForce[1];
705 force[2] = generalForce[2];
706 torque[0] = generalForce[3];
707 torque[1] = generalForce[4];
708 torque[2] = generalForce[5];
This basic Periodic Table class was originally taken from the data.h file in OpenBabel.
Computes eigenvalues and eigenvectors of a real (non-complex) matrix.
AtomType * getAtomType()
Returns the AtomType of this Atom.
AtomType is what OpenMD looks to for unchanging data about an atom.
virtual void step()
Computes an integration step from t to t+dt.
Dynamically-sized vector class.
RealType GetVdwRad(int atomicnum)
int GetAtomicNum(const char *str)
An ellipsoid in OpenMD is restricted to having two equal equatorial semi-axes.
Container for information about the hydrodynamic behavior of objects interacting with surroundings.
Declaration of the Integrator base class, which all other integrators inherit from.
Vector3d getCom()
Returns the current center of mass position of this molecule.
size_t getNumAtoms()
Returns the number of atoms in this rigid body.
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.
void setFdf(int fdf)
sets the current number of frozen degrees of freedom
static SquareMatrix< RealType, Dim > identity()
SquareMatrix< Real, Dim > inverse()
Returns the inverse of this 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.
RotMat3x3d getA()
Returns the current rotation matrix of this stuntDouble.
Vector3d getVel()
Returns the current velocity of this stuntDouble.
int linearAxis()
Returns the linear axis of the rigidbody, atom and directional atom will always return -1.
RealType getMass()
Returns the mass of this stuntDouble.
virtual Mat3x3d getI()=0
Returns the inertia tensor of this stuntDouble.
virtual std::string getType()=0
Returns the name of this stuntDouble.
bool isLinear()
Tests the if this stuntDouble is a linear rigidbody.
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.
void addTrq(const Vector3d &trq)
Adds torque into the current torque of this stuntDouble.
bool isRigidBody()
Tests if this stuntDouble is a rigid body.
Vector3d getJ()
Returns the current angular momentum of this stuntDouble (body -fixed).
bool isAtom()
Tests if this stuntDouble is an atom.
bool isDirectional()
Tests if this stuntDouble is a directional one.
int freeze()
Freezes out all velocity, angular velocity, forces and torques on this StuntDouble.
Vector3d getFrc()
Returns the current force of this stuntDouble.
void setJ(const Vector3d &angMom)
Sets the current angular momentum of this stuntDouble (body-fixed).
void addFrc(const Vector3d &frc)
Adds force into the current force of this stuntDouble.
Real length()
Returns the length of this vector.
Velocity-modifying routines.
void removeComDrift()
Removes Center of Mass Drift Velocity Removes the center of mass drift velocity (required for accurat...
void removeAngularDrift()
Removes Center of Mass Angular momentum Removes the center of mass angular momentum (particularly use...
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
Vector3d rcr
Distance between CoM and Center of Resistance.