45#include "constraints/ZconstraintForceModifier.hpp"
53#include "integrators/Integrator.hpp"
54#include "utils/Constants.hpp"
56#include "utils/simError.h"
60 ZConstraintForceModifier::ZConstraintForceModifier(
SimInfo* info) :
62 Globals* simParam = info_->getSimParams();
63 currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
64 currZconsTime_ = currSnapshot_->getTime();
66 if (simParam->haveDt()) {
67 dt_ = simParam->getDt();
69 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
70 "ZconstraintForceManager Error: dt is not set\n");
75 if (simParam->haveZconsTime()) {
76 zconsTime_ = simParam->getZconsTime();
78 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
79 "ZconstraintForceManager error: If you use a ZConstraint,\n"
80 "\tyou must set zconsTime.\n");
85 if (simParam->haveZconsTol()) {
86 zconsTol_ = simParam->getZconsTol();
89 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
90 "ZconstraintForceManager Warning: Tolerance for z-constraint "
91 "method is not specified.\n"
92 "\tOpenMD will use a default value of %f.\n"
93 "\tTo set the tolerance, use the zconsTol variable.\n",
100 if (simParam->haveZconsGap()) {
101 usingZconsGap_ =
true;
102 zconsGap_ = simParam->getZconsGap();
104 usingZconsGap_ =
false;
109 if (simParam->haveZconsFixtime()) {
110 zconsFixingTime_ = simParam->getZconsFixtime();
112 zconsFixingTime_ = infiniteTime;
116 if (simParam->haveZconsUsingSMD()) {
117 usingSMD_ = simParam->getZconsUsingSMD();
122 zconsOutput_ =
getPrefix(info_->getFinalConfigFileName()) +
".fz";
125 Mat3x3d hmat = currSnapshot_->getHmat();
126 RealType halfOfLargestBox =
127 std::max(hmat(0, 0), std::max(hmat(1, 1), hmat(2, 2))) / 2;
129 if (simParam->haveTargetTemp()) {
130 targetTemp = simParam->getTargetTemp();
134 RealType zforceConstant =
135 Constants::kb * targetTemp / (halfOfLargestBox * halfOfLargestBox);
137 int nZconstraints = simParam->getNZconsStamps();
138 std::vector<ZConsStamp*> stamp = simParam->getZconsStamps();
140 for (
int i = 0; i < nZconstraints; i++) {
142 int zmolIndex = stamp[i]->getMolIndex();
143 if (stamp[i]->haveZpos()) {
149 param.
kz = zforceConstant * stamp[i]->getKratio();
151 if (stamp[i]->haveCantVel()) {
152 param.
cantVel = stamp[i]->getCantVel();
157 allZMolIndices_.insert(std::make_pair(zmolIndex, param));
166 totMassUnconsMols_ = 0.0;
167 std::vector<Molecule*>::iterator j;
168 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
169 totMassUnconsMols_ += (*j)->getMass();
172 MPI_Allreduce(MPI_IN_PLACE, &totMassUnconsMols_, 1, MPI_REALTYPE, MPI_SUM,
182 fzOut =
new ZConsWriter(info_, zconsOutput_.c_str());
185 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
186 "ZconstraintForceManager:: Failed to create ZConsWriter\n");
187 painCave.isFatal = 1;
192 ZConstraintForceModifier::~ZConstraintForceModifier() {
delete fzOut; }
194 RealType ZConstraintForceModifier::getZTargetPos(
int index) {
200 zTargetPos = com[whichDirection];
203 if (whichProc == worldRank) {
206 zTargetPos = com[whichDirection];
207 MPI_Bcast(&zTargetPos, 1, MPI_REALTYPE, whichProc, MPI_COMM_WORLD);
209 MPI_Bcast(&zTargetPos, 1, MPI_REALTYPE, whichProc, MPI_COMM_WORLD);
215 void ZConstraintForceModifier::update() {
217 movingZMols_.clear();
218 unzconsMols_.clear();
220 for (std::map<int, ZconstraintParam>::iterator i = allZMolIndices_.begin();
221 i != allZMolIndices_.end(); ++i) {
228 zmol.param = i->second;
235 RealType diff = fabs(d[whichDirection]);
237 if (diff < zconsTol_) {
238 fixedZMols_.push_back(zmol);
240 movingZMols_.push_back(zmol);
248 calcTotalMassMovingZMols();
250 std::set<int> zmolSet;
251 for (std::list<ZconstraintMol>::iterator i = movingZMols_.begin();
252 i != movingZMols_.end(); ++i) {
253 zmolSet.insert(i->mol->getGlobalIndex());
256 for (std::list<ZconstraintMol>::iterator i = fixedZMols_.begin();
257 i != fixedZMols_.end(); ++i) {
258 zmolSet.insert(i->mol->getGlobalIndex());
261 SimInfo::MoleculeIterator mi;
266 unzconsMols_.push_back(mol);
271 void ZConstraintForceModifier::calcTotalMassMovingZMols() {
272 totMassMovingZMols_ = 0.0;
273 std::list<ZconstraintMol>::iterator i;
274 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
275 totMassMovingZMols_ += i->mol->getMass();
279 MPI_Allreduce(MPI_IN_PLACE, &totMassMovingZMols_, 1, MPI_REALTYPE, MPI_SUM,
284 bool ZConstraintForceModifier::isZMol(
Molecule* mol) {
286 allZMolIndices_.end() ?
291 void ZConstraintForceModifier::modifyForces() {
294 if (usingZconsGap_) { updateZPos(); }
296 if (checkZConsState()) {
297 calcTotalMassMovingZMols();
302 if (haveFixedZMols()) { doZconstraintForce(); }
305 if (haveMovingZMols()) { doHarmonic(); }
308 if (currSnapshot_->getTime() >= currZconsTime_) {
309 std::list<ZconstraintMol>::iterator i;
311 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
312 com = i->mol->getCom();
313 i->zpos = com[whichDirection];
316 fzOut->writeFZ(fixedZMols_);
317 currZconsTime_ += zconsTime_;
321 void ZConstraintForceModifier::updateZPos() {
322 std::list<ZconstraintMol>::iterator i;
323 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
324 i->param.zTargetPos += zconsGap_;
328 bool ZConstraintForceModifier::checkZConsState() {
333 std::list<ZconstraintMol>::iterator i;
334 std::list<ZconstraintMol>::iterator j;
336 std::list<ZconstraintMol> newMovingZMols;
337 for (i = fixedZMols_.begin(); i != fixedZMols_.end();) {
338 com = i->mol->getCom();
342 RealType diff = fabs(d[whichDirection]);
344 if (diff > zconsTol_) {
345 if (usingZconsGap_) { i->endFixingTime = infiniteTime; }
347 newMovingZMols.push_back(*j);
348 fixedZMols_.erase(j);
355 std::list<ZconstraintMol> newFixedZMols;
356 for (i = movingZMols_.begin(); i != movingZMols_.end();) {
357 com = i->mol->getCom();
360 diff = fabs(d[whichDirection]);
362 if (diff <= zconsTol_) {
363 if (usingZconsGap_) {
364 i->endFixingTime = currSnapshot_->getTime() + zconsFixingTime_;
368 newFixedZMols.push_back(*j);
369 movingZMols_.erase(j);
377 fixedZMols_.insert(fixedZMols_.end(), newFixedZMols.begin(),
378 newFixedZMols.end());
379 movingZMols_.insert(movingZMols_.end(), newMovingZMols.begin(),
380 newMovingZMols.end());
383 MPI_Allreduce(MPI_IN_PLACE, &changed, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
386 return (changed > 0);
389 void ZConstraintForceModifier::zeroVelocity() {
392 std::list<ZconstraintMol>::iterator i;
395 Molecule::IntegrableObjectIterator ii;
399 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
403 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
404 sd = mol->nextIntegrableObject(ii)) {
406 vel[whichDirection] -= comVel[whichDirection];
415 RealType pzMovingMols = 0.0;
417 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
420 pzMovingMols += mol->
getMass() * comVel[whichDirection];
423 std::vector<Molecule*>::iterator j;
424 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
427 pzMovingMols += mol->
getMass() * comVel[whichDirection];
431 MPI_Allreduce(MPI_IN_PLACE, &pzMovingMols, 1, MPI_REALTYPE, MPI_SUM,
435 RealType vzMovingMols =
436 pzMovingMols / (totMassMovingZMols_ + totMassUnconsMols_);
440 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
443 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
444 sd = mol->nextIntegrableObject(ii)) {
446 vel[whichDirection] -= vzMovingMols;
452 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
455 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
456 sd = mol->nextIntegrableObject(ii)) {
458 vel[whichDirection] -= vzMovingMols;
464 bool ZConstraintForceModifier::haveFixedZMols() {
465 int haveFixed = fixedZMols_.empty() ? 0 : 1;
468 MPI_Allreduce(MPI_IN_PLACE, &haveFixed, 1, MPI_INT, MPI_SUM,
472 return haveFixed > 0;
477 void ZConstraintForceModifier::doZconstraintForce() {
478 RealType totalFZ(0.0);
482 std::list<ZconstraintMol>::iterator i;
485 Molecule::IntegrableObjectIterator ii;
487 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
491 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
492 sd = mol->nextIntegrableObject(ii)) {
493 i->fz += (sd->
getFrc())[whichDirection];
501 MPI_Allreduce(MPI_IN_PLACE, &totalFZ, 1, MPI_REALTYPE, MPI_SUM,
506 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
509 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
510 sd = mol->nextIntegrableObject(ii)) {
512 force[whichDirection] = -getZFOfFixedZMols(mol, sd, i->fz);
520 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
524 force[whichDirection] = -getZFOfMovingMols(mol, totalFZ);
526 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
527 sd = mol->nextIntegrableObject(ii)) {
534 std::vector<Molecule*>::iterator j;
535 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
539 force[whichDirection] = -getZFOfMovingMols(mol, totalFZ);
541 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
542 sd = mol->nextIntegrableObject(ii)) {
550 RealType ZConstraintForceModifier::getZFOfFixedZMols(
Molecule* mol,
552 RealType totalForce) {
558 RealType ZConstraintForceModifier::getZFOfMovingMols(
Molecule* mol,
559 RealType totalForce) {
560 return totalForce * mol->
getMass() /
561 (totMassUnconsMols_ + totMassMovingZMols_);
564 bool ZConstraintForceModifier::haveMovingZMols() {
565 int haveMoving = movingZMols_.empty() ? 0 : 1;
568 MPI_Allreduce(MPI_IN_PLACE, &haveMoving, 1, MPI_INT, MPI_SUM,
572 return haveMoving > 0;
577 void ZConstraintForceModifier::doHarmonic() {
578 RealType totalFZ(0.0);
581 RealType restPot(0.0);
582 std::list<ZconstraintMol>::iterator i;
584 Molecule::IntegrableObjectIterator ii;
587 RealType pe = currSnapshot_->getPotentialEnergy();
588 currSnapshot_->setRawPotential(pe);
590 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
593 RealType resPos = usingSMD_ ? i->cantPos : i->param.zTargetPos;
597 RealType diff = d[whichDirection];
599 restPot += 0.5 * i->param.kz * diff * diff;
601 RealType harmonicF = -(i->param.kz * diff);
602 totalFZ += harmonicF;
605 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
606 sd = mol->nextIntegrableObject(ii)) {
607 force[whichDirection] = getHFOfFixedZMols(mol, sd, harmonicF);
613 MPI_Allreduce(MPI_IN_PLACE, &restPot, 1, MPI_REALTYPE, MPI_SUM,
615 MPI_Allreduce(MPI_IN_PLACE, &totalFZ, 1, MPI_REALTYPE, MPI_SUM,
619 RealType rp = currSnapshot_->getRestraintPotential();
620 currSnapshot_->setRestraintPotential(rp + restPot);
622 currSnapshot_->setPotentialEnergy(pe + restPot);
625 std::vector<Molecule*>::iterator j;
626 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
628 force[whichDirection] = getHFOfUnconsMols(mol, totalFZ);
630 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
631 sd = mol->nextIntegrableObject(ii)) {
637 RealType ZConstraintForceModifier::getHFOfFixedZMols(
Molecule* mol,
639 RealType totalForce) {
643 RealType ZConstraintForceModifier::getHFOfUnconsMols(
Molecule* mol,
644 RealType totalForce) {
645 return totalForce * mol->
getMass() / totMassUnconsMols_;
Abstract class for external ForceModifier classes.
RealType getMass()
get total mass of this molecule
int getGlobalIndex()
Returns the global index of this molecule.
Vector3d getComVel()
Returns the velocity of center of mass of this molecule.
Vector3d getCom()
Returns the current center of mass position of this molecule.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Molecule * getMoleculeByGlobalIndex(int index)
Finds a molecule with a specified global index.
int getMolToProc(int globalIndex)
Finds the processor where a molecule resides.
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.
SnapshotManager * getSnapshotManager()
Returns the snapshot manager.
void wrapVector(Vector3d &v)
Wrapping the vector according to periodic boundary condition.
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
Vector3d getVel()
Returns the current velocity of this stuntDouble.
RealType getMass()
Returns the mass of this stuntDouble.
void setVel(const Vector3d &vel)
Sets the current velocity of this stuntDouble.
Vector3d getFrc()
Returns the current force of this stuntDouble.
void addFrc(const Vector3d &frc)
Adds force into the current force of this stuntDouble.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)
RealType cantPos
current position of cantilever
RealType zTargetPos
target zconstraint position
RealType kz
force constant
RealType cantVel
The velocity of cantilever.