45#include "constraints/Shake.hpp"
52#include "utils/simError.h"
56 Shake::Shake(SimInfo* info) :
57 info_(info), maxConsIteration_(10), consTolerance_(1.0e-6),
58 doShake_(false), currConstraintTime_(0.0) {
59 if (info_->getNGlobalConstraints() > 0) doShake_ =
true;
61 if (!doShake_)
return;
63 Globals* simParams = info_->getSimParams();
65 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
66 if (simParams->haveConstraintTime()) {
67 constraintTime_ = simParams->getConstraintTime();
69 constraintTime_ = simParams->getStatusTime();
72 constraintOutputFile_ =
73 getPrefix(info_->getFinalConfigFileName()) +
".constraintForces";
77 new ConstraintWriter(info_, constraintOutputFile_.c_str());
79 if (!constraintWriter_) {
80 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
81 "Failed to create ConstraintWriter\n");
87 void Shake::constraintR() {
88 if (!doShake_)
return;
89 doConstraint(&Shake::constraintPairR);
91 void Shake::constraintF() {
92 if (!doShake_)
return;
93 doConstraint(&Shake::constraintPairF);
95 if (currentSnapshot_->getTime() >= currConstraintTime_) {
97 SimInfo::MoleculeIterator mi;
98 ConstraintPair* consPair;
99 Molecule::ConstraintPairIterator cpi;
100 std::list<ConstraintPair*> constraints;
101 for (mol = info_->beginMolecule(mi); mol != NULL;
102 mol = info_->nextMolecule(mi)) {
103 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
104 consPair = mol->nextConstraintPair(cpi)) {
105 constraints.push_back(consPair);
109 constraintWriter_->writeConstraintForces(constraints);
110 currConstraintTime_ += constraintTime_;
114 void Shake::doConstraint(ConstraintPairFuncPtr func) {
115 if (!doShake_)
return;
118 SimInfo::MoleculeIterator mi;
119 ConstraintElem* consElem;
120 Molecule::ConstraintElemIterator cei;
121 ConstraintPair* consPair;
122 Molecule::ConstraintPairIterator cpi;
124 for (mol = info_->beginMolecule(mi); mol != NULL;
125 mol = info_->nextMolecule(mi)) {
126 for (consElem = mol->beginConstraintElem(cei); consElem != NULL;
127 consElem = mol->nextConstraintElem(cei)) {
128 consElem->setMoved(
true);
129 consElem->setMoving(
false);
136 while (!done && iteration < maxConsIteration_) {
141 for (mol = info_->beginMolecule(mi); mol != NULL;
142 mol = info_->nextMolecule(mi)) {
143 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
144 consPair = mol->nextConstraintPair(cpi)) {
146 if (consPair->isMoved()) {
147 int exeStatus = (this->*func)(consPair);
151 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
152 "Constraint failure in Shake::constrainA, "
153 "Constraint Fail\n");
154 painCave.isFatal = 1;
161 consPair->getConsElem1()->setMoving(
true);
162 consPair->getConsElem2()->setMoving(
true);
169 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
170 "ConstraintAlgorithm::doConstraint() "
171 "Error: unrecognized status");
172 painCave.isFatal = 1;
181 MPI_Allreduce(MPI_IN_PLACE, &done, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
186 for (mol = info_->beginMolecule(mi); mol != NULL;
187 mol = info_->nextMolecule(mi)) {
188 for (consElem = mol->beginConstraintElem(cei); consElem != NULL;
189 consElem = mol->nextConstraintElem(cei)) {
190 consElem->setMoved(consElem->getMoving());
191 consElem->setMoving(
false);
199 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
200 "Constraint failure in Shake::constrainA, "
201 "too many iterations: %d\n",
203 painCave.isFatal = 1;
213 int Shake::constraintPairR(ConstraintPair* consPair) {
214 ConstraintElem* consElem1 = consPair->getConsElem1();
215 ConstraintElem* consElem2 = consPair->getConsElem2();
217 Vector3d posA = consElem1->getPos();
218 Vector3d posB = consElem2->getPos();
220 Vector3d pab = posA - posB;
224 currentSnapshot_->wrapVector(pab);
228 RealType rabsq = consPair->getConsDistSquare();
229 RealType diffsq = rabsq - pabsq;
232 if (fabs(diffsq) > (consTolerance_ * rabsq * 2)) {
233 Vector3d oldPosA = consElem1->getPrevPos();
234 Vector3d oldPosB = consElem2->getPrevPos();
236 Vector3d rab = oldPosA - oldPosB;
238 currentSnapshot_->wrapVector(rab);
240 RealType rpab =
dot(rab, pab);
241 RealType rpabsq = rpab * rpab;
243 if (rpabsq < (rabsq * -diffsq)) {
return consFail; }
245 RealType rma = 1.0 / consElem1->getMass();
246 RealType rmb = 1.0 / consElem2->getMass();
248 RealType gab = diffsq / (2.0 * (rma + rmb) * rpab);
250 Vector3d delta = rab * gab;
254 consElem1->setPos(posA);
258 consElem2->setPos(posB);
261 consPair->setConstraintForce(gab);
270 int Shake::constraintPairF(ConstraintPair* consPair) {
271 ConstraintElem* consElem1 = consPair->getConsElem1();
272 ConstraintElem* consElem2 = consPair->getConsElem2();
274 Vector3d posA = consElem1->getPos();
275 Vector3d posB = consElem2->getPos();
277 Vector3d rab = posA - posB;
279 currentSnapshot_->wrapVector(rab);
281 Vector3d frcA = consElem1->getFrc();
282 Vector3d frcB = consElem2->getFrc();
284 RealType rma = 1.0 / consElem1->getMass();
285 RealType rmb = 1.0 / consElem2->getMass();
287 Vector3d fpab = frcA * rma - frcB * rmb;
290 if (gab < 1.0) gab = 1.0;
292 RealType rabsq = rab.lengthSquare();
293 RealType rfab =
dot(rab, fpab);
295 if (fabs(rfab) > sqrt(rabsq * gab) * consTolerance_) {
296 gab = -rfab / (rabsq * (rma + rmb));
301 consElem1->setFrc(frcA);
302 consElem2->setFrc(frcB);
305 consPair->setConstraintForce(gab);
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)