48#include "constraints/ZconstraintForceModifier.hpp"
56#include "integrators/Integrator.hpp"
57#include "utils/Constants.hpp"
59#include "utils/simError.h"
63 ZConstraintForceModifier::ZConstraintForceModifier(
SimInfo* info) :
65 Globals* simParam = info_->getSimParams();
66 currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
67 currZconsTime_ = currSnapshot_->getTime();
69 if (simParam->haveDt()) {
70 dt_ = simParam->getDt();
72 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
73 "ZconstraintForceManager Error: dt is not set\n");
78 if (simParam->haveZconsTime()) {
79 zconsTime_ = simParam->getZconsTime();
81 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
82 "ZconstraintForceManager error: If you use a ZConstraint,\n"
83 "\tyou must set zconsTime.\n");
88 if (simParam->haveZconsTol()) {
89 zconsTol_ = simParam->getZconsTol();
92 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
93 "ZconstraintForceManager Warning: Tolerance for z-constraint "
94 "method is not specified.\n"
95 "\tOpenMD will use a default value of %f.\n"
96 "\tTo set the tolerance, use the zconsTol variable.\n",
103 if (simParam->haveZconsGap()) {
104 usingZconsGap_ =
true;
105 zconsGap_ = simParam->getZconsGap();
107 usingZconsGap_ =
false;
112 if (simParam->haveZconsFixtime()) {
113 zconsFixingTime_ = simParam->getZconsFixtime();
115 zconsFixingTime_ = infiniteTime;
119 if (simParam->haveZconsUsingSMD()) {
120 usingSMD_ = simParam->getZconsUsingSMD();
125 zconsOutput_ =
getPrefix(info_->getFinalConfigFileName()) +
".fz";
128 Mat3x3d hmat = currSnapshot_->getHmat();
129 RealType halfOfLargestBox =
130 std::max(hmat(0, 0), std::max(hmat(1, 1), hmat(2, 2))) / 2;
132 if (simParam->haveTargetTemp()) {
133 targetTemp = simParam->getTargetTemp();
137 RealType zforceConstant =
138 Constants::kb * targetTemp / (halfOfLargestBox * halfOfLargestBox);
140 int nZconstraints = simParam->getNZconsStamps();
141 std::vector<ZConsStamp*> stamp = simParam->getZconsStamps();
143 for (
int i = 0; i < nZconstraints; i++) {
144 ZconstraintParam param;
145 int zmolIndex = stamp[i]->getMolIndex();
146 if (stamp[i]->haveZpos()) {
147 param.zTargetPos = stamp[i]->getZpos();
149 param.zTargetPos = getZTargetPos(zmolIndex);
152 param.kz = zforceConstant * stamp[i]->getKratio();
154 if (stamp[i]->haveCantVel()) {
155 param.cantVel = stamp[i]->getCantVel();
160 allZMolIndices_.insert(std::make_pair(zmolIndex, param));
169 totMassUnconsMols_ = 0.0;
170 std::vector<Molecule*>::iterator j;
171 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
172 totMassUnconsMols_ += (*j)->getMass();
175 MPI_Allreduce(MPI_IN_PLACE, &totMassUnconsMols_, 1, MPI_REALTYPE, MPI_SUM,
185 fzOut =
new ZConsWriter(info_, zconsOutput_.c_str());
188 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
189 "ZconstraintForceManager:: Failed to create ZConsWriter\n");
190 painCave.isFatal = 1;
195 ZConstraintForceModifier::~ZConstraintForceModifier() {
delete fzOut; }
197 RealType ZConstraintForceModifier::getZTargetPos(
int index) {
200 Molecule* mol = info_->getMoleculeByGlobalIndex(index);
202 Vector3d com = mol->getCom();
203 zTargetPos = com[whichDirection];
205 int whichProc = info_->getMolToProc(index);
206 if (whichProc == worldRank) {
207 Molecule* mol = info_->getMoleculeByGlobalIndex(index);
208 Vector3d com = mol->getCom();
209 zTargetPos = com[whichDirection];
210 MPI_Bcast(&zTargetPos, 1, MPI_REALTYPE, whichProc, MPI_COMM_WORLD);
212 MPI_Bcast(&zTargetPos, 1, MPI_REALTYPE, whichProc, MPI_COMM_WORLD);
218 void ZConstraintForceModifier::update() {
220 movingZMols_.clear();
221 unzconsMols_.clear();
223 for (std::map<int, ZconstraintParam>::iterator i = allZMolIndices_.begin();
224 i != allZMolIndices_.end(); ++i) {
226 if (info_->getMolToProc(i->first) == worldRank) {
229 zmol.mol = info_->getMoleculeByGlobalIndex(i->first);
231 zmol.param = i->second;
232 zmol.cantPos = zmol.param.zTargetPos;
235 Vector3d com = zmol.mol->getCom();
236 Vector3d d = Vector3d(0.0, 0.0, zmol.param.zTargetPos) - com;
237 currSnapshot_->wrapVector(d);
238 RealType diff = fabs(d[whichDirection]);
240 if (diff < zconsTol_) {
241 fixedZMols_.push_back(zmol);
243 movingZMols_.push_back(zmol);
251 calcTotalMassMovingZMols();
253 std::set<int> zmolSet;
254 for (std::list<ZconstraintMol>::iterator i = movingZMols_.begin();
255 i != movingZMols_.end(); ++i) {
256 zmolSet.insert(i->mol->getGlobalIndex());
259 for (std::list<ZconstraintMol>::iterator i = fixedZMols_.begin();
260 i != fixedZMols_.end(); ++i) {
261 zmolSet.insert(i->mol->getGlobalIndex());
264 SimInfo::MoleculeIterator mi;
266 for (mol = info_->beginMolecule(mi); mol != NULL;
267 mol = info_->nextMolecule(mi)) {
268 if (zmolSet.find(mol->getGlobalIndex()) == zmolSet.end()) {
269 unzconsMols_.push_back(mol);
274 void ZConstraintForceModifier::calcTotalMassMovingZMols() {
275 totMassMovingZMols_ = 0.0;
276 std::list<ZconstraintMol>::iterator i;
277 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
278 totMassMovingZMols_ += i->mol->getMass();
282 MPI_Allreduce(MPI_IN_PLACE, &totMassMovingZMols_, 1, MPI_REALTYPE, MPI_SUM,
287 bool ZConstraintForceModifier::isZMol(Molecule* mol) {
288 return allZMolIndices_.find(mol->getGlobalIndex()) ==
289 allZMolIndices_.end() ?
294 void ZConstraintForceModifier::modifyForces() {
295 currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
297 if (usingZconsGap_) { updateZPos(); }
299 if (checkZConsState()) {
300 calcTotalMassMovingZMols();
305 if (haveFixedZMols()) { doZconstraintForce(); }
308 if (haveMovingZMols()) { doHarmonic(); }
311 if (currSnapshot_->getTime() >= currZconsTime_) {
312 std::list<ZconstraintMol>::iterator i;
314 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
315 com = i->mol->getCom();
316 i->zpos = com[whichDirection];
319 fzOut->writeFZ(fixedZMols_);
320 currZconsTime_ += zconsTime_;
324 void ZConstraintForceModifier::updateZPos() {
325 std::list<ZconstraintMol>::iterator i;
326 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
327 i->param.zTargetPos += zconsGap_;
331 bool ZConstraintForceModifier::checkZConsState() {
336 std::list<ZconstraintMol>::iterator i;
337 std::list<ZconstraintMol>::iterator j;
339 std::list<ZconstraintMol> newMovingZMols;
340 for (i = fixedZMols_.begin(); i != fixedZMols_.end();) {
341 com = i->mol->getCom();
342 Vector3d d = com - Vector3d(0.0, 0.0, i->param.zTargetPos);
343 currSnapshot_->wrapVector(d);
345 RealType diff = fabs(d[whichDirection]);
347 if (diff > zconsTol_) {
348 if (usingZconsGap_) { i->endFixingTime = infiniteTime; }
350 newMovingZMols.push_back(*j);
351 fixedZMols_.erase(j);
358 std::list<ZconstraintMol> newFixedZMols;
359 for (i = movingZMols_.begin(); i != movingZMols_.end();) {
360 com = i->mol->getCom();
361 Vector3d d = com - Vector3d(0.0, 0.0, i->param.zTargetPos);
362 currSnapshot_->wrapVector(d);
363 diff = fabs(d[whichDirection]);
365 if (diff <= zconsTol_) {
366 if (usingZconsGap_) {
367 i->endFixingTime = currSnapshot_->getTime() + zconsFixingTime_;
371 newFixedZMols.push_back(*j);
372 movingZMols_.erase(j);
380 fixedZMols_.insert(fixedZMols_.end(), newFixedZMols.begin(),
381 newFixedZMols.end());
382 movingZMols_.insert(movingZMols_.end(), newMovingZMols.begin(),
383 newMovingZMols.end());
386 MPI_Allreduce(MPI_IN_PLACE, &changed, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
389 return (changed > 0);
392 void ZConstraintForceModifier::zeroVelocity() {
395 std::list<ZconstraintMol>::iterator i;
398 Molecule::IntegrableObjectIterator ii;
402 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
404 comVel = mol->getComVel();
406 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
407 sd = mol->nextIntegrableObject(ii)) {
409 vel[whichDirection] -= comVel[whichDirection];
418 RealType pzMovingMols = 0.0;
420 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
422 comVel = mol->getComVel();
423 pzMovingMols += mol->getMass() * comVel[whichDirection];
426 std::vector<Molecule*>::iterator j;
427 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
429 comVel = mol->getComVel();
430 pzMovingMols += mol->getMass() * comVel[whichDirection];
434 MPI_Allreduce(MPI_IN_PLACE, &pzMovingMols, 1, MPI_REALTYPE, MPI_SUM,
438 RealType vzMovingMols =
439 pzMovingMols / (totMassMovingZMols_ + totMassUnconsMols_);
443 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
446 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
447 sd = mol->nextIntegrableObject(ii)) {
449 vel[whichDirection] -= vzMovingMols;
455 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
458 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
459 sd = mol->nextIntegrableObject(ii)) {
461 vel[whichDirection] -= vzMovingMols;
467 bool ZConstraintForceModifier::haveFixedZMols() {
468 int haveFixed = fixedZMols_.empty() ? 0 : 1;
471 MPI_Allreduce(MPI_IN_PLACE, &haveFixed, 1, MPI_INT, MPI_SUM,
475 return haveFixed > 0;
480 void ZConstraintForceModifier::doZconstraintForce() {
481 RealType totalFZ(0.0);
485 std::list<ZconstraintMol>::iterator i;
488 Molecule::IntegrableObjectIterator ii;
490 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
494 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
495 sd = mol->nextIntegrableObject(ii)) {
496 i->fz += (sd->getFrc())[whichDirection];
504 MPI_Allreduce(MPI_IN_PLACE, &totalFZ, 1, MPI_REALTYPE, MPI_SUM,
509 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
512 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
513 sd = mol->nextIntegrableObject(ii)) {
515 force[whichDirection] = -getZFOfFixedZMols(mol, sd, i->fz);
523 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
527 force[whichDirection] = -getZFOfMovingMols(mol, totalFZ);
529 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
530 sd = mol->nextIntegrableObject(ii)) {
537 std::vector<Molecule*>::iterator j;
538 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
542 force[whichDirection] = -getZFOfMovingMols(mol, totalFZ);
544 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
545 sd = mol->nextIntegrableObject(ii)) {
553 RealType ZConstraintForceModifier::getZFOfFixedZMols(Molecule* mol,
555 RealType totalForce) {
556 return totalForce * sd->getMass() / mol->getMass();
561 RealType ZConstraintForceModifier::getZFOfMovingMols(Molecule* mol,
562 RealType totalForce) {
563 return totalForce * mol->getMass() /
564 (totMassUnconsMols_ + totMassMovingZMols_);
567 bool ZConstraintForceModifier::haveMovingZMols() {
568 int haveMoving = movingZMols_.empty() ? 0 : 1;
571 MPI_Allreduce(MPI_IN_PLACE, &haveMoving, 1, MPI_INT, MPI_SUM,
575 return haveMoving > 0;
580 void ZConstraintForceModifier::doHarmonic() {
581 RealType totalFZ(0.0);
584 RealType restPot(0.0);
585 std::list<ZconstraintMol>::iterator i;
587 Molecule::IntegrableObjectIterator ii;
590 RealType pe = currSnapshot_->getPotentialEnergy();
591 currSnapshot_->setRawPotential(pe);
593 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
595 Vector3d com = mol->getCom();
596 RealType resPos = usingSMD_ ? i->cantPos : i->param.zTargetPos;
597 Vector3d d = com - Vector3d(0.0, 0.0, resPos);
598 currSnapshot_->wrapVector(d);
600 RealType diff = d[whichDirection];
602 restPot += 0.5 * i->param.kz * diff * diff;
604 RealType harmonicF = -(i->param.kz * diff);
605 totalFZ += harmonicF;
608 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
609 sd = mol->nextIntegrableObject(ii)) {
610 force[whichDirection] = getHFOfFixedZMols(mol, sd, harmonicF);
616 MPI_Allreduce(MPI_IN_PLACE, &restPot, 1, MPI_REALTYPE, MPI_SUM,
618 MPI_Allreduce(MPI_IN_PLACE, &totalFZ, 1, MPI_REALTYPE, MPI_SUM,
622 RealType rp = currSnapshot_->getRestraintPotential();
623 currSnapshot_->setRestraintPotential(rp + restPot);
625 currSnapshot_->setPotentialEnergy(pe + restPot);
628 std::vector<Molecule*>::iterator j;
629 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
631 force[whichDirection] = getHFOfUnconsMols(mol, totalFZ);
633 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
634 sd = mol->nextIntegrableObject(ii)) {
640 RealType ZConstraintForceModifier::getHFOfFixedZMols(Molecule* mol,
642 RealType totalForce) {
643 return totalForce * sd->getMass() / mol->getMass();
646 RealType ZConstraintForceModifier::getHFOfUnconsMols(Molecule* mol,
647 RealType totalForce) {
648 return totalForce * mol->getMass() / totMassUnconsMols_;
Abstract class for external ForceModifier classes.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)