OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
ZconstraintForceModifier.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48#include "constraints/ZconstraintForceModifier.hpp"
49
50#include <cmath>
51
52#ifdef IS_MPI
53#include <mpi.h>
54#endif
55
56#include "integrators/Integrator.hpp"
57#include "utils/Constants.hpp"
58#include "utils/StringUtils.hpp"
59#include "utils/simError.h"
60
61namespace OpenMD {
62
63 ZConstraintForceModifier::ZConstraintForceModifier(SimInfo* info) :
64 ForceModifier {info}, infiniteTime {1e31} {
65 Globals* simParam = info_->getSimParams();
66 currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
67 currZconsTime_ = currSnapshot_->getTime();
68
69 if (simParam->haveDt()) {
70 dt_ = simParam->getDt();
71 } else {
72 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
73 "ZconstraintForceManager Error: dt is not set\n");
74 painCave.isFatal = 1;
75 simError();
76 }
77
78 if (simParam->haveZconsTime()) {
79 zconsTime_ = simParam->getZconsTime();
80 } else {
81 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
82 "ZconstraintForceManager error: If you use a ZConstraint,\n"
83 "\tyou must set zconsTime.\n");
84 painCave.isFatal = 1;
85 simError();
86 }
87
88 if (simParam->haveZconsTol()) {
89 zconsTol_ = simParam->getZconsTol();
90 } else {
91 zconsTol_ = 0.01;
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",
97 zconsTol_);
98 painCave.isFatal = 0;
99 simError();
100 }
101
102 // set zcons gap
103 if (simParam->haveZconsGap()) {
104 usingZconsGap_ = true;
105 zconsGap_ = simParam->getZconsGap();
106 } else {
107 usingZconsGap_ = false;
108 zconsGap_ = 0.0;
109 }
110
111 // set zcons fixtime
112 if (simParam->haveZconsFixtime()) {
113 zconsFixingTime_ = simParam->getZconsFixtime();
114 } else {
115 zconsFixingTime_ = infiniteTime;
116 }
117
118 // set zconsUsingSMD
119 if (simParam->haveZconsUsingSMD()) {
120 usingSMD_ = simParam->getZconsUsingSMD();
121 } else {
122 usingSMD_ = false;
123 }
124
125 zconsOutput_ = getPrefix(info_->getFinalConfigFileName()) + ".fz";
126
127 // estimate the force constant of harmonical potential
128 Mat3x3d hmat = currSnapshot_->getHmat();
129 RealType halfOfLargestBox =
130 std::max(hmat(0, 0), std::max(hmat(1, 1), hmat(2, 2))) / 2;
131 RealType targetTemp;
132 if (simParam->haveTargetTemp()) {
133 targetTemp = simParam->getTargetTemp();
134 } else {
135 targetTemp = 298.0;
136 }
137 RealType zforceConstant =
138 Constants::kb * targetTemp / (halfOfLargestBox * halfOfLargestBox);
139
140 int nZconstraints = simParam->getNZconsStamps();
141 std::vector<ZConsStamp*> stamp = simParam->getZconsStamps();
142
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();
148 } else {
149 param.zTargetPos = getZTargetPos(zmolIndex);
150 }
151
152 param.kz = zforceConstant * stamp[i]->getKratio();
153
154 if (stamp[i]->haveCantVel()) {
155 param.cantVel = stamp[i]->getCantVel();
156 } else {
157 param.cantVel = 0.0;
158 }
159
160 allZMolIndices_.insert(std::make_pair(zmolIndex, param));
161 }
162
163 // create fixedMols_, movingMols_ and unconsMols lists
164 update();
165
166 // calculate mass of unconstrained molecules in the whole system
167 // (never changes during the simulation)
168
169 totMassUnconsMols_ = 0.0;
170 std::vector<Molecule*>::iterator j;
171 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
172 totMassUnconsMols_ += (*j)->getMass();
173 }
174#ifdef IS_MPI
175 MPI_Allreduce(MPI_IN_PLACE, &totMassUnconsMols_, 1, MPI_REALTYPE, MPI_SUM,
176 MPI_COMM_WORLD);
177#endif
178
179 // Zero out the velocities of center of mass of unconstrained
180 // molecules and the velocities of center of mass of every single
181 // z-constrained molecueles
182 zeroVelocity();
183
184 // create zconsWriter
185 fzOut = new ZConsWriter(info_, zconsOutput_.c_str());
186
187 if (!fzOut) {
188 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
189 "ZconstraintForceManager:: Failed to create ZConsWriter\n");
190 painCave.isFatal = 1;
191 simError();
192 }
193 }
194
195 ZConstraintForceModifier::~ZConstraintForceModifier() { delete fzOut; }
196
197 RealType ZConstraintForceModifier::getZTargetPos(int index) {
198 RealType zTargetPos;
199#ifndef IS_MPI
200 Molecule* mol = info_->getMoleculeByGlobalIndex(index);
201 assert(mol);
202 Vector3d com = mol->getCom();
203 zTargetPos = com[whichDirection];
204#else
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);
211 } else {
212 MPI_Bcast(&zTargetPos, 1, MPI_REALTYPE, whichProc, MPI_COMM_WORLD);
213 }
214#endif
215 return zTargetPos;
216 }
217
218 void ZConstraintForceModifier::update() {
219 fixedZMols_.clear();
220 movingZMols_.clear();
221 unzconsMols_.clear();
222
223 for (std::map<int, ZconstraintParam>::iterator i = allZMolIndices_.begin();
224 i != allZMolIndices_.end(); ++i) {
225#ifdef IS_MPI
226 if (info_->getMolToProc(i->first) == worldRank) {
227#endif
228 ZconstraintMol zmol;
229 zmol.mol = info_->getMoleculeByGlobalIndex(i->first);
230 assert(zmol.mol);
231 zmol.param = i->second;
232 zmol.cantPos = zmol.param.zTargetPos; /**@todo fix me when
233 zmol migrates, it is
234 incorrect*/
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]);
239
240 if (diff < zconsTol_) {
241 fixedZMols_.push_back(zmol);
242 } else {
243 movingZMols_.push_back(zmol);
244 }
245
246#ifdef IS_MPI
247 }
248#endif
249 }
250
251 calcTotalMassMovingZMols();
252
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());
257 }
258
259 for (std::list<ZconstraintMol>::iterator i = fixedZMols_.begin();
260 i != fixedZMols_.end(); ++i) {
261 zmolSet.insert(i->mol->getGlobalIndex());
262 }
263
264 SimInfo::MoleculeIterator mi;
265 Molecule* mol;
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);
270 }
271 }
272 }
273
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();
279 }
280
281#ifdef IS_MPI
282 MPI_Allreduce(MPI_IN_PLACE, &totMassMovingZMols_, 1, MPI_REALTYPE, MPI_SUM,
283 MPI_COMM_WORLD);
284#endif
285 }
286
287 bool ZConstraintForceModifier::isZMol(Molecule* mol) {
288 return allZMolIndices_.find(mol->getGlobalIndex()) ==
289 allZMolIndices_.end() ?
290 false :
291 true;
292 }
293
294 void ZConstraintForceModifier::modifyForces() {
295 currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
296
297 if (usingZconsGap_) { updateZPos(); }
298
299 if (checkZConsState()) {
300 calcTotalMassMovingZMols();
301 zeroVelocity();
302 }
303
304 // do zconstraint force;
305 if (haveFixedZMols()) { doZconstraintForce(); }
306
307 // use external force to move the molecules to the specified positions
308 if (haveMovingZMols()) { doHarmonic(); }
309
310 // write out forces and current positions of z-constraint molecules
311 if (currSnapshot_->getTime() >= currZconsTime_) {
312 std::list<ZconstraintMol>::iterator i;
313 Vector3d com;
314 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
315 com = i->mol->getCom();
316 i->zpos = com[whichDirection];
317 }
318
319 fzOut->writeFZ(fixedZMols_);
320 currZconsTime_ += zconsTime_;
321 }
322 }
323
324 void ZConstraintForceModifier::updateZPos() {
325 std::list<ZconstraintMol>::iterator i;
326 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
327 i->param.zTargetPos += zconsGap_;
328 }
329 }
330
331 bool ZConstraintForceModifier::checkZConsState() {
332 Vector3d com;
333 RealType diff;
334 int changed = 0;
335
336 std::list<ZconstraintMol>::iterator i;
337 std::list<ZconstraintMol>::iterator j;
338
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);
344
345 RealType diff = fabs(d[whichDirection]);
346
347 if (diff > zconsTol_) {
348 if (usingZconsGap_) { i->endFixingTime = infiniteTime; }
349 j = i++;
350 newMovingZMols.push_back(*j);
351 fixedZMols_.erase(j);
352 changed = 1;
353 } else {
354 ++i;
355 }
356 }
357
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]);
364
365 if (diff <= zconsTol_) {
366 if (usingZconsGap_) {
367 i->endFixingTime = currSnapshot_->getTime() + zconsFixingTime_;
368 }
369 // This moving zconstraint molecule is now fixed
370 j = i++;
371 newFixedZMols.push_back(*j);
372 movingZMols_.erase(j);
373 changed = 1;
374 } else {
375 ++i;
376 }
377 }
378
379 // merge the lists
380 fixedZMols_.insert(fixedZMols_.end(), newFixedZMols.begin(),
381 newFixedZMols.end());
382 movingZMols_.insert(movingZMols_.end(), newMovingZMols.begin(),
383 newMovingZMols.end());
384
385#ifdef IS_MPI
386 MPI_Allreduce(MPI_IN_PLACE, &changed, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
387#endif
388
389 return (changed > 0);
390 }
391
392 void ZConstraintForceModifier::zeroVelocity() {
393 Vector3d comVel;
394 Vector3d vel;
395 std::list<ZconstraintMol>::iterator i;
396 Molecule* mol;
397 StuntDouble* sd;
398 Molecule::IntegrableObjectIterator ii;
399
400 // Zero out the velocities of center of mass of fixed
401 // z-constrained molecules
402 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
403 mol = i->mol;
404 comVel = mol->getComVel();
405
406 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
407 sd = mol->nextIntegrableObject(ii)) {
408 vel = sd->getVel();
409 vel[whichDirection] -= comVel[whichDirection];
410 sd->setVel(vel);
411 }
412 }
413
414 // Calculate the vz of center of mass of moving molecules
415 // (including unconstrained molecules and moving z-constrained
416 // molecules)
417
418 RealType pzMovingMols = 0.0;
419
420 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
421 mol = i->mol;
422 comVel = mol->getComVel();
423 pzMovingMols += mol->getMass() * comVel[whichDirection];
424 }
425
426 std::vector<Molecule*>::iterator j;
427 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
428 mol = *j;
429 comVel = mol->getComVel();
430 pzMovingMols += mol->getMass() * comVel[whichDirection];
431 }
432
433#ifdef IS_MPI
434 MPI_Allreduce(MPI_IN_PLACE, &pzMovingMols, 1, MPI_REALTYPE, MPI_SUM,
435 MPI_COMM_WORLD);
436#endif
437
438 RealType vzMovingMols =
439 pzMovingMols / (totMassMovingZMols_ + totMassUnconsMols_);
440
441 // Modify the velocities of moving z-constrained molecules
442
443 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
444 mol = i->mol;
445
446 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
447 sd = mol->nextIntegrableObject(ii)) {
448 vel = sd->getVel();
449 vel[whichDirection] -= vzMovingMols;
450 sd->setVel(vel);
451 }
452 }
453
454 // Modify the velocites of unconstrained molecules
455 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
456 mol = *j;
457
458 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
459 sd = mol->nextIntegrableObject(ii)) {
460 vel = sd->getVel();
461 vel[whichDirection] -= vzMovingMols;
462 sd->setVel(vel);
463 }
464 }
465 }
466
467 bool ZConstraintForceModifier::haveFixedZMols() {
468 int haveFixed = fixedZMols_.empty() ? 0 : 1;
469
470#ifdef IS_MPI
471 MPI_Allreduce(MPI_IN_PLACE, &haveFixed, 1, MPI_INT, MPI_SUM,
472 MPI_COMM_WORLD);
473#endif
474
475 return haveFixed > 0;
476 }
477
478 /// Constrains the molecules which have reached their specified
479 /// positions.
480 void ZConstraintForceModifier::doZconstraintForce() {
481 RealType totalFZ(0.0);
482
483 // Calculate the total z-contraint force on the fixed molecules:
484
485 std::list<ZconstraintMol>::iterator i;
486 Molecule* mol;
487 StuntDouble* sd;
488 Molecule::IntegrableObjectIterator ii;
489
490 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
491 mol = i->mol;
492 i->fz = 0.0;
493
494 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
495 sd = mol->nextIntegrableObject(ii)) {
496 i->fz += (sd->getFrc())[whichDirection];
497 }
498
499 totalFZ += i->fz;
500 }
501
502#ifdef IS_MPI
503 // collect the total z-constraint force
504 MPI_Allreduce(MPI_IN_PLACE, &totalFZ, 1, MPI_REALTYPE, MPI_SUM,
505 MPI_COMM_WORLD);
506#endif
507
508 // apply negative force to fixed z-constrained molecules:
509 for (i = fixedZMols_.begin(); i != fixedZMols_.end(); ++i) {
510 mol = i->mol;
511
512 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
513 sd = mol->nextIntegrableObject(ii)) {
514 Vector3d force(0.0);
515 force[whichDirection] = -getZFOfFixedZMols(mol, sd, i->fz);
516
517 sd->addFrc(force);
518 }
519 }
520
521 // modify the forces of the currently moving z-constrained
522 // molecules so that system stays fixed:
523 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
524 mol = i->mol;
525
526 Vector3d force(0.0);
527 force[whichDirection] = -getZFOfMovingMols(mol, totalFZ);
528
529 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
530 sd = mol->nextIntegrableObject(ii)) {
531 sd->addFrc(force);
532 }
533 }
534
535 // modify the forces of unconstrained molecules so that the system
536 // stays fixed:
537 std::vector<Molecule*>::iterator j;
538 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
539 mol = *j;
540
541 Vector3d force(0.0);
542 force[whichDirection] = -getZFOfMovingMols(mol, totalFZ);
543
544 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
545 sd = mol->nextIntegrableObject(ii)) {
546 sd->addFrc(force);
547 }
548 }
549 }
550
551 /// Calculates how to distribute constraint force onto StuntDoubles
552 /// in a constrained molecule.
553 RealType ZConstraintForceModifier::getZFOfFixedZMols(Molecule* mol,
554 StuntDouble* sd,
555 RealType totalForce) {
556 return totalForce * sd->getMass() / mol->getMass();
557 }
558
559 /// Calculates how to distribute constraint forces onto
560 /// unconstrained or moving molecules.
561 RealType ZConstraintForceModifier::getZFOfMovingMols(Molecule* mol,
562 RealType totalForce) {
563 return totalForce * mol->getMass() /
564 (totMassUnconsMols_ + totMassMovingZMols_);
565 }
566
567 bool ZConstraintForceModifier::haveMovingZMols() {
568 int haveMoving = movingZMols_.empty() ? 0 : 1;
569
570#ifdef IS_MPI
571 MPI_Allreduce(MPI_IN_PLACE, &haveMoving, 1, MPI_INT, MPI_SUM,
572 MPI_COMM_WORLD);
573#endif
574
575 return haveMoving > 0;
576 }
577
578 /// Applies a restraint force to the molecules which are not at
579 /// their specified positions.
580 void ZConstraintForceModifier::doHarmonic() {
581 RealType totalFZ(0.0);
582 Vector3d force(0.0);
583 Vector3d com;
584 RealType restPot(0.0);
585 std::list<ZconstraintMol>::iterator i;
586 StuntDouble* sd;
587 Molecule::IntegrableObjectIterator ii;
588 Molecule* mol;
589
590 RealType pe = currSnapshot_->getPotentialEnergy();
591 currSnapshot_->setRawPotential(pe);
592
593 for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
594 mol = i->mol;
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);
599
600 RealType diff = d[whichDirection];
601
602 restPot += 0.5 * i->param.kz * diff * diff;
603
604 RealType harmonicF = -(i->param.kz * diff);
605 totalFZ += harmonicF;
606
607 // adjust force
608 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
609 sd = mol->nextIntegrableObject(ii)) {
610 force[whichDirection] = getHFOfFixedZMols(mol, sd, harmonicF);
611 sd->addFrc(force);
612 }
613 }
614
615#ifdef IS_MPI
616 MPI_Allreduce(MPI_IN_PLACE, &restPot, 1, MPI_REALTYPE, MPI_SUM,
617 MPI_COMM_WORLD);
618 MPI_Allreduce(MPI_IN_PLACE, &totalFZ, 1, MPI_REALTYPE, MPI_SUM,
619 MPI_COMM_WORLD);
620#endif
621
622 RealType rp = currSnapshot_->getRestraintPotential();
623 currSnapshot_->setRestraintPotential(rp + restPot);
624
625 currSnapshot_->setPotentialEnergy(pe + restPot);
626
627 // modify the forces of unconstrained molecules
628 std::vector<Molecule*>::iterator j;
629 for (j = unzconsMols_.begin(); j != unzconsMols_.end(); ++j) {
630 mol = *j;
631 force[whichDirection] = getHFOfUnconsMols(mol, totalFZ);
632
633 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
634 sd = mol->nextIntegrableObject(ii)) {
635 sd->addFrc(force);
636 }
637 }
638 }
639
640 RealType ZConstraintForceModifier::getHFOfFixedZMols(Molecule* mol,
641 StuntDouble* sd,
642 RealType totalForce) {
643 return totalForce * sd->getMass() / mol->getMass();
644 }
645
646 RealType ZConstraintForceModifier::getHFOfUnconsMols(Molecule* mol,
647 RealType totalForce) {
648 return totalForce * mol->getMass() / totMassUnconsMols_;
649 }
650
651 // void ZConstraintForceModifier::updateCantPos() {
652 // std::list<ZconstraintMol>::iterator i;
653 // for (i = movingZMols_.begin(); i != movingZMols_.end(); ++i) {
654 // i->cantPos += i->param.cantVel * dt_;
655 // }
656 // }
657} // namespace OpenMD
Abstract class for external ForceModifier classes.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:96
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)