48#include "constraints/Rattle.hpp"
57#include "utils/simError.h"
62 info_(info), maxConsIteration_(10), consTolerance_(1.0e-6),
63 doRattle_(false), currConstraintTime_(0.0) {
64 if (info_->getNGlobalConstraints() > 0) doRattle_ =
true;
66 if (!doRattle_)
return;
68 Globals* simParams = info_->getSimParams();
70 if (simParams->haveDt()) {
71 dt_ = simParams->getDt();
73 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
74 "Rattle Error: dt is not set\n");
79 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
80 if (simParams->haveConstraintTime()) {
81 constraintTime_ = simParams->getConstraintTime();
83 constraintTime_ = simParams->getStatusTime();
86 constraintOutputFile_ =
87 getPrefix(info_->getFinalConfigFileName()) +
".constraintForces";
91 new ConstraintWriter(info_, constraintOutputFile_.c_str());
93 if (!constraintWriter_) {
94 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
95 "Failed to create ConstraintWriter\n");
101 Rattle::~Rattle() {
delete constraintWriter_; }
103 void Rattle::constraintA() {
104 if (!doRattle_)
return;
105 doConstraint(&Rattle::constraintPairA);
107 void Rattle::constraintB() {
108 if (!doRattle_)
return;
109 doConstraint(&Rattle::constraintPairB);
111 if (currentSnapshot_->getTime() >= currConstraintTime_) {
113 SimInfo::MoleculeIterator mi;
114 ConstraintPair* consPair;
115 Molecule::ConstraintPairIterator cpi;
116 std::list<ConstraintPair*> constraints;
117 for (mol = info_->beginMolecule(mi); mol != NULL;
118 mol = info_->nextMolecule(mi)) {
119 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
120 consPair = mol->nextConstraintPair(cpi)) {
121 constraints.push_back(consPair);
124 constraintWriter_->writeConstraintForces(constraints);
125 currConstraintTime_ += constraintTime_;
129 void Rattle::doConstraint(ConstraintPairFuncPtr func) {
130 if (!doRattle_)
return;
133 SimInfo::MoleculeIterator mi;
134 ConstraintElem* consElem;
135 Molecule::ConstraintElemIterator cei;
136 ConstraintPair* consPair;
137 Molecule::ConstraintPairIterator cpi;
139 for (mol = info_->beginMolecule(mi); mol != NULL;
140 mol = info_->nextMolecule(mi)) {
141 for (consElem = mol->beginConstraintElem(cei); consElem != NULL;
142 consElem = mol->nextConstraintElem(cei)) {
143 consElem->setMoved(
true);
144 consElem->setMoving(
false);
146 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
147 consPair = mol->nextConstraintPair(cpi)) {
148 consPair->resetConstraintForce();
155 while (!done && iteration < maxConsIteration_) {
160 for (mol = info_->beginMolecule(mi); mol != NULL;
161 mol = info_->nextMolecule(mi)) {
162 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
163 consPair = mol->nextConstraintPair(cpi)) {
165 if (consPair->isMoved()) {
166 int exeStatus = (this->*func)(consPair);
170 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
171 "Constraint failure in Rattle::constrainA, "
172 "Constraint Fail\n");
173 painCave.isFatal = 1;
180 consPair->getConsElem1()->setMoving(
true);
181 consPair->getConsElem2()->setMoving(
true);
188 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
189 "ConstraintAlgorithm::doConstraint() "
190 "Error: unrecognized status");
191 painCave.isFatal = 1;
200 MPI_Allreduce(MPI_IN_PLACE, &done, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
205 for (mol = info_->beginMolecule(mi); mol != NULL;
206 mol = info_->nextMolecule(mi)) {
207 for (consElem = mol->beginConstraintElem(cei); consElem != NULL;
208 consElem = mol->nextConstraintElem(cei)) {
209 consElem->setMoved(consElem->getMoving());
210 consElem->setMoving(
false);
217 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
218 "Constraint failure in Rattle::constrainA, "
219 "too many iterations: %d\n",
221 painCave.isFatal = 1;
228 int Rattle::constraintPairA(ConstraintPair* consPair) {
229 ConstraintElem* consElem1 = consPair->getConsElem1();
230 ConstraintElem* consElem2 = consPair->getConsElem2();
232 Vector3d posA = consElem1->getPos();
233 Vector3d posB = consElem2->getPos();
235 Vector3d pab = posA - posB;
239 currentSnapshot_->wrapVector(pab);
243 RealType rabsq = consPair->getConsDistSquare();
244 RealType diffsq = rabsq - pabsq;
247 if (fabs(diffsq) > (consTolerance_ * rabsq * 2.0)) {
248 Vector3d oldPosA = consElem1->getPrevPos();
249 Vector3d oldPosB = consElem2->getPrevPos();
251 Vector3d rab = oldPosA - oldPosB;
253 currentSnapshot_->wrapVector(rab);
255 RealType rpab =
dot(rab, pab);
256 RealType rpabsq = rpab * rpab;
258 if (rpabsq < (rabsq * -diffsq)) {
return consFail; }
260 RealType rma = 1.0 / consElem1->getMass();
261 RealType rmb = 1.0 / consElem2->getMass();
263 RealType gab = diffsq / (2.0 * (rma + rmb) * rpab);
265 Vector3d delta = rab * gab;
269 consElem1->setPos(posA);
273 consElem2->setPos(posB);
278 Vector3d velA = consElem1->getVel();
280 consElem1->setVel(velA);
283 Vector3d velB = consElem2->getVel();
285 consElem2->setVel(velB);
288 Vector3d fcons = 2.0 * delta / dt_;
289 RealType proj = copysign(fcons.length(),
dot(fcons, rab));
291 consPair->addConstraintForce(proj);
298 int Rattle::constraintPairB(ConstraintPair* consPair) {
299 ConstraintElem* consElem1 = consPair->getConsElem1();
300 ConstraintElem* consElem2 = consPair->getConsElem2();
302 Vector3d velA = consElem1->getVel();
303 Vector3d velB = consElem2->getVel();
305 Vector3d dv = velA - velB;
307 Vector3d posA = consElem1->getPos();
308 Vector3d posB = consElem2->getPos();
310 Vector3d rab = posA - posB;
312 currentSnapshot_->wrapVector(rab);
314 RealType rma = 1.0 / consElem1->getMass();
315 RealType rmb = 1.0 / consElem2->getMass();
317 RealType rvab =
dot(rab, dv);
319 RealType gab = -rvab / ((rma + rmb) * consPair->getConsDistSquare());
321 if (fabs(gab) > consTolerance_) {
322 Vector3d delta = rab * gab;
324 consElem1->setVel(velA);
327 consElem2->setVel(velB);
331 Vector3d fcons = 2.0 * delta / dt_;
332 RealType proj = copysign(fcons.length(),
dot(fcons, rab));
334 consPair->addConstraintForce(proj);
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Real lengthSquare() const
Returns the squared length of this vector.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
std::string getPrefix(const std::string &str)