45#include "constraints/Rattle.hpp"
54#include "utils/simError.h"
58 Rattle::Rattle(SimInfo* info) :
59 info_(info), maxConsIteration_(10), consTolerance_(1.0e-6),
60 doRattle_(false), currConstraintTime_(0.0) {
61 if (info_->getNGlobalConstraints() > 0) doRattle_ =
true;
63 if (!doRattle_)
return;
65 Globals* simParams = info_->getSimParams();
67 if (simParams->haveDt()) {
68 dt_ = simParams->getDt();
70 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
71 "Rattle Error: dt is not set\n");
76 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
77 if (simParams->haveConstraintTime()) {
78 constraintTime_ = simParams->getConstraintTime();
80 constraintTime_ = simParams->getStatusTime();
83 constraintOutputFile_ =
84 getPrefix(info_->getFinalConfigFileName()) +
".constraintForces";
88 new ConstraintWriter(info_, constraintOutputFile_.c_str());
90 if (!constraintWriter_) {
91 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
92 "Failed to create ConstraintWriter\n");
98 Rattle::~Rattle() {
delete constraintWriter_; }
100 void Rattle::constraintA() {
101 if (!doRattle_)
return;
102 doConstraint(&Rattle::constraintPairA);
104 void Rattle::constraintB() {
105 if (!doRattle_)
return;
106 doConstraint(&Rattle::constraintPairB);
108 if (currentSnapshot_->getTime() >= currConstraintTime_) {
110 SimInfo::MoleculeIterator mi;
111 ConstraintPair* consPair;
112 Molecule::ConstraintPairIterator cpi;
113 std::list<ConstraintPair*> constraints;
114 for (mol = info_->beginMolecule(mi); mol != NULL;
115 mol = info_->nextMolecule(mi)) {
116 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
117 consPair = mol->nextConstraintPair(cpi)) {
118 constraints.push_back(consPair);
121 constraintWriter_->writeConstraintForces(constraints);
122 currConstraintTime_ += constraintTime_;
126 void Rattle::doConstraint(ConstraintPairFuncPtr func) {
127 if (!doRattle_)
return;
130 SimInfo::MoleculeIterator mi;
131 ConstraintElem* consElem;
132 Molecule::ConstraintElemIterator cei;
133 ConstraintPair* consPair;
134 Molecule::ConstraintPairIterator cpi;
136 for (mol = info_->beginMolecule(mi); mol != NULL;
137 mol = info_->nextMolecule(mi)) {
138 for (consElem = mol->beginConstraintElem(cei); consElem != NULL;
139 consElem = mol->nextConstraintElem(cei)) {
140 consElem->setMoved(
true);
141 consElem->setMoving(
false);
143 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
144 consPair = mol->nextConstraintPair(cpi)) {
145 consPair->resetConstraintForce();
152 while (!done && iteration < maxConsIteration_) {
157 for (mol = info_->beginMolecule(mi); mol != NULL;
158 mol = info_->nextMolecule(mi)) {
159 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
160 consPair = mol->nextConstraintPair(cpi)) {
162 if (consPair->isMoved()) {
163 int exeStatus = (this->*func)(consPair);
167 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
168 "Constraint failure in Rattle::constrainA, "
169 "Constraint Fail\n");
170 painCave.isFatal = 1;
177 consPair->getConsElem1()->setMoving(
true);
178 consPair->getConsElem2()->setMoving(
true);
185 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
186 "ConstraintAlgorithm::doConstraint() "
187 "Error: unrecognized status");
188 painCave.isFatal = 1;
197 MPI_Allreduce(MPI_IN_PLACE, &done, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
202 for (mol = info_->beginMolecule(mi); mol != NULL;
203 mol = info_->nextMolecule(mi)) {
204 for (consElem = mol->beginConstraintElem(cei); consElem != NULL;
205 consElem = mol->nextConstraintElem(cei)) {
206 consElem->setMoved(consElem->getMoving());
207 consElem->setMoving(
false);
214 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
215 "Constraint failure in Rattle::constrainA, "
216 "too many iterations: %d\n",
218 painCave.isFatal = 1;
225 int Rattle::constraintPairA(ConstraintPair* consPair) {
226 ConstraintElem* consElem1 = consPair->getConsElem1();
227 ConstraintElem* consElem2 = consPair->getConsElem2();
229 Vector3d posA = consElem1->getPos();
230 Vector3d posB = consElem2->getPos();
232 Vector3d pab = posA - posB;
236 currentSnapshot_->wrapVector(pab);
240 RealType rabsq = consPair->getConsDistSquare();
241 RealType diffsq = rabsq - pabsq;
244 if (fabs(diffsq) > (consTolerance_ * rabsq * 2.0)) {
245 Vector3d oldPosA = consElem1->getPrevPos();
246 Vector3d oldPosB = consElem2->getPrevPos();
248 Vector3d rab = oldPosA - oldPosB;
250 currentSnapshot_->wrapVector(rab);
252 RealType rpab =
dot(rab, pab);
253 RealType rpabsq = rpab * rpab;
255 if (rpabsq < (rabsq * -diffsq)) {
return consFail; }
257 RealType rma = 1.0 / consElem1->getMass();
258 RealType rmb = 1.0 / consElem2->getMass();
260 RealType gab = diffsq / (2.0 * (rma + rmb) * rpab);
262 Vector3d delta = rab * gab;
266 consElem1->setPos(posA);
270 consElem2->setPos(posB);
275 Vector3d velA = consElem1->getVel();
277 consElem1->setVel(velA);
280 Vector3d velB = consElem2->getVel();
282 consElem2->setVel(velB);
285 Vector3d fcons = 2.0 * delta / dt_;
286 RealType proj = copysign(fcons.length(),
dot(fcons, rab));
288 consPair->addConstraintForce(proj);
295 int Rattle::constraintPairB(ConstraintPair* consPair) {
296 ConstraintElem* consElem1 = consPair->getConsElem1();
297 ConstraintElem* consElem2 = consPair->getConsElem2();
299 Vector3d velA = consElem1->getVel();
300 Vector3d velB = consElem2->getVel();
302 Vector3d dv = velA - velB;
304 Vector3d posA = consElem1->getPos();
305 Vector3d posB = consElem2->getPos();
307 Vector3d rab = posA - posB;
309 currentSnapshot_->wrapVector(rab);
311 RealType rma = 1.0 / consElem1->getMass();
312 RealType rmb = 1.0 / consElem2->getMass();
314 RealType rvab =
dot(rab, dv);
316 RealType gab = -rvab / ((rma + rmb) * consPair->getConsDistSquare());
318 if (fabs(gab) > consTolerance_) {
319 Vector3d delta = rab * gab;
321 consElem1->setVel(velA);
324 consElem2->setVel(velB);
328 Vector3d fcons = 2.0 * delta / dt_;
329 RealType proj = copysign(fcons.length(),
dot(fcons, rab));
331 consPair->addConstraintForce(proj);
Real lengthSquare()
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)