48#include "constraints/Shake.hpp"
55#include "utils/simError.h"
60 info_(info), maxConsIteration_(10), consTolerance_(1.0e-6),
61 doShake_(false), currConstraintTime_(0.0) {
62 if (info_->getNGlobalConstraints() > 0) doShake_ =
true;
64 if (!doShake_)
return;
66 Globals* simParams = info_->getSimParams();
68 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
69 if (simParams->haveConstraintTime()) {
70 constraintTime_ = simParams->getConstraintTime();
72 constraintTime_ = simParams->getStatusTime();
75 constraintOutputFile_ =
76 getPrefix(info_->getFinalConfigFileName()) +
".constraintForces";
80 new ConstraintWriter(info_, constraintOutputFile_.c_str());
82 if (!constraintWriter_) {
83 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
84 "Failed to create ConstraintWriter\n");
90 void Shake::constraintR() {
91 if (!doShake_)
return;
92 doConstraint(&Shake::constraintPairR);
94 void Shake::constraintF() {
95 if (!doShake_)
return;
96 doConstraint(&Shake::constraintPairF);
98 if (currentSnapshot_->getTime() >= currConstraintTime_) {
100 SimInfo::MoleculeIterator mi;
101 ConstraintPair* consPair;
102 Molecule::ConstraintPairIterator cpi;
103 std::list<ConstraintPair*> constraints;
104 for (mol = info_->beginMolecule(mi); mol != NULL;
105 mol = info_->nextMolecule(mi)) {
106 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
107 consPair = mol->nextConstraintPair(cpi)) {
108 constraints.push_back(consPair);
112 constraintWriter_->writeConstraintForces(constraints);
113 currConstraintTime_ += constraintTime_;
117 void Shake::doConstraint(ConstraintPairFuncPtr func) {
118 if (!doShake_)
return;
121 SimInfo::MoleculeIterator mi;
122 ConstraintElem* consElem;
123 Molecule::ConstraintElemIterator cei;
124 ConstraintPair* consPair;
125 Molecule::ConstraintPairIterator cpi;
127 for (mol = info_->beginMolecule(mi); mol != NULL;
128 mol = info_->nextMolecule(mi)) {
129 for (consElem = mol->beginConstraintElem(cei); consElem != NULL;
130 consElem = mol->nextConstraintElem(cei)) {
131 consElem->setMoved(
true);
132 consElem->setMoving(
false);
139 while (!done && iteration < maxConsIteration_) {
144 for (mol = info_->beginMolecule(mi); mol != NULL;
145 mol = info_->nextMolecule(mi)) {
146 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
147 consPair = mol->nextConstraintPair(cpi)) {
149 if (consPair->isMoved()) {
150 int exeStatus = (this->*func)(consPair);
154 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
155 "Constraint failure in Shake::constrainA, "
156 "Constraint Fail\n");
157 painCave.isFatal = 1;
164 consPair->getConsElem1()->setMoving(
true);
165 consPair->getConsElem2()->setMoving(
true);
172 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
173 "ConstraintAlgorithm::doConstraint() "
174 "Error: unrecognized status");
175 painCave.isFatal = 1;
184 MPI_Allreduce(MPI_IN_PLACE, &done, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
189 for (mol = info_->beginMolecule(mi); mol != NULL;
190 mol = info_->nextMolecule(mi)) {
191 for (consElem = mol->beginConstraintElem(cei); consElem != NULL;
192 consElem = mol->nextConstraintElem(cei)) {
193 consElem->setMoved(consElem->getMoving());
194 consElem->setMoving(
false);
202 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
203 "Constraint failure in Shake::constrainA, "
204 "too many iterations: %d\n",
206 painCave.isFatal = 1;
216 int Shake::constraintPairR(ConstraintPair* consPair) {
217 ConstraintElem* consElem1 = consPair->getConsElem1();
218 ConstraintElem* consElem2 = consPair->getConsElem2();
220 Vector3d posA = consElem1->getPos();
221 Vector3d posB = consElem2->getPos();
223 Vector3d pab = posA - posB;
227 currentSnapshot_->wrapVector(pab);
231 RealType rabsq = consPair->getConsDistSquare();
232 RealType diffsq = rabsq - pabsq;
235 if (fabs(diffsq) > (consTolerance_ * rabsq * 2)) {
236 Vector3d oldPosA = consElem1->getPrevPos();
237 Vector3d oldPosB = consElem2->getPrevPos();
239 Vector3d rab = oldPosA - oldPosB;
241 currentSnapshot_->wrapVector(rab);
243 RealType rpab =
dot(rab, pab);
244 RealType rpabsq = rpab * rpab;
246 if (rpabsq < (rabsq * -diffsq)) {
return consFail; }
248 RealType rma = 1.0 / consElem1->getMass();
249 RealType rmb = 1.0 / consElem2->getMass();
251 RealType gab = diffsq / (2.0 * (rma + rmb) * rpab);
253 Vector3d delta = rab * gab;
257 consElem1->setPos(posA);
261 consElem2->setPos(posB);
264 consPair->setConstraintForce(gab);
273 int Shake::constraintPairF(ConstraintPair* consPair) {
274 ConstraintElem* consElem1 = consPair->getConsElem1();
275 ConstraintElem* consElem2 = consPair->getConsElem2();
277 Vector3d posA = consElem1->getPos();
278 Vector3d posB = consElem2->getPos();
280 Vector3d rab = posA - posB;
282 currentSnapshot_->wrapVector(rab);
284 Vector3d frcA = consElem1->getFrc();
285 Vector3d frcB = consElem2->getFrc();
287 RealType rma = 1.0 / consElem1->getMass();
288 RealType rmb = 1.0 / consElem2->getMass();
290 Vector3d fpab = frcA * rma - frcB * rmb;
293 if (gab < 1.0) gab = 1.0;
295 RealType rabsq = rab.lengthSquare();
296 RealType rfab =
dot(rab, fpab);
298 if (fabs(rfab) > sqrt(rabsq * gab) * consTolerance_) {
299 gab = -rfab / (rabsq * (rma + rmb));
304 consElem1->setFrc(frcA);
305 consElem2->setFrc(frcB);
308 consPair->setConstraintForce(gab);
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)