60#include "constraints/ZconstraintForceModifier.hpp"
61#include "integrators/LDForceModifier.hpp"
62#include "integrators/LangevinHullForceModifier.hpp"
63#include "nonbonded/NonBondedInteraction.hpp"
64#include "parallel/ForceMatrixDecomposition.hpp"
73#include "restraints/RestraintForceModifier.hpp"
74#include "restraints/ThermoIntegrationForceModifier.hpp"
76#include "utils/simError.h"
81 ForceManager::ForceManager(
SimInfo* info) :
82 initialized_(false), info_(info), switcher_(NULL), seleMan_(info),
84 forceField_ = info_->getForceField();
87 thermo =
new Thermo(info_);
90 ForceManager::~ForceManager() {
91 Utils::deletePointers(forceModifiers_);
94 delete interactionMan_;
127 Globals* simParams_ = info_->getSimParams();
131 if (simParams_->haveMDfileVersion())
132 mdFileVersion = simParams_->getMDfileVersion();
139 AtomTypeSet::iterator i;
140 AtomTypeSet atomTypes_;
143 if (simParams_->haveCutoffRadius()) {
144 rCut_ = simParams_->getCutoffRadius();
146 if (info_->usesElectrostaticAtoms()) {
147 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
148 "ForceManager::setupCutoffs: No value was set for the "
150 "\tOpenMD will use a default value of 12.0 angstroms"
151 "\tfor the cutoffRadius.\n");
152 painCave.isFatal = 0;
153 painCave.severity = OPENMD_INFO;
158 for (i = atomTypes_.begin(); i != atomTypes_.end(); ++i) {
159 thisCut = interactionMan_->getSuggestedCutoffRadius((*i));
162 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
163 "ForceManager::setupCutoffs: No value was set for the "
165 "\tOpenMD will use %lf angstroms.\n",
167 painCave.isFatal = 0;
168 painCave.severity = OPENMD_INFO;
173 fDecomp_->setCutoffRadius(
rCut_);
174 interactionMan_->setCutoffRadius(
rCut_);
177 map<string, CutoffMethod> stringToCutoffMethod;
178 stringToCutoffMethod[
"HARD"] = HARD;
179 stringToCutoffMethod[
"SWITCHED"] = SWITCHED;
180 stringToCutoffMethod[
"SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;
181 stringToCutoffMethod[
"SHIFTED_FORCE"] = SHIFTED_FORCE;
182 stringToCutoffMethod[
"TAYLOR_SHIFTED"] = TAYLOR_SHIFTED;
183 stringToCutoffMethod[
"EWALD_FULL"] = EWALD_FULL;
185 if (simParams_->haveCutoffMethod()) {
186 string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
187 map<string, CutoffMethod>::iterator i;
188 i = stringToCutoffMethod.find(cutMeth);
189 if (i == stringToCutoffMethod.end()) {
190 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
191 "ForceManager::setupCutoffs: Could not find chosen "
193 "\tShould be one of: "
194 "HARD, SWITCHED, SHIFTED_POTENTIAL, TAYLOR_SHIFTED,\n"
195 "\tSHIFTED_FORCE, or EWALD_FULL\n",
197 painCave.isFatal = 1;
198 painCave.severity = OPENMD_ERROR;
204 if (mdFileVersion > 1) {
205 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
206 "ForceManager::setupCutoffs: No value was set "
207 "for the cutoffMethod.\n"
208 "\tOpenMD will use SHIFTED_FORCE.\n");
209 painCave.isFatal = 0;
210 painCave.severity = OPENMD_INFO;
218 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
219 "ForceManager::setupCutoffs : DEPRECATED FILE FORMAT!\n"
220 "\tOpenMD found a file which does not set a cutoffMethod.\n"
221 "\tOpenMD will attempt to deduce a cutoffMethod using the\n"
222 "\tbehavior of the older (version 1) code. To remove this\n"
223 "\twarning, add an explicit cutoffMethod and change the top\n"
224 "\tof the file so that it begins with <OpenMD version=2>\n");
225 painCave.isFatal = 0;
226 painCave.severity = OPENMD_WARNING;
232 if (simParams_->haveElectrostaticSummationMethod()) {
233 string myMethod = simParams_->getElectrostaticSummationMethod();
236 if (myMethod ==
"SHIFTED_POTENTIAL") {
238 }
else if (myMethod ==
"SHIFTED_FORCE") {
240 }
else if (myMethod ==
"TAYLOR_SHIFTED") {
242 }
else if (myMethod ==
"EWALD_FULL") {
244 useSurfaceTerm_ =
true;
247 if (simParams_->haveSwitchingRadius())
248 rSwitch_ = simParams_->getSwitchingRadius();
250 if (myMethod ==
"SHIFTED_POTENTIAL" || myMethod ==
"SHIFTED_FORCE" ||
251 myMethod ==
"TAYLOR_SHIFTED" || myMethod ==
"EWALD_FULL") {
252 if (simParams_->haveSwitchingRadius()) {
253 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
254 "ForceManager::setupCutoffs : DEPRECATED ERROR MESSAGE\n"
255 "\tA value was set for the switchingRadius\n"
256 "\teven though the electrostaticSummationMethod was\n"
259 painCave.severity = OPENMD_WARNING;
260 painCave.isFatal = 1;
266 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
267 "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
268 "\tcutoffRadius and switchingRadius are set to the\n"
269 "\tsame value. OpenMD will use shifted force\n"
270 "\tpotentials instead of switching functions.\n");
271 painCave.isFatal = 0;
272 painCave.severity = OPENMD_WARNING;
276 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
277 "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
278 "\tcutoffRadius and switchingRadius are set to the\n"
279 "\tsame value. OpenMD will use shifted potentials\n"
280 "\tinstead of switching functions.\n");
281 painCave.isFatal = 0;
282 painCave.severity = OPENMD_WARNING;
295 if (simParams_->haveSwitchingRadius()) {
296 rSwitch_ = simParams_->getSwitchingRadius();
298 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
299 "ForceManager::setupCutoffs: switchingRadius (%f) is larger "
300 "than the cutoffRadius(%f)\n",
302 painCave.isFatal = 1;
303 painCave.severity = OPENMD_ERROR;
308 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
309 "ForceManager::setupCutoffs: No value was set for the "
311 "\tOpenMD will use a default value of 85 percent of the "
313 "\tswitchingRadius = %f. for this simulation\n",
315 painCave.isFatal = 0;
316 painCave.severity = OPENMD_WARNING;
320 if (mdFileVersion > 1) {
323 if (simParams_->haveSwitchingRadius()) {
324 map<string, CutoffMethod>::const_iterator it;
326 for (it = stringToCutoffMethod.begin();
327 it != stringToCutoffMethod.end(); ++it) {
333 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
334 "ForceManager::setupCutoffs: the cutoffMethod (%s)\n"
335 "\tis not set to SWITCHED, so switchingRadius value\n"
336 "\twill be ignored for this simulation\n",
338 painCave.isFatal = 0;
339 painCave.severity = OPENMD_WARNING;
348 if (simParams_->haveSwitchingFunctionType()) {
349 string funcType = simParams_->getSwitchingFunctionType();
351 if (funcType ==
"CUBIC") {
354 if (funcType ==
"FIFTH_ORDER_POLYNOMIAL") {
355 sft_ = fifth_order_poly;
359 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
360 "ForceManager::setupSwitching : Unknown switchingFunctionType. "
362 "file specified %s .)\n"
363 "\tswitchingFunctionType must be one of: "
364 "\"cubic\" or \"fifth_order_polynomial\".",
366 painCave.isFatal = 1;
367 painCave.severity = OPENMD_ERROR;
372 switcher_->setSwitchType(
sft_);
377 if (!info_->isTopologyDone()) {
379 interactionMan_->setSimInfo(info_);
380 interactionMan_->initialize();
382 useSurfaceTerm_ =
false;
383 useSlabGeometry_ =
false;
392 doParticlePot_ = info_->getSimParams()->getOutputParticlePotential();
393 doHeatFlux_ = info_->getSimParams()->getPrintHeatFlux();
394 if (doHeatFlux_) doParticlePot_ =
true;
396 doElectricField_ = info_->getSimParams()->getOutputElectricField();
398 info_->getSimParams()->getRNEMDParameters()->requiresElectricField();
399 doSitePotential_ = info_->getSimParams()->getOutputSitePotential();
400 if (info_->getSimParams()->haveUseSurfaceTerm() &&
401 info_->getSimParams()->getUseSurfaceTerm()) {
402 if (info_->usesElectrostaticAtoms()) {
403 useSurfaceTerm_ = info_->getSimParams()->getUseSurfaceTerm();
404 if (info_->getSimParams()->haveUseSlabGeometry()) {
405 useSlabGeometry_ = info_->getSimParams()->getUseSlabGeometry();
408 toUpperCopy(info_->getSimParams()->getPrivilegedAxis());
409 if (axis.compare(
"X") == 0)
411 else if (axis.compare(
"Y") == 0)
417 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
418 "ForceManager::initialize : useSurfaceTerm was set true\n"
419 "\tbut no electrostatic atoms are present. OpenMD will\n"
420 "\tignore this setting.\n");
421 painCave.isFatal = 0;
422 painCave.severity = OPENMD_WARNING;
439 vdwScale_.reserve(4);
440 fill(vdwScale_.begin(), vdwScale_.end(), 0.0);
442 electrostaticScale_.reserve(4);
443 fill(electrostaticScale_.begin(), electrostaticScale_.end(), 0.0);
446 vdwScale_[1] = fopts.getvdw12scale();
447 vdwScale_[2] = fopts.getvdw13scale();
448 vdwScale_[3] = fopts.getvdw14scale();
450 electrostaticScale_[0] = 1.0;
451 electrostaticScale_[1] = fopts.getelectrostatic12scale();
452 electrostaticScale_[2] = fopts.getelectrostatic13scale();
453 electrostaticScale_[3] = fopts.getelectrostatic14scale();
456 if (info_->getSimParams()->haveUniformField()) {
458 forceModifiers_.push_back(eField);
461 if (info_->getSimParams()->haveMagneticField()) {
463 forceModifiers_.push_back(mField);
466 if (info_->getSimParams()->haveUniformGradientStrength() ||
467 info_->getSimParams()->haveUniformGradientDirection1() ||
468 info_->getSimParams()->haveUniformGradientDirection2()) {
470 forceModifiers_.push_back(eGrad);
474 if (info_->getSimParams()->getUseThermodynamicIntegration()) {
477 forceModifiers_.push_back(thermoInt);
478 }
else if (info_->getSimParams()->getUseRestraints()) {
480 forceModifiers_.push_back(restraint);
483 std::string ensembleParam =
484 toUpperCopy(info_->getSimParams()->getEnsemble());
486 if (ensembleParam ==
"LHULL" || ensembleParam ==
"LANGEVINHULL" ||
487 ensembleParam ==
"SMIPD") {
490 forceModifiers_.push_back(langevinHullFM);
491 }
else if (ensembleParam ==
"LANGEVINDYNAMICS" || ensembleParam ==
"LD") {
493 forceModifiers_.push_back(langevinDynamicsFM);
496 if (info_->getSimParams()->getNZconsStamps() > 0) {
499 forceModifiers_.push_back(zCons);
502 usePeriodicBoundaryConditions_ =
503 info_->getSimParams()->getUsePeriodicBoundaryConditions();
505 fDecomp_->distributeInitialData();
507 doPotentialSelection_ =
false;
508 if (info_->getSimParams()->havePotentialSelection()) {
509 doPotentialSelection_ =
true;
510 selectionScript_ = info_->getSimParams()->getPotentialSelection();
511 evaluator_.loadScriptString(selectionScript_);
513 seleMan_.setSelectionSet(evaluator_.evaluate());
520 void ForceManager::calcForces() {
524 shortRangeInteractions();
525 longRangeInteractions();
529 void ForceManager::preCalculation() {
530 SimInfo::MoleculeIterator mi;
532 Molecule::AtomIterator ai;
534 Molecule::RigidBodyIterator rbIter;
536 Molecule::CutoffGroupIterator ci;
544 fDecomp_->setSnapshot(snap);
546 snap->setBondPotential(0.0);
547 snap->setBendPotential(0.0);
548 snap->setTorsionPotential(0.0);
549 snap->setInversionPotential(0.0);
552 snap->setLongRangePotentials(zeroPot);
554 snap->setExcludedPotentials(zeroPot);
555 if (doPotentialSelection_) snap->setSelectionPotentials(zeroPot);
557 snap->setSelfPotentials(0.0);
558 snap->setRestraintPotential(0.0);
559 snap->setRawPotential(0.0);
563 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
564 atom->zeroForcesAndTorques();
568 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
569 rb = mol->nextRigidBody(rbIter)) {
570 rb->zeroForcesAndTorques();
574 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
575 cg = mol->nextCutoffGroup(ci)) {
585 fDecomp_->setHeatFlux(
Vector3d(0.0));
587 if (doPotentialSelection_) {
589 seleMan_.setSelectionSet(evaluator_.evaluate());
594 void ForceManager::shortRangeInteractions() {
601 SimInfo::MoleculeIterator mi;
602 Molecule::RigidBodyIterator rbIter;
603 Molecule::BondIterator bondIter;
605 Molecule::BendIterator bendIter;
606 Molecule::TorsionIterator torsionIter;
607 Molecule::InversionIterator inversionIter;
608 RealType bondPotential = 0.0;
609 RealType bendPotential = 0.0;
610 RealType torsionPotential = 0.0;
611 RealType inversionPotential = 0.0;
612 potVec selectionPotential(0.0);
618 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
619 rb = mol->nextRigidBody(rbIter)) {
623 for (bond = mol->beginBond(bondIter); bond != NULL;
624 bond = mol->nextBond(bondIter)) {
625 bond->calcForce(doParticlePot_);
626 bondPotential += bond->getPotential();
627 if (doPotentialSelection_) {
628 if (seleMan_.isSelected(bond->getAtomA()) ||
629 seleMan_.isSelected(bond->getAtomB())) {
635 for (bend = mol->beginBend(bendIter); bend != NULL;
636 bend = mol->nextBend(bendIter)) {
638 bend->calcForce(angle, doParticlePot_);
639 RealType currBendPot = bend->getPotential();
641 bendPotential += bend->getPotential();
642 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
643 if (i == bendDataSets.end()) {
645 dataSet.prev.angle = dataSet.curr.angle = angle;
646 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
647 dataSet.deltaV = 0.0;
649 map<Bend*, BendDataSet>::value_type(bend, dataSet));
651 i->second.prev.angle = i->second.curr.angle;
652 i->second.prev.potential = i->second.curr.potential;
653 i->second.curr.angle = angle;
654 i->second.curr.potential = currBendPot;
656 fabs(i->second.curr.potential - i->second.prev.potential);
658 if (doPotentialSelection_) {
659 if (seleMan_.isSelected(bend->getAtomA()) ||
660 seleMan_.isSelected(bend->getAtomB()) ||
661 seleMan_.isSelected(bend->getAtomC())) {
667 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
668 torsion = mol->nextTorsion(torsionIter)) {
670 torsion->calcForce(angle, doParticlePot_);
671 RealType currTorsionPot = torsion->getPotential();
672 torsionPotential += torsion->getPotential();
673 map<Torsion*, TorsionDataSet>::iterator i =
674 torsionDataSets.find(torsion);
675 if (i == torsionDataSets.end()) {
677 dataSet.prev.angle = dataSet.curr.angle = angle;
678 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
679 dataSet.deltaV = 0.0;
680 torsionDataSets.insert(
681 map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
683 i->second.prev.angle = i->second.curr.angle;
684 i->second.prev.potential = i->second.curr.potential;
685 i->second.curr.angle = angle;
686 i->second.curr.potential = currTorsionPot;
688 fabs(i->second.curr.potential - i->second.prev.potential);
690 if (doPotentialSelection_) {
691 if (seleMan_.isSelected(torsion->getAtomA()) ||
692 seleMan_.isSelected(torsion->getAtomB()) ||
693 seleMan_.isSelected(torsion->getAtomC()) ||
694 seleMan_.isSelected(torsion->getAtomD())) {
695 selectionPotential[
BONDED_FAMILY] += torsion->getPotential();
700 for (inversion = mol->beginInversion(inversionIter); inversion != NULL;
701 inversion = mol->nextInversion(inversionIter)) {
703 inversion->calcForce(angle, doParticlePot_);
704 RealType currInversionPot = inversion->getPotential();
705 inversionPotential += inversion->getPotential();
706 map<Inversion*, InversionDataSet>::iterator i =
707 inversionDataSets.find(inversion);
708 if (i == inversionDataSets.end()) {
710 dataSet.prev.angle = dataSet.curr.angle = angle;
711 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
712 dataSet.deltaV = 0.0;
713 inversionDataSets.insert(
714 map<Inversion*, InversionDataSet>::value_type(inversion,
717 i->second.prev.angle = i->second.curr.angle;
718 i->second.prev.potential = i->second.curr.potential;
719 i->second.curr.angle = angle;
720 i->second.curr.potential = currInversionPot;
722 fabs(i->second.curr.potential - i->second.prev.potential);
724 if (doPotentialSelection_) {
725 if (seleMan_.isSelected(inversion->getAtomA()) ||
726 seleMan_.isSelected(inversion->getAtomB()) ||
727 seleMan_.isSelected(inversion->getAtomC()) ||
728 seleMan_.isSelected(inversion->getAtomD())) {
729 selectionPotential[
BONDED_FAMILY] += inversion->getPotential();
740 MPI_Allreduce(MPI_IN_PLACE, &bondPotential, 1, MPI_REALTYPE, MPI_SUM,
742 MPI_Allreduce(MPI_IN_PLACE, &bendPotential, 1, MPI_REALTYPE, MPI_SUM,
744 MPI_Allreduce(MPI_IN_PLACE, &torsionPotential, 1, MPI_REALTYPE, MPI_SUM,
746 MPI_Allreduce(MPI_IN_PLACE, &inversionPotential, 1, MPI_REALTYPE, MPI_SUM,
748 MPI_Allreduce(MPI_IN_PLACE, &selectionPotential[
BONDED_FAMILY], 1,
749 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
753 fDecomp_->setSnapshot(curSnapshot);
755 curSnapshot->setBondPotential(bondPotential);
756 curSnapshot->setBendPotential(bendPotential);
757 curSnapshot->setTorsionPotential(torsionPotential);
758 curSnapshot->setInversionPotential(inversionPotential);
759 curSnapshot->setSelectionPotentials(selectionPotential);
767 void ForceManager::longRangeInteractions() {
769 fDecomp_->setSnapshot(curSnapshot);
776 SimInfo::MoleculeIterator mi;
778 Molecule::CutoffGroupIterator ci;
784 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
785 cg = mol->nextCutoffGroup(ci)) {
792 cgConfig->position = config->position;
793 cgConfig->velocity = config->velocity;
796 fDecomp_->zeroWorkArrays();
797 fDecomp_->distributeData();
799 int cg1, cg2, atom1, atom2;
801 RealType rgrpsq, rgrp;
804 bool in_switching_region;
805 RealType dswdr, swderiv;
806 vector<int> atomListColumn, atomListRow;
808 potVec longRangePotential(0.0);
809 potVec selfPotential(0.0);
810 RealType reciprocalPotential(0.0);
811 RealType surfacePotential(0.0);
812 potVec selectionPotential(0.0);
818 vector<int>::iterator ia, jb;
820 int loopStart, loopEnd;
834 if (info_->requiresPrepair()) {
835 loopStart = PREPAIR_LOOP;
837 loopStart = PAIR_LOOP;
839 for (
int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
840 if (iLoop == loopStart) {
841 bool update_nlist = fDecomp_->checkNeighborList(savedPositions_);
844 if (!usePeriodicBoundaryConditions_)
846 fDecomp_->buildNeighborList(neighborList_, point_, savedPositions_);
850 for (cg1 = 0; cg1 < int(point_.size()) - 1; cg1++) {
851 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
854 for (
int m2 = point_[cg1]; m2 < point_[cg1 + 1]; m2++) {
855 cg2 = neighborList_[m2];
857 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
861 rgrpsq = d_grp.lengthSquare();
863 if (rgrpsq < rCutSq_) {
864 if (iLoop == PAIR_LOOP) {
873 in_switching_region =
874 switcher_->getSwitch(rgrpsq, idat.
sw, dswdr, rgrp);
876 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
878 if (doHeatFlux_) gvel2 = fDecomp_->getGroupVelocityColumn(cg2);
880 for (ia = atomListRow.begin(); ia != atomListRow.end(); ++ia) {
882 if (atomListRow.size() > 1) newAtom1 =
true;
884 if (doPotentialSelection_) {
885 gid1 = fDecomp_->getGlobalIDRow(atom1);
886 idat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
889 for (jb = atomListColumn.begin(); jb != atomListColumn.end();
893 if (doPotentialSelection_) {
894 gid2 = fDecomp_->getGlobalIDCol(atom2);
895 idat.
isSelected |= seleMan_.isGlobalIDSelected(gid2);
898 if (!fDecomp_->skipAtomPair(atom1, atom2, cg1, cg2)) {
907 fDecomp_->fillInteractionData(idat, atom1, atom2, newAtom1);
911 fDecomp_->getTopologicalDistance(atom1, atom2);
915 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
918 if (doHeatFlux_) vel2 = gvel2;
920 idat.
d = fDecomp_->getInteratomicVector(atom1, atom2);
921 curSnapshot->wrapVector(idat.
d);
924 vel2 = fDecomp_->getAtomVelocityColumn(atom2);
927 idat.
rij = sqrt(idat.
r2);
929 if (iLoop == PREPAIR_LOOP) {
930 interactionMan_->doPrePair(idat);
931 fDecomp_->unpackPrePairData(idat, atom1, atom2);
933 interactionMan_->doPair(idat);
934 fDecomp_->unpackInteractionData(idat, atom1, atom2);
937 virialTensor -= outProduct(idat.
d, idat.
f1);
939 fDecomp_->addToHeatFlux(idat.
d *
dot(idat.
f1, vel2));
945 if (iLoop == PAIR_LOOP) {
946 if (in_switching_region) {
947 swderiv = vij * dswdr / rgrp;
948 fg = swderiv * d_grp;
951 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
952 if (!fDecomp_->skipAtomPair(atomListRow[0], atomListColumn[0],
954 virialTensor -= outProduct(idat.
d, fg);
956 fDecomp_->addToHeatFlux(idat.
d *
dot(fg, vel2));
960 for (ia = atomListRow.begin(); ia != atomListRow.end(); ++ia) {
962 mf = fDecomp_->getMassFactorRow(atom1);
965 fg = swderiv * d_grp * mf;
966 fDecomp_->addForceToAtomRow(atom1, fg);
967 if (atomListRow.size() > 1) {
968 if (info_->usesAtomicVirial()) {
971 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
972 virialTensor -= outProduct(dag, fg);
974 fDecomp_->addToHeatFlux(dag *
dot(fg, vel2));
978 for (jb = atomListColumn.begin(); jb != atomListColumn.end();
981 mf = fDecomp_->getMassFactorColumn(atom2);
984 fg = -swderiv * d_grp * mf;
985 fDecomp_->addForceToAtomColumn(atom2, fg);
987 if (atomListColumn.size() > 1) {
988 if (info_->usesAtomicVirial()) {
991 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
992 virialTensor -= outProduct(dag, fg);
994 fDecomp_->addToHeatFlux(dag *
dot(fg, vel2));
1009 if (iLoop == PREPAIR_LOOP) {
1010 if (info_->requiresPrepair()) {
1011 fDecomp_->collectIntermediateData();
1013 for (
unsigned int atom1 = 0; atom1 < info_->
getNAtoms(); atom1++) {
1014 if (doPotentialSelection_) {
1015 gid1 = fDecomp_->getGlobalID(atom1);
1016 sdat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1018 fDecomp_->fillPreForceData(sdat, atom1);
1019 interactionMan_->doPreForce(sdat);
1020 fDecomp_->unpackPreForceData(sdat, atom1);
1023 fDecomp_->distributeIntermediateData();
1029 fDecomp_->collectData();
1031 interactionMan_->doReciprocalSpaceSum(reciprocalPotential);
1032 curSnapshot->setReciprocalPotential(reciprocalPotential);
1035 if (useSurfaceTerm_) {
1036 interactionMan_->doSurfaceTerm(useSlabGeometry_, axis_, surfacePotential);
1037 curSnapshot->setSurfacePotential(surfacePotential);
1040 if (info_->requiresSelfCorrection()) {
1041 for (
unsigned int atom1 = 0; atom1 < info_->
getNAtoms(); atom1++) {
1042 if (doPotentialSelection_) {
1043 gid1 = fDecomp_->getGlobalID(atom1);
1044 sdat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1046 fDecomp_->fillSelfData(sdat, atom1);
1047 interactionMan_->doSelfCorrection(sdat);
1048 fDecomp_->unpackSelfData(sdat, atom1);
1053 fDecomp_->collectSelfData();
1055 longRangePotential = fDecomp_->getPairwisePotential();
1056 curSnapshot->setLongRangePotentials(longRangePotential);
1058 selfPotential = fDecomp_->getSelfPotential();
1059 curSnapshot->setSelfPotentials(selfPotential);
1061 curSnapshot->setExcludedPotentials(fDecomp_->getExcludedSelfPotential() +
1062 fDecomp_->getExcludedPotential());
1064 if (doPotentialSelection_) {
1065 selectionPotential = curSnapshot->getSelectionPotentials();
1066 selectionPotential += fDecomp_->getSelectedSelfPotential();
1067 selectionPotential += fDecomp_->getSelectedPotential();
1068 curSnapshot->setSelectionPotentials(selectionPotential);
1072 void ForceManager::postCalculation() {
1073 for (
auto& forceModifier : forceModifiers_)
1074 forceModifier->modifyForces();
1077 SimInfo::MoleculeIterator mi;
1079 Molecule::RigidBodyIterator rbIter;
1086 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
1087 rb = mol->nextRigidBody(rbIter)) {
1088 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
1089 virialTensor += rbTau;
1094 MPI_Allreduce(MPI_IN_PLACE, virialTensor.
getArrayPointer(), 9, MPI_REALTYPE,
1095 MPI_SUM, MPI_COMM_WORLD);
1097 curSnapshot->setVirialTensor(virialTensor);
1139 selectedPreCalculation(mol1, mol2);
1140 selectedShortRangeInteractions(mol1, mol2);
1141 selectedLongRangeInteractions(mol1, mol2);
1142 selectedPostCalculation(mol1, mol2);
1145 void ForceManager::selectedPreCalculation(
Molecule* mol1,
Molecule* mol2) {
1146 SimInfo::MoleculeIterator mi;
1147 Molecule::AtomIterator ai;
1149 Molecule::RigidBodyIterator rbIter;
1151 Molecule::CutoffGroupIterator ci;
1159 snap->setBondPotential(0.0);
1160 snap->setBendPotential(0.0);
1161 snap->setTorsionPotential(0.0);
1162 snap->setInversionPotential(0.0);
1165 snap->setLongRangePotentials(zeroPot);
1166 snap->setExcludedPotentials(zeroPot);
1167 if (doPotentialSelection_) snap->setSelectionPotentials(zeroPot);
1169 snap->setRestraintPotential(0.0);
1170 snap->setRawPotential(0.0);
1173 for (atom = mol1->beginAtom(ai); atom != NULL; atom = mol1->nextAtom(ai)) {
1174 atom->zeroForcesAndTorques();
1177 for (rb = mol1->beginRigidBody(rbIter); rb != NULL;
1178 rb = mol1->nextRigidBody(rbIter)) {
1179 rb->zeroForcesAndTorques();
1182 for (cg = mol1->beginCutoffGroup(ci); cg != NULL;
1183 cg = mol1->nextCutoffGroup(ci)) {
1190 for (atom = mol2->beginAtom(ai); atom != NULL; atom = mol2->nextAtom(ai)) {
1191 atom->zeroForcesAndTorques();
1194 for (rb = mol2->beginRigidBody(rbIter); rb != NULL;
1195 rb = mol2->nextRigidBody(rbIter)) {
1196 rb->zeroForcesAndTorques();
1199 for (cg = mol2->beginCutoffGroup(ci); cg != NULL;
1200 cg = mol2->nextCutoffGroup(ci)) {
1207 virialTensor *= 0.0;
1209 fDecomp_->setHeatFlux(
Vector3d(0.0));
1212 void ForceManager::selectedShortRangeInteractions(
Molecule* mol1,
1219 SimInfo::MoleculeIterator mi;
1220 Molecule::RigidBodyIterator rbIter;
1221 Molecule::BondIterator bondIter;
1222 Molecule::BendIterator bendIter;
1223 Molecule::TorsionIterator torsionIter;
1224 Molecule::InversionIterator inversionIter;
1225 RealType bondPotential = 0.0;
1226 RealType bendPotential = 0.0;
1227 RealType torsionPotential = 0.0;
1228 RealType inversionPotential = 0.0;
1229 potVec selectionPotential(0.0);
1232 for (rb = mol1->beginRigidBody(rbIter); rb != NULL;
1233 rb = mol1->nextRigidBody(rbIter)) {
1237 for (bond = mol1->beginBond(bondIter); bond != NULL;
1238 bond = mol1->nextBond(bondIter)) {
1239 bond->calcForce(doParticlePot_);
1240 bondPotential += bond->getPotential();
1241 if (doPotentialSelection_) {
1242 if (seleMan_.isSelected(bond->getAtomA()) ||
1243 seleMan_.isSelected(bond->getAtomB())) {
1249 for (bend = mol1->beginBend(bendIter); bend != NULL;
1250 bend = mol1->nextBend(bendIter)) {
1252 bend->calcForce(angle, doParticlePot_);
1253 RealType currBendPot = bend->getPotential();
1255 bendPotential += bend->getPotential();
1256 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
1257 if (i == bendDataSets.end()) {
1259 dataSet.prev.angle = dataSet.curr.angle = angle;
1260 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
1261 dataSet.deltaV = 0.0;
1262 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend, dataSet));
1264 i->second.prev.angle = i->second.curr.angle;
1265 i->second.prev.potential = i->second.curr.potential;
1266 i->second.curr.angle = angle;
1267 i->second.curr.potential = currBendPot;
1269 fabs(i->second.curr.potential - i->second.prev.potential);
1271 if (doPotentialSelection_) {
1272 if (seleMan_.isSelected(bend->getAtomA()) ||
1273 seleMan_.isSelected(bend->getAtomB()) ||
1274 seleMan_.isSelected(bend->getAtomC())) {
1280 for (torsion = mol1->beginTorsion(torsionIter); torsion != NULL;
1281 torsion = mol1->nextTorsion(torsionIter)) {
1283 torsion->calcForce(angle, doParticlePot_);
1284 RealType currTorsionPot = torsion->getPotential();
1285 torsionPotential += torsion->getPotential();
1286 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
1287 if (i == torsionDataSets.end()) {
1289 dataSet.prev.angle = dataSet.curr.angle = angle;
1290 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
1291 dataSet.deltaV = 0.0;
1292 torsionDataSets.insert(
1293 map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
1295 i->second.prev.angle = i->second.curr.angle;
1296 i->second.prev.potential = i->second.curr.potential;
1297 i->second.curr.angle = angle;
1298 i->second.curr.potential = currTorsionPot;
1300 fabs(i->second.curr.potential - i->second.prev.potential);
1302 if (doPotentialSelection_) {
1303 if (seleMan_.isSelected(torsion->getAtomA()) ||
1304 seleMan_.isSelected(torsion->getAtomB()) ||
1305 seleMan_.isSelected(torsion->getAtomC()) ||
1306 seleMan_.isSelected(torsion->getAtomD())) {
1307 selectionPotential[
BONDED_FAMILY] += torsion->getPotential();
1312 for (inversion = mol1->beginInversion(inversionIter); inversion != NULL;
1313 inversion = mol1->nextInversion(inversionIter)) {
1315 inversion->calcForce(angle, doParticlePot_);
1316 RealType currInversionPot = inversion->getPotential();
1317 inversionPotential += inversion->getPotential();
1318 map<Inversion*, InversionDataSet>::iterator i =
1319 inversionDataSets.find(inversion);
1320 if (i == inversionDataSets.end()) {
1322 dataSet.prev.angle = dataSet.curr.angle = angle;
1323 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
1324 dataSet.deltaV = 0.0;
1325 inversionDataSets.insert(
1326 map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
1328 i->second.prev.angle = i->second.curr.angle;
1329 i->second.prev.potential = i->second.curr.potential;
1330 i->second.curr.angle = angle;
1331 i->second.curr.potential = currInversionPot;
1333 fabs(i->second.curr.potential - i->second.prev.potential);
1335 if (doPotentialSelection_) {
1336 if (seleMan_.isSelected(inversion->getAtomA()) ||
1337 seleMan_.isSelected(inversion->getAtomB()) ||
1338 seleMan_.isSelected(inversion->getAtomC()) ||
1339 seleMan_.isSelected(inversion->getAtomD())) {
1340 selectionPotential[
BONDED_FAMILY] += inversion->getPotential();
1346 for (rb = mol2->beginRigidBody(rbIter); rb != NULL;
1347 rb = mol2->nextRigidBody(rbIter)) {
1351 for (bond = mol2->beginBond(bondIter); bond != NULL;
1352 bond = mol2->nextBond(bondIter)) {
1353 bond->calcForce(doParticlePot_);
1354 bondPotential += bond->getPotential();
1355 if (doPotentialSelection_) {
1356 if (seleMan_.isSelected(bond->getAtomA()) ||
1357 seleMan_.isSelected(bond->getAtomB())) {
1363 for (bend = mol2->beginBend(bendIter); bend != NULL;
1364 bend = mol2->nextBend(bendIter)) {
1366 bend->calcForce(angle, doParticlePot_);
1367 RealType currBendPot = bend->getPotential();
1369 bendPotential += bend->getPotential();
1370 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
1371 if (i == bendDataSets.end()) {
1373 dataSet.prev.angle = dataSet.curr.angle = angle;
1374 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
1375 dataSet.deltaV = 0.0;
1376 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend, dataSet));
1378 i->second.prev.angle = i->second.curr.angle;
1379 i->second.prev.potential = i->second.curr.potential;
1380 i->second.curr.angle = angle;
1381 i->second.curr.potential = currBendPot;
1383 fabs(i->second.curr.potential - i->second.prev.potential);
1385 if (doPotentialSelection_) {
1386 if (seleMan_.isSelected(bend->getAtomA()) ||
1387 seleMan_.isSelected(bend->getAtomB()) ||
1388 seleMan_.isSelected(bend->getAtomC())) {
1394 for (torsion = mol2->beginTorsion(torsionIter); torsion != NULL;
1395 torsion = mol2->nextTorsion(torsionIter)) {
1397 torsion->calcForce(angle, doParticlePot_);
1398 RealType currTorsionPot = torsion->getPotential();
1399 torsionPotential += torsion->getPotential();
1400 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
1401 if (i == torsionDataSets.end()) {
1403 dataSet.prev.angle = dataSet.curr.angle = angle;
1404 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
1405 dataSet.deltaV = 0.0;
1406 torsionDataSets.insert(
1407 map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
1409 i->second.prev.angle = i->second.curr.angle;
1410 i->second.prev.potential = i->second.curr.potential;
1411 i->second.curr.angle = angle;
1412 i->second.curr.potential = currTorsionPot;
1414 fabs(i->second.curr.potential - i->second.prev.potential);
1416 if (doPotentialSelection_) {
1417 if (seleMan_.isSelected(torsion->getAtomA()) ||
1418 seleMan_.isSelected(torsion->getAtomB()) ||
1419 seleMan_.isSelected(torsion->getAtomC()) ||
1420 seleMan_.isSelected(torsion->getAtomD())) {
1421 selectionPotential[
BONDED_FAMILY] += torsion->getPotential();
1426 for (inversion = mol2->beginInversion(inversionIter); inversion != NULL;
1427 inversion = mol2->nextInversion(inversionIter)) {
1429 inversion->calcForce(angle, doParticlePot_);
1430 RealType currInversionPot = inversion->getPotential();
1431 inversionPotential += inversion->getPotential();
1432 map<Inversion*, InversionDataSet>::iterator i =
1433 inversionDataSets.find(inversion);
1434 if (i == inversionDataSets.end()) {
1436 dataSet.prev.angle = dataSet.curr.angle = angle;
1437 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
1438 dataSet.deltaV = 0.0;
1439 inversionDataSets.insert(
1440 map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
1442 i->second.prev.angle = i->second.curr.angle;
1443 i->second.prev.potential = i->second.curr.potential;
1444 i->second.curr.angle = angle;
1445 i->second.curr.potential = currInversionPot;
1447 fabs(i->second.curr.potential - i->second.prev.potential);
1449 if (doPotentialSelection_) {
1450 if (seleMan_.isSelected(inversion->getAtomA()) ||
1451 seleMan_.isSelected(inversion->getAtomB()) ||
1452 seleMan_.isSelected(inversion->getAtomC()) ||
1453 seleMan_.isSelected(inversion->getAtomD())) {
1454 selectionPotential[
BONDED_FAMILY] += inversion->getPotential();
1464 MPI_Allreduce(MPI_IN_PLACE, &bondPotential, 1, MPI_REALTYPE, MPI_SUM,
1466 MPI_Allreduce(MPI_IN_PLACE, &bendPotential, 1, MPI_REALTYPE, MPI_SUM,
1468 MPI_Allreduce(MPI_IN_PLACE, &torsionPotential, 1, MPI_REALTYPE, MPI_SUM,
1470 MPI_Allreduce(MPI_IN_PLACE, &inversionPotential, 1, MPI_REALTYPE, MPI_SUM,
1472 MPI_Allreduce(MPI_IN_PLACE, &selectionPotential[
BONDED_FAMILY], 1,
1473 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
1478 curSnapshot->setBondPotential(bondPotential);
1479 curSnapshot->setBendPotential(bendPotential);
1480 curSnapshot->setTorsionPotential(torsionPotential);
1481 curSnapshot->setInversionPotential(inversionPotential);
1482 curSnapshot->setSelectionPotentials(selectionPotential);
1490 void ForceManager::selectedLongRangeInteractions(
Molecule* mol1,
1498 SimInfo::MoleculeIterator mi;
1499 Molecule::CutoffGroupIterator ci;
1503 for (cg = mol1->beginCutoffGroup(ci); cg != NULL;
1504 cg = mol1->nextCutoffGroup(ci)) {
1507 for (cg = mol2->beginCutoffGroup(ci); cg != NULL;
1508 cg = mol2->nextCutoffGroup(ci)) {
1514 cgConfig->position = config->position;
1515 cgConfig->velocity = config->velocity;
1518 fDecomp_->zeroWorkArrays();
1519 fDecomp_->distributeData();
1521 int cg1, cg2, atom1, atom2;
1523 RealType rgrpsq, rgrp;
1526 bool in_switching_region;
1527 RealType dswdr, swderiv;
1528 vector<int> atomListColumn, atomListRow;
1530 potVec longRangePotential(0.0);
1531 potVec selfPotential(0.0);
1532 potVec selectionPotential(0.0);
1533 RealType reciprocalPotential(0.0);
1534 RealType surfacePotential(0.0);
1540 vector<int>::iterator ia, jb;
1542 int loopStart, loopEnd;
1555 loopEnd = PAIR_LOOP;
1556 if (info_->requiresPrepair()) {
1557 loopStart = PREPAIR_LOOP;
1559 loopStart = PAIR_LOOP;
1561 for (
int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
1562 if (iLoop == loopStart) {
1563 bool update_nlist = fDecomp_->checkNeighborList(savedPositions_);
1566 if (!usePeriodicBoundaryConditions_)
1568 fDecomp_->buildNeighborList(neighborList_, point_, savedPositions_);
1572 for (cg1 = 0; cg1 < int(point_.size()) - 1; cg1++) {
1573 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
1576 for (
int m2 = point_[cg1]; m2 < point_[cg1 + 1]; m2++) {
1577 cg2 = neighborList_[m2];
1579 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
1583 rgrpsq = d_grp.lengthSquare();
1585 if (rgrpsq < rCutSq_) {
1586 if (iLoop == PAIR_LOOP) {
1595 in_switching_region =
1596 switcher_->getSwitch(rgrpsq, idat.
sw, dswdr, rgrp);
1598 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
1600 if (doHeatFlux_) gvel2 = fDecomp_->getGroupVelocityColumn(cg2);
1602 for (ia = atomListRow.begin(); ia != atomListRow.end(); ++ia) {
1603 if (atomListRow.size() > 1) newAtom1 =
true;
1606 if (doPotentialSelection_) {
1607 gid1 = fDecomp_->getGlobalIDRow(atom1);
1608 idat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1611 for (jb = atomListColumn.begin(); jb != atomListColumn.end();
1615 if (doPotentialSelection_) {
1616 gid2 = fDecomp_->getGlobalIDCol(atom2);
1617 idat.
isSelected |= seleMan_.isGlobalIDSelected(gid2);
1620 if (!fDecomp_->skipAtomPair(atom1, atom2, cg1, cg2)) {
1629 fDecomp_->fillInteractionData(idat, atom1, atom2, newAtom1);
1633 fDecomp_->getTopologicalDistance(atom1, atom2);
1637 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
1640 if (doHeatFlux_) vel2 = gvel2;
1642 idat.
d = fDecomp_->getInteratomicVector(atom1, atom2);
1643 curSnapshot->wrapVector(idat.
d);
1646 vel2 = fDecomp_->getAtomVelocityColumn(atom2);
1649 idat.
rij = sqrt(idat.
r2);
1651 if (iLoop == PREPAIR_LOOP) {
1652 interactionMan_->doPrePair(idat);
1653 fDecomp_->unpackPrePairData(idat, atom1, atom2);
1655 interactionMan_->doPair(idat);
1656 fDecomp_->unpackInteractionData(idat, atom1, atom2);
1659 virialTensor -= outProduct(idat.
d, idat.
f1);
1661 fDecomp_->addToHeatFlux(idat.
d *
dot(idat.
f1, vel2));
1667 if (iLoop == PAIR_LOOP) {
1668 if (in_switching_region) {
1669 swderiv = vij * dswdr / rgrp;
1670 fg = swderiv * d_grp;
1673 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
1674 if (!fDecomp_->skipAtomPair(atomListRow[0], atomListColumn[0],
1676 virialTensor -= outProduct(idat.
d, fg);
1678 fDecomp_->addToHeatFlux(idat.
d *
dot(fg, vel2));
1682 for (ia = atomListRow.begin(); ia != atomListRow.end(); ++ia) {
1684 mf = fDecomp_->getMassFactorRow(atom1);
1687 fg = swderiv * d_grp * mf;
1688 fDecomp_->addForceToAtomRow(atom1, fg);
1689 if (atomListRow.size() > 1) {
1690 if (info_->usesAtomicVirial()) {
1693 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
1694 virialTensor -= outProduct(dag, fg);
1696 fDecomp_->addToHeatFlux(dag *
dot(fg, vel2));
1700 for (jb = atomListColumn.begin(); jb != atomListColumn.end();
1703 mf = fDecomp_->getMassFactorColumn(atom2);
1706 fg = -swderiv * d_grp * mf;
1707 fDecomp_->addForceToAtomColumn(atom2, fg);
1709 if (atomListColumn.size() > 1) {
1710 if (info_->usesAtomicVirial()) {
1713 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
1714 virialTensor -= outProduct(dag, fg);
1716 fDecomp_->addToHeatFlux(dag *
dot(fg, vel2));
1731 if (iLoop == PREPAIR_LOOP) {
1732 if (info_->requiresPrepair()) {
1733 fDecomp_->collectIntermediateData();
1735 for (
unsigned int atom1 = 0; atom1 < info_->
getNAtoms(); atom1++) {
1736 if (doPotentialSelection_) {
1737 gid1 = fDecomp_->getGlobalID(atom1);
1738 sdat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1741 fDecomp_->fillPreForceData(sdat, atom1);
1742 interactionMan_->doPreForce(sdat);
1743 fDecomp_->unpackPreForceData(sdat, atom1);
1746 fDecomp_->distributeIntermediateData();
1752 fDecomp_->collectData();
1754 interactionMan_->doReciprocalSpaceSum(reciprocalPotential);
1755 curSnapshot->setReciprocalPotential(reciprocalPotential);
1758 if (useSurfaceTerm_) {
1759 interactionMan_->doSurfaceTerm(useSlabGeometry_, axis_, surfacePotential);
1760 curSnapshot->setSurfacePotential(surfacePotential);
1763 if (info_->requiresSelfCorrection()) {
1764 for (
unsigned int atom1 = 0; atom1 < info_->
getNAtoms(); atom1++) {
1765 if (doPotentialSelection_) {
1766 gid1 = fDecomp_->getGlobalID(atom1);
1767 sdat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1770 fDecomp_->fillSelfData(sdat, atom1);
1771 interactionMan_->doSelfCorrection(sdat);
1772 fDecomp_->unpackSelfData(sdat, atom1);
1777 fDecomp_->collectSelfData();
1779 longRangePotential = fDecomp_->getPairwisePotential();
1780 curSnapshot->setLongRangePotentials(longRangePotential);
1782 selfPotential = fDecomp_->getSelfPotential();
1783 curSnapshot->setSelfPotentials(selfPotential);
1785 curSnapshot->setExcludedPotentials(fDecomp_->getExcludedSelfPotential() +
1786 fDecomp_->getExcludedPotential());
1788 if (doPotentialSelection_) {
1789 selectionPotential = curSnapshot->getSelectionPotentials();
1790 selectionPotential += fDecomp_->getSelectedSelfPotential();
1791 selectionPotential += fDecomp_->getSelectedPotential();
1792 curSnapshot->setSelectionPotentials(selectionPotential);
1796 void ForceManager::selectedPostCalculation(
Molecule* mol1,
Molecule* mol2) {
1797 for (
auto& forceModifier : forceModifiers_)
1798 forceModifier->modifyForces();
1801 SimInfo::MoleculeIterator mi;
1802 Molecule::RigidBodyIterator rbIter;
1807 for (rb = mol1->beginRigidBody(rbIter); rb != NULL;
1808 rb = mol1->nextRigidBody(rbIter)) {
1809 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
1810 virialTensor += rbTau;
1813 for (rb = mol2->beginRigidBody(rbIter); rb != NULL;
1814 rb = mol2->nextRigidBody(rbIter)) {
1815 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
1816 virialTensor += rbTau;
1820 MPI_Allreduce(MPI_IN_PLACE, virialTensor.
getArrayPointer(), 9, MPI_REALTYPE,
1821 MPI_SUM, MPI_COMM_WORLD);
1823 curSnapshot->setVirialTensor(virialTensor);
Uniform Magnetic Field perturbation.
virtual void setupCutoffs()
setupCutoffs
SwitchingFunctionType sft_
Type of switching function in use.
RealType rCut_
cutoff radius for non-bonded interactions
CutoffMethod cutoffMethod_
Cutoff Method for most non-bonded interactions.
RealType rSwitch_
inner radius of switching function
InteractionManager is responsible for keeping track of the non-bonded interactions (C++)
Force modifier for Langevin Dynamics applying friction and random forces as well as torques.
Force modifier for NPT Langevin Hull Dynamics applying friction and random forces as well as torques.
Applies a uniform (vector) magnetic field to the system.
Real * getArrayPointer()
Returns the pointer of internal array.
bool isDynamic()
Tests if the result from evaluation of script is dynamic.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
void setNZconstraint(int nZconstraint)
Sets the number of z-constraint molecules in the system.
Molecule * beginMolecule(MoleculeIterator &i)
Returns the first molecule in this SimInfo and intialize the iterator.
unsigned int getNAtoms()
Returns the number of local atoms.
void prepareTopology()
Do final bookkeeping before Force managers need their data.
int getNGlobalAtoms()
Returns the total number of atoms in the system.
unsigned int getNCutoffGroups()
Returns the number of local cutoff groups.
Molecule * nextMolecule(MoleculeIterator &i)
Returns the next avaliable Molecule based on the iterator.
SnapshotManager * getSnapshotManager()
Returns the snapshot manager.
int getNGlobalCutoffGroups()
Returns the total number of cutoff groups in the system.
AtomTypeSet getSimulatedAtomTypes()
Returns the set of atom types present in this simulation.
The Snapshot class is a repository storing dynamic data during a Simulation.
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
Mat3x3d getBoundingBox()
Returns the Axis-aligned bounding box for the current system.
void zero()
Zeros out the values in this vector in place.
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.
@ BONDED_FAMILY
directly bonded 1-2, 1-3, or 1-4 interactions
bool shiftedPot
shift the potential up inside the cutoff?
Vector3d d
interatomic vector (already wrapped into box)
RealType sPot2
site potential on second atom
RealType dVdFQ1
fluctuating charge force on atom1
RealType dVdFQ2
fluctuating charge force on atom2
RealType electroMult
multiplier for electrostatic interactions
potVec pot
total potential
potVec selePot
potential energies of the selected sites
RealType sw
switching function value at rij
Vector3d eField1
electric field on first atom
bool isSelected
one of the particles has been selected for selection potential
bool doElectricField
should we bother with the electric field?
Vector3d eField2
electric field on second atom
RealType vpair
pair potential
RealType sPot1
site potential on first atom
bool doSitePotential
should we bother with electrostatic site potential
bool shiftedForce
shifted forces smoothly inside the cutoff?
int topoDist
topological distance between atoms
RealType rcut
cutoff radius for this interaction
potVec excludedPot
potential energy excluded from the overall calculation
RealType vdwMult
multiplier for van der Waals interactions
bool doParticlePot
should we bother with the particle pot?
Vector3d f1
force between the two atoms
RealType rij
interatomic separation
bool isSelected
this site has been selected for selection potential
bool doParticlePot
should we bother with the particle pot?