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"
66#include "perturbations/LightParameters.hpp"
75#include "restraints/RestraintForceModifier.hpp"
76#include "restraints/ThermoIntegrationForceModifier.hpp"
78#include "utils/simError.h"
83 ForceManager::ForceManager(
SimInfo* info) :
84 initialized_(false), info_(info), switcher_(NULL), seleMan_(info),
86 forceField_ = info_->getForceField();
89 thermo =
new Thermo(info_);
92 ForceManager::~ForceManager() {
93 Utils::deletePointers(forceModifiers_);
96 delete interactionMan_;
129 Globals* simParams_ = info_->getSimParams();
133 if (simParams_->haveMDfileVersion())
134 mdFileVersion = simParams_->getMDfileVersion();
141 AtomTypeSet::iterator i;
142 AtomTypeSet atomTypes_;
145 if (simParams_->haveCutoffRadius()) {
146 rCut_ = simParams_->getCutoffRadius();
148 if (info_->usesElectrostaticAtoms()) {
149 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
150 "ForceManager::setupCutoffs: No value was set for the "
152 "\tOpenMD will use a default value of 12.0 angstroms"
153 "\tfor the cutoffRadius.\n");
154 painCave.isFatal = 0;
155 painCave.severity = OPENMD_INFO;
160 for (i = atomTypes_.begin(); i != atomTypes_.end(); ++i) {
161 thisCut = interactionMan_->getSuggestedCutoffRadius((*i));
164 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
165 "ForceManager::setupCutoffs: No value was set for the "
167 "\tOpenMD will use %lf angstroms.\n",
169 painCave.isFatal = 0;
170 painCave.severity = OPENMD_INFO;
175 fDecomp_->setCutoffRadius(
rCut_);
176 interactionMan_->setCutoffRadius(
rCut_);
179 map<string, CutoffMethod> stringToCutoffMethod;
180 stringToCutoffMethod[
"HARD"] = HARD;
181 stringToCutoffMethod[
"SWITCHED"] = SWITCHED;
182 stringToCutoffMethod[
"SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;
183 stringToCutoffMethod[
"SHIFTED_FORCE"] = SHIFTED_FORCE;
184 stringToCutoffMethod[
"TAYLOR_SHIFTED"] = TAYLOR_SHIFTED;
185 stringToCutoffMethod[
"EWALD_FULL"] = EWALD_FULL;
187 if (simParams_->haveCutoffMethod()) {
188 string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
189 map<string, CutoffMethod>::iterator i;
190 i = stringToCutoffMethod.find(cutMeth);
191 if (i == stringToCutoffMethod.end()) {
192 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
193 "ForceManager::setupCutoffs: Could not find chosen "
195 "\tShould be one of: "
196 "HARD, SWITCHED, SHIFTED_POTENTIAL, TAYLOR_SHIFTED,\n"
197 "\tSHIFTED_FORCE, or EWALD_FULL\n",
199 painCave.isFatal = 1;
200 painCave.severity = OPENMD_ERROR;
206 if (mdFileVersion > 1) {
207 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
208 "ForceManager::setupCutoffs: No value was set "
209 "for the cutoffMethod.\n"
210 "\tOpenMD will use SHIFTED_FORCE.\n");
211 painCave.isFatal = 0;
212 painCave.severity = OPENMD_INFO;
220 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
221 "ForceManager::setupCutoffs : DEPRECATED FILE FORMAT!\n"
222 "\tOpenMD found a file which does not set a cutoffMethod.\n"
223 "\tOpenMD will attempt to deduce a cutoffMethod using the\n"
224 "\tbehavior of the older (version 1) code. To remove this\n"
225 "\twarning, add an explicit cutoffMethod and change the top\n"
226 "\tof the file so that it begins with <OpenMD version=2>\n");
227 painCave.isFatal = 0;
228 painCave.severity = OPENMD_WARNING;
234 if (simParams_->haveElectrostaticSummationMethod()) {
235 string myMethod = simParams_->getElectrostaticSummationMethod();
238 if (myMethod ==
"SHIFTED_POTENTIAL") {
240 }
else if (myMethod ==
"SHIFTED_FORCE") {
242 }
else if (myMethod ==
"TAYLOR_SHIFTED") {
244 }
else if (myMethod ==
"EWALD_FULL") {
246 useSurfaceTerm_ =
true;
249 if (simParams_->haveSwitchingRadius())
250 rSwitch_ = simParams_->getSwitchingRadius();
252 if (myMethod ==
"SHIFTED_POTENTIAL" || myMethod ==
"SHIFTED_FORCE" ||
253 myMethod ==
"TAYLOR_SHIFTED" || myMethod ==
"EWALD_FULL") {
254 if (simParams_->haveSwitchingRadius()) {
255 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
256 "ForceManager::setupCutoffs : DEPRECATED ERROR MESSAGE\n"
257 "\tA value was set for the switchingRadius\n"
258 "\teven though the electrostaticSummationMethod was\n"
261 painCave.severity = OPENMD_WARNING;
262 painCave.isFatal = 1;
268 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
269 "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
270 "\tcutoffRadius and switchingRadius are set to the\n"
271 "\tsame value. OpenMD will use shifted force\n"
272 "\tpotentials instead of switching functions.\n");
273 painCave.isFatal = 0;
274 painCave.severity = OPENMD_WARNING;
278 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
279 "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
280 "\tcutoffRadius and switchingRadius are set to the\n"
281 "\tsame value. OpenMD will use shifted potentials\n"
282 "\tinstead of switching functions.\n");
283 painCave.isFatal = 0;
284 painCave.severity = OPENMD_WARNING;
297 if (simParams_->haveSwitchingRadius()) {
298 rSwitch_ = simParams_->getSwitchingRadius();
300 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
301 "ForceManager::setupCutoffs: switchingRadius (%f) is larger "
302 "than the cutoffRadius(%f)\n",
304 painCave.isFatal = 1;
305 painCave.severity = OPENMD_ERROR;
310 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
311 "ForceManager::setupCutoffs: No value was set for the "
313 "\tOpenMD will use a default value of 85 percent of the "
315 "\tswitchingRadius = %f. for this simulation\n",
317 painCave.isFatal = 0;
318 painCave.severity = OPENMD_WARNING;
322 if (mdFileVersion > 1) {
325 if (simParams_->haveSwitchingRadius()) {
326 map<string, CutoffMethod>::const_iterator it;
328 for (it = stringToCutoffMethod.begin();
329 it != stringToCutoffMethod.end(); ++it) {
335 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
336 "ForceManager::setupCutoffs: the cutoffMethod (%s)\n"
337 "\tis not set to SWITCHED, so switchingRadius value\n"
338 "\twill be ignored for this simulation\n",
340 painCave.isFatal = 0;
341 painCave.severity = OPENMD_WARNING;
350 if (simParams_->haveSwitchingFunctionType()) {
351 string funcType = simParams_->getSwitchingFunctionType();
353 if (funcType ==
"CUBIC") {
356 if (funcType ==
"FIFTH_ORDER_POLYNOMIAL") {
357 sft_ = fifth_order_poly;
361 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
362 "ForceManager::setupSwitching : Unknown switchingFunctionType. "
364 "file specified %s .)\n"
365 "\tswitchingFunctionType must be one of: "
366 "\"cubic\" or \"fifth_order_polynomial\".",
368 painCave.isFatal = 1;
369 painCave.severity = OPENMD_ERROR;
374 switcher_->setSwitchType(
sft_);
379 if (!info_->isTopologyDone()) {
381 interactionMan_->setSimInfo(info_);
382 interactionMan_->initialize();
384 useSurfaceTerm_ =
false;
385 useSlabGeometry_ =
false;
394 doParticlePot_ = info_->getSimParams()->getOutputParticlePotential();
395 doHeatFlux_ = info_->getSimParams()->getPrintHeatFlux();
396 if (doHeatFlux_) doParticlePot_ =
true;
398 doElectricField_ = info_->getSimParams()->getOutputElectricField();
400 info_->getSimParams()->getRNEMDParameters()->requiresElectricField();
401 doSitePotential_ = info_->getSimParams()->getOutputSitePotential();
402 if (info_->getSimParams()->haveUseSurfaceTerm() &&
403 info_->getSimParams()->getUseSurfaceTerm()) {
404 if (info_->usesElectrostaticAtoms()) {
405 useSurfaceTerm_ = info_->getSimParams()->getUseSurfaceTerm();
406 if (info_->getSimParams()->haveUseSlabGeometry()) {
407 useSlabGeometry_ = info_->getSimParams()->getUseSlabGeometry();
410 toUpperCopy(info_->getSimParams()->getPrivilegedAxis());
411 if (axis.compare(
"X") == 0)
413 else if (axis.compare(
"Y") == 0)
419 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
420 "ForceManager::initialize : useSurfaceTerm was set true\n"
421 "\tbut no electrostatic atoms are present. OpenMD will\n"
422 "\tignore this setting.\n");
423 painCave.isFatal = 0;
424 painCave.severity = OPENMD_WARNING;
441 vdwScale_.reserve(4);
442 fill(vdwScale_.begin(), vdwScale_.end(), 0.0);
444 electrostaticScale_.reserve(4);
445 fill(electrostaticScale_.begin(), electrostaticScale_.end(), 0.0);
448 vdwScale_[1] = fopts.getvdw12scale();
449 vdwScale_[2] = fopts.getvdw13scale();
450 vdwScale_[3] = fopts.getvdw14scale();
452 electrostaticScale_[0] = 1.0;
453 electrostaticScale_[1] = fopts.getelectrostatic12scale();
454 electrostaticScale_[2] = fopts.getelectrostatic13scale();
455 electrostaticScale_[3] = fopts.getelectrostatic14scale();
458 if (info_->getSimParams()->haveUniformField()) {
460 forceModifiers_.push_back(eField);
463 if (info_->getSimParams()->haveMagneticField()) {
465 forceModifiers_.push_back(mField);
468 if (info_->getSimParams()->haveUniformGradientStrength() ||
469 info_->getSimParams()->haveUniformGradientDirection1() ||
470 info_->getSimParams()->haveUniformGradientDirection2()) {
472 forceModifiers_.push_back(eGrad);
475 if (info_->getSimParams()->getLightParameters()->getUseLight()) {
477 forceModifiers_.push_back(light);
481 if (info_->getSimParams()->getUseThermodynamicIntegration()) {
484 forceModifiers_.push_back(thermoInt);
485 }
else if (info_->getSimParams()->getUseRestraints()) {
487 forceModifiers_.push_back(restraint);
490 std::string ensembleParam =
491 toUpperCopy(info_->getSimParams()->getEnsemble());
493 if (ensembleParam ==
"LHULL" || ensembleParam ==
"LANGEVINHULL" ||
494 ensembleParam ==
"SMIPD") {
497 forceModifiers_.push_back(langevinHullFM);
498 }
else if (ensembleParam ==
"LANGEVINDYNAMICS" || ensembleParam ==
"LD") {
500 forceModifiers_.push_back(langevinDynamicsFM);
503 if (info_->getSimParams()->getNZconsStamps() > 0) {
506 forceModifiers_.push_back(zCons);
509 usePeriodicBoundaryConditions_ =
510 info_->getSimParams()->getUsePeriodicBoundaryConditions();
512 fDecomp_->distributeInitialData();
514 doPotentialSelection_ =
false;
515 if (info_->getSimParams()->havePotentialSelection()) {
516 doPotentialSelection_ =
true;
517 selectionScript_ = info_->getSimParams()->getPotentialSelection();
518 evaluator_.loadScriptString(selectionScript_);
520 seleMan_.setSelectionSet(evaluator_.evaluate());
527 void ForceManager::calcForces() {
531 shortRangeInteractions();
532 longRangeInteractions();
536 void ForceManager::preCalculation() {
537 SimInfo::MoleculeIterator mi;
539 Molecule::AtomIterator ai;
541 Molecule::RigidBodyIterator rbIter;
543 Molecule::CutoffGroupIterator ci;
551 fDecomp_->setSnapshot(snap);
553 snap->setBondPotential(0.0);
554 snap->setBendPotential(0.0);
555 snap->setTorsionPotential(0.0);
556 snap->setInversionPotential(0.0);
559 snap->setLongRangePotentials(zeroPot);
561 snap->setExcludedPotentials(zeroPot);
562 if (doPotentialSelection_) snap->setSelectionPotentials(zeroPot);
564 snap->setSelfPotentials(0.0);
565 snap->setRestraintPotential(0.0);
566 snap->setRawPotential(0.0);
570 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
575 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
576 rb = mol->nextRigidBody(rbIter)) {
581 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
582 cg = mol->nextCutoffGroup(ci)) {
592 fDecomp_->setHeatFlux(
Vector3d(0.0));
594 if (doPotentialSelection_) {
596 seleMan_.setSelectionSet(evaluator_.evaluate());
601 void ForceManager::shortRangeInteractions() {
608 SimInfo::MoleculeIterator mi;
609 Molecule::RigidBodyIterator rbIter;
610 Molecule::BondIterator bondIter;
612 Molecule::BendIterator bendIter;
613 Molecule::TorsionIterator torsionIter;
614 Molecule::InversionIterator inversionIter;
615 RealType bondPotential = 0.0;
616 RealType bendPotential = 0.0;
617 RealType torsionPotential = 0.0;
618 RealType inversionPotential = 0.0;
619 potVec selectionPotential(0.0);
625 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
626 rb = mol->nextRigidBody(rbIter)) {
630 for (bond = mol->beginBond(bondIter); bond != NULL;
631 bond = mol->nextBond(bondIter)) {
632 bond->calcForce(doParticlePot_);
633 bondPotential += bond->getPotential();
634 if (doPotentialSelection_) {
635 if (seleMan_.isSelected(bond->getAtomA()) ||
636 seleMan_.isSelected(bond->getAtomB())) {
642 for (bend = mol->beginBend(bendIter); bend != NULL;
643 bend = mol->nextBend(bendIter)) {
646 RealType currBendPot = bend->getPotential();
648 bendPotential += bend->getPotential();
649 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
650 if (i == bendDataSets.end()) {
652 dataSet.prev.angle = dataSet.curr.angle = angle;
653 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
654 dataSet.deltaV = 0.0;
656 map<Bend*, BendDataSet>::value_type(bend, dataSet));
658 i->second.prev.angle = i->second.curr.angle;
659 i->second.prev.potential = i->second.curr.potential;
660 i->second.curr.angle = angle;
661 i->second.curr.potential = currBendPot;
663 fabs(i->second.curr.potential - i->second.prev.potential);
665 if (doPotentialSelection_) {
666 if (seleMan_.isSelected(bend->getAtomA()) ||
667 seleMan_.isSelected(bend->getAtomB()) ||
668 seleMan_.isSelected(bend->getAtomC())) {
674 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
675 torsion = mol->nextTorsion(torsionIter)) {
677 torsion->calcForce(angle, doParticlePot_);
678 RealType currTorsionPot = torsion->getPotential();
679 torsionPotential += torsion->getPotential();
680 map<Torsion*, TorsionDataSet>::iterator i =
681 torsionDataSets.find(torsion);
682 if (i == torsionDataSets.end()) {
684 dataSet.prev.angle = dataSet.curr.angle = angle;
685 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
686 dataSet.deltaV = 0.0;
687 torsionDataSets.insert(
688 map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
690 i->second.prev.angle = i->second.curr.angle;
691 i->second.prev.potential = i->second.curr.potential;
692 i->second.curr.angle = angle;
693 i->second.curr.potential = currTorsionPot;
695 fabs(i->second.curr.potential - i->second.prev.potential);
697 if (doPotentialSelection_) {
698 if (seleMan_.isSelected(torsion->getAtomA()) ||
699 seleMan_.isSelected(torsion->getAtomB()) ||
700 seleMan_.isSelected(torsion->getAtomC()) ||
701 seleMan_.isSelected(torsion->getAtomD())) {
702 selectionPotential[
BONDED_FAMILY] += torsion->getPotential();
707 for (inversion = mol->beginInversion(inversionIter); inversion != NULL;
708 inversion = mol->nextInversion(inversionIter)) {
710 inversion->calcForce(angle, doParticlePot_);
711 RealType currInversionPot = inversion->getPotential();
712 inversionPotential += inversion->getPotential();
713 map<Inversion*, InversionDataSet>::iterator i =
714 inversionDataSets.find(inversion);
715 if (i == inversionDataSets.end()) {
717 dataSet.prev.angle = dataSet.curr.angle = angle;
718 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
719 dataSet.deltaV = 0.0;
720 inversionDataSets.insert(
721 map<Inversion*, InversionDataSet>::value_type(inversion,
724 i->second.prev.angle = i->second.curr.angle;
725 i->second.prev.potential = i->second.curr.potential;
726 i->second.curr.angle = angle;
727 i->second.curr.potential = currInversionPot;
729 fabs(i->second.curr.potential - i->second.prev.potential);
731 if (doPotentialSelection_) {
732 if (seleMan_.isSelected(inversion->getAtomA()) ||
733 seleMan_.isSelected(inversion->getAtomB()) ||
734 seleMan_.isSelected(inversion->getAtomC()) ||
735 seleMan_.isSelected(inversion->getAtomD())) {
736 selectionPotential[
BONDED_FAMILY] += inversion->getPotential();
747 MPI_Allreduce(MPI_IN_PLACE, &bondPotential, 1, MPI_REALTYPE, MPI_SUM,
749 MPI_Allreduce(MPI_IN_PLACE, &bendPotential, 1, MPI_REALTYPE, MPI_SUM,
751 MPI_Allreduce(MPI_IN_PLACE, &torsionPotential, 1, MPI_REALTYPE, MPI_SUM,
753 MPI_Allreduce(MPI_IN_PLACE, &inversionPotential, 1, MPI_REALTYPE, MPI_SUM,
755 MPI_Allreduce(MPI_IN_PLACE, &selectionPotential[
BONDED_FAMILY], 1,
756 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
760 fDecomp_->setSnapshot(curSnapshot);
762 curSnapshot->setBondPotential(bondPotential);
763 curSnapshot->setBendPotential(bendPotential);
764 curSnapshot->setTorsionPotential(torsionPotential);
765 curSnapshot->setInversionPotential(inversionPotential);
766 curSnapshot->setSelectionPotentials(selectionPotential);
774 void ForceManager::longRangeInteractions() {
776 fDecomp_->setSnapshot(curSnapshot);
783 SimInfo::MoleculeIterator mi;
785 Molecule::CutoffGroupIterator ci;
791 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
792 cg = mol->nextCutoffGroup(ci)) {
799 cgConfig->position = config->position;
803 fDecomp_->zeroWorkArrays();
804 fDecomp_->distributeData();
806 int cg1, cg2, atom1, atom2;
808 RealType rgrpsq, rgrp;
811 bool in_switching_region;
812 RealType dswdr, swderiv;
813 vector<int> atomListColumn, atomListRow;
815 potVec longRangePotential(0.0);
816 potVec selfPotential(0.0);
817 RealType reciprocalPotential(0.0);
818 RealType surfacePotential(0.0);
819 potVec selectionPotential(0.0);
825 vector<int>::iterator ia, jb;
827 int loopStart, loopEnd;
841 if (info_->requiresPrepair()) {
842 loopStart = PREPAIR_LOOP;
844 loopStart = PAIR_LOOP;
846 for (
int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
847 if (iLoop == loopStart) {
848 bool update_nlist = fDecomp_->checkNeighborList(savedPositions_);
851 if (!usePeriodicBoundaryConditions_)
853 fDecomp_->buildNeighborList(neighborList_, point_, savedPositions_);
857 for (cg1 = 0; cg1 < int(point_.size()) - 1; cg1++) {
858 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
861 for (
int m2 = point_[cg1]; m2 < point_[cg1 + 1]; m2++) {
862 cg2 = neighborList_[m2];
864 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
870 if (rgrpsq < rCutSq_) {
871 if (iLoop == PAIR_LOOP) {
880 in_switching_region =
881 switcher_->getSwitch(rgrpsq, idat.
sw, dswdr, rgrp);
883 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
885 if (doHeatFlux_) gvel2 = fDecomp_->getGroupVelocityColumn(cg2);
887 for (ia = atomListRow.begin(); ia != atomListRow.end(); ++ia) {
889 if (atomListRow.size() > 1) newAtom1 =
true;
891 if (doPotentialSelection_) {
892 gid1 = fDecomp_->getGlobalIDRow(atom1);
893 idat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
896 for (jb = atomListColumn.begin(); jb != atomListColumn.end();
900 if (doPotentialSelection_) {
901 gid2 = fDecomp_->getGlobalIDCol(atom2);
902 idat.
isSelected |= seleMan_.isGlobalIDSelected(gid2);
905 if (!fDecomp_->skipAtomPair(atom1, atom2, cg1, cg2)) {
914 fDecomp_->fillInteractionData(idat, atom1, atom2, newAtom1);
918 fDecomp_->getTopologicalDistance(atom1, atom2);
922 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
925 if (doHeatFlux_) vel2 = gvel2;
927 idat.
d = fDecomp_->getInteratomicVector(atom1, atom2);
931 vel2 = fDecomp_->getAtomVelocityColumn(atom2);
934 idat.
rij = sqrt(idat.
r2);
936 if (iLoop == PREPAIR_LOOP) {
937 interactionMan_->doPrePair(idat);
938 fDecomp_->unpackPrePairData(idat, atom1, atom2);
940 interactionMan_->doPair(idat);
941 fDecomp_->unpackInteractionData(idat, atom1, atom2);
944 virialTensor -= outProduct(idat.
d, idat.
f1);
946 fDecomp_->addToHeatFlux(idat.
d *
dot(idat.
f1, vel2));
952 if (iLoop == PAIR_LOOP) {
953 if (in_switching_region) {
954 swderiv = vij * dswdr / rgrp;
955 fg = swderiv * d_grp;
958 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
959 if (!fDecomp_->skipAtomPair(atomListRow[0], atomListColumn[0],
961 virialTensor -= outProduct(idat.
d, fg);
963 fDecomp_->addToHeatFlux(idat.
d *
dot(fg, vel2));
967 for (ia = atomListRow.begin(); ia != atomListRow.end(); ++ia) {
969 mf = fDecomp_->getMassFactorRow(atom1);
972 fg = swderiv * d_grp * mf;
973 fDecomp_->addForceToAtomRow(atom1, fg);
974 if (atomListRow.size() > 1) {
975 if (info_->usesAtomicVirial()) {
978 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
979 virialTensor -= outProduct(dag, fg);
981 fDecomp_->addToHeatFlux(dag *
dot(fg, vel2));
985 for (jb = atomListColumn.begin(); jb != atomListColumn.end();
988 mf = fDecomp_->getMassFactorColumn(atom2);
991 fg = -swderiv * d_grp * mf;
992 fDecomp_->addForceToAtomColumn(atom2, fg);
994 if (atomListColumn.size() > 1) {
995 if (info_->usesAtomicVirial()) {
998 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
999 virialTensor -= outProduct(dag, fg);
1001 fDecomp_->addToHeatFlux(dag *
dot(fg, vel2));
1016 if (iLoop == PREPAIR_LOOP) {
1017 if (info_->requiresPrepair()) {
1018 fDecomp_->collectIntermediateData();
1020 for (
unsigned int atom1 = 0; atom1 < info_->
getNAtoms(); atom1++) {
1021 if (doPotentialSelection_) {
1022 gid1 = fDecomp_->getGlobalID(atom1);
1023 sdat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1025 fDecomp_->fillPreForceData(sdat, atom1);
1026 interactionMan_->doPreForce(sdat);
1027 fDecomp_->unpackPreForceData(sdat, atom1);
1030 fDecomp_->distributeIntermediateData();
1036 fDecomp_->collectData();
1038 interactionMan_->doReciprocalSpaceSum(reciprocalPotential);
1039 curSnapshot->setReciprocalPotential(reciprocalPotential);
1042 if (useSurfaceTerm_) {
1043 interactionMan_->doSurfaceTerm(useSlabGeometry_, axis_, surfacePotential);
1044 curSnapshot->setSurfacePotential(surfacePotential);
1047 if (info_->requiresSelfCorrection()) {
1048 for (
unsigned int atom1 = 0; atom1 < info_->
getNAtoms(); atom1++) {
1049 if (doPotentialSelection_) {
1050 gid1 = fDecomp_->getGlobalID(atom1);
1051 sdat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1053 fDecomp_->fillSelfData(sdat, atom1);
1054 interactionMan_->doSelfCorrection(sdat);
1055 fDecomp_->unpackSelfData(sdat, atom1);
1060 fDecomp_->collectSelfData();
1062 longRangePotential = fDecomp_->getPairwisePotential();
1063 curSnapshot->setLongRangePotentials(longRangePotential);
1065 selfPotential = fDecomp_->getSelfPotential();
1066 curSnapshot->setSelfPotentials(selfPotential);
1068 curSnapshot->setExcludedPotentials(fDecomp_->getExcludedSelfPotential() +
1069 fDecomp_->getExcludedPotential());
1071 if (doPotentialSelection_) {
1072 selectionPotential = curSnapshot->getSelectionPotentials();
1073 selectionPotential += fDecomp_->getSelectedSelfPotential();
1074 selectionPotential += fDecomp_->getSelectedPotential();
1075 curSnapshot->setSelectionPotentials(selectionPotential);
1079 void ForceManager::postCalculation() {
1080 for (
auto& forceModifier : forceModifiers_)
1081 forceModifier->modifyForces();
1084 SimInfo::MoleculeIterator mi;
1086 Molecule::RigidBodyIterator rbIter;
1093 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
1094 rb = mol->nextRigidBody(rbIter)) {
1096 virialTensor += rbTau;
1101 MPI_Allreduce(MPI_IN_PLACE, virialTensor.
getArrayPointer(), 9, MPI_REALTYPE,
1102 MPI_SUM, MPI_COMM_WORLD);
1104 curSnapshot->setVirialTensor(virialTensor);
1146 selectedPreCalculation(mol1, mol2);
1147 selectedShortRangeInteractions(mol1, mol2);
1148 selectedLongRangeInteractions(mol1, mol2);
1149 selectedPostCalculation(mol1, mol2);
1152 void ForceManager::selectedPreCalculation(
Molecule* mol1,
Molecule* mol2) {
1153 SimInfo::MoleculeIterator mi;
1154 Molecule::AtomIterator ai;
1156 Molecule::RigidBodyIterator rbIter;
1158 Molecule::CutoffGroupIterator ci;
1166 snap->setBondPotential(0.0);
1167 snap->setBendPotential(0.0);
1168 snap->setTorsionPotential(0.0);
1169 snap->setInversionPotential(0.0);
1172 snap->setLongRangePotentials(zeroPot);
1173 snap->setExcludedPotentials(zeroPot);
1174 if (doPotentialSelection_) snap->setSelectionPotentials(zeroPot);
1176 snap->setRestraintPotential(0.0);
1177 snap->setRawPotential(0.0);
1180 for (atom = mol1->beginAtom(ai); atom != NULL; atom = mol1->nextAtom(ai)) {
1184 for (rb = mol1->beginRigidBody(rbIter); rb != NULL;
1185 rb = mol1->nextRigidBody(rbIter)) {
1189 for (cg = mol1->beginCutoffGroup(ci); cg != NULL;
1190 cg = mol1->nextCutoffGroup(ci)) {
1197 for (atom = mol2->beginAtom(ai); atom != NULL; atom = mol2->nextAtom(ai)) {
1201 for (rb = mol2->beginRigidBody(rbIter); rb != NULL;
1202 rb = mol2->nextRigidBody(rbIter)) {
1206 for (cg = mol2->beginCutoffGroup(ci); cg != NULL;
1207 cg = mol2->nextCutoffGroup(ci)) {
1214 virialTensor *= 0.0;
1216 fDecomp_->setHeatFlux(
Vector3d(0.0));
1219 void ForceManager::selectedShortRangeInteractions(
Molecule* mol1,
1226 SimInfo::MoleculeIterator mi;
1227 Molecule::RigidBodyIterator rbIter;
1228 Molecule::BondIterator bondIter;
1229 Molecule::BendIterator bendIter;
1230 Molecule::TorsionIterator torsionIter;
1231 Molecule::InversionIterator inversionIter;
1232 RealType bondPotential = 0.0;
1233 RealType bendPotential = 0.0;
1234 RealType torsionPotential = 0.0;
1235 RealType inversionPotential = 0.0;
1236 potVec selectionPotential(0.0);
1239 for (rb = mol1->beginRigidBody(rbIter); rb != NULL;
1240 rb = mol1->nextRigidBody(rbIter)) {
1244 for (bond = mol1->beginBond(bondIter); bond != NULL;
1245 bond = mol1->nextBond(bondIter)) {
1246 bond->calcForce(doParticlePot_);
1247 bondPotential += bond->getPotential();
1248 if (doPotentialSelection_) {
1249 if (seleMan_.isSelected(bond->getAtomA()) ||
1250 seleMan_.isSelected(bond->getAtomB())) {
1256 for (bend = mol1->beginBend(bendIter); bend != NULL;
1257 bend = mol1->nextBend(bendIter)) {
1260 RealType currBendPot = bend->getPotential();
1262 bendPotential += bend->getPotential();
1263 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
1264 if (i == bendDataSets.end()) {
1266 dataSet.prev.angle = dataSet.curr.angle = angle;
1267 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
1268 dataSet.deltaV = 0.0;
1269 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend, dataSet));
1271 i->second.prev.angle = i->second.curr.angle;
1272 i->second.prev.potential = i->second.curr.potential;
1273 i->second.curr.angle = angle;
1274 i->second.curr.potential = currBendPot;
1276 fabs(i->second.curr.potential - i->second.prev.potential);
1278 if (doPotentialSelection_) {
1279 if (seleMan_.isSelected(bend->getAtomA()) ||
1280 seleMan_.isSelected(bend->getAtomB()) ||
1281 seleMan_.isSelected(bend->getAtomC())) {
1287 for (torsion = mol1->beginTorsion(torsionIter); torsion != NULL;
1288 torsion = mol1->nextTorsion(torsionIter)) {
1290 torsion->calcForce(angle, doParticlePot_);
1291 RealType currTorsionPot = torsion->getPotential();
1292 torsionPotential += torsion->getPotential();
1293 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
1294 if (i == torsionDataSets.end()) {
1296 dataSet.prev.angle = dataSet.curr.angle = angle;
1297 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
1298 dataSet.deltaV = 0.0;
1299 torsionDataSets.insert(
1300 map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
1302 i->second.prev.angle = i->second.curr.angle;
1303 i->second.prev.potential = i->second.curr.potential;
1304 i->second.curr.angle = angle;
1305 i->second.curr.potential = currTorsionPot;
1307 fabs(i->second.curr.potential - i->second.prev.potential);
1309 if (doPotentialSelection_) {
1310 if (seleMan_.isSelected(torsion->getAtomA()) ||
1311 seleMan_.isSelected(torsion->getAtomB()) ||
1312 seleMan_.isSelected(torsion->getAtomC()) ||
1313 seleMan_.isSelected(torsion->getAtomD())) {
1314 selectionPotential[
BONDED_FAMILY] += torsion->getPotential();
1319 for (inversion = mol1->beginInversion(inversionIter); inversion != NULL;
1320 inversion = mol1->nextInversion(inversionIter)) {
1322 inversion->calcForce(angle, doParticlePot_);
1323 RealType currInversionPot = inversion->getPotential();
1324 inversionPotential += inversion->getPotential();
1325 map<Inversion*, InversionDataSet>::iterator i =
1326 inversionDataSets.find(inversion);
1327 if (i == inversionDataSets.end()) {
1329 dataSet.prev.angle = dataSet.curr.angle = angle;
1330 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
1331 dataSet.deltaV = 0.0;
1332 inversionDataSets.insert(
1333 map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
1335 i->second.prev.angle = i->second.curr.angle;
1336 i->second.prev.potential = i->second.curr.potential;
1337 i->second.curr.angle = angle;
1338 i->second.curr.potential = currInversionPot;
1340 fabs(i->second.curr.potential - i->second.prev.potential);
1342 if (doPotentialSelection_) {
1343 if (seleMan_.isSelected(inversion->getAtomA()) ||
1344 seleMan_.isSelected(inversion->getAtomB()) ||
1345 seleMan_.isSelected(inversion->getAtomC()) ||
1346 seleMan_.isSelected(inversion->getAtomD())) {
1347 selectionPotential[
BONDED_FAMILY] += inversion->getPotential();
1353 for (rb = mol2->beginRigidBody(rbIter); rb != NULL;
1354 rb = mol2->nextRigidBody(rbIter)) {
1358 for (bond = mol2->beginBond(bondIter); bond != NULL;
1359 bond = mol2->nextBond(bondIter)) {
1360 bond->calcForce(doParticlePot_);
1361 bondPotential += bond->getPotential();
1362 if (doPotentialSelection_) {
1363 if (seleMan_.isSelected(bond->getAtomA()) ||
1364 seleMan_.isSelected(bond->getAtomB())) {
1370 for (bend = mol2->beginBend(bendIter); bend != NULL;
1371 bend = mol2->nextBend(bendIter)) {
1374 RealType currBendPot = bend->getPotential();
1376 bendPotential += bend->getPotential();
1377 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
1378 if (i == bendDataSets.end()) {
1380 dataSet.prev.angle = dataSet.curr.angle = angle;
1381 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
1382 dataSet.deltaV = 0.0;
1383 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend, dataSet));
1385 i->second.prev.angle = i->second.curr.angle;
1386 i->second.prev.potential = i->second.curr.potential;
1387 i->second.curr.angle = angle;
1388 i->second.curr.potential = currBendPot;
1390 fabs(i->second.curr.potential - i->second.prev.potential);
1392 if (doPotentialSelection_) {
1393 if (seleMan_.isSelected(bend->getAtomA()) ||
1394 seleMan_.isSelected(bend->getAtomB()) ||
1395 seleMan_.isSelected(bend->getAtomC())) {
1401 for (torsion = mol2->beginTorsion(torsionIter); torsion != NULL;
1402 torsion = mol2->nextTorsion(torsionIter)) {
1404 torsion->calcForce(angle, doParticlePot_);
1405 RealType currTorsionPot = torsion->getPotential();
1406 torsionPotential += torsion->getPotential();
1407 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
1408 if (i == torsionDataSets.end()) {
1410 dataSet.prev.angle = dataSet.curr.angle = angle;
1411 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
1412 dataSet.deltaV = 0.0;
1413 torsionDataSets.insert(
1414 map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
1416 i->second.prev.angle = i->second.curr.angle;
1417 i->second.prev.potential = i->second.curr.potential;
1418 i->second.curr.angle = angle;
1419 i->second.curr.potential = currTorsionPot;
1421 fabs(i->second.curr.potential - i->second.prev.potential);
1423 if (doPotentialSelection_) {
1424 if (seleMan_.isSelected(torsion->getAtomA()) ||
1425 seleMan_.isSelected(torsion->getAtomB()) ||
1426 seleMan_.isSelected(torsion->getAtomC()) ||
1427 seleMan_.isSelected(torsion->getAtomD())) {
1428 selectionPotential[
BONDED_FAMILY] += torsion->getPotential();
1433 for (inversion = mol2->beginInversion(inversionIter); inversion != NULL;
1434 inversion = mol2->nextInversion(inversionIter)) {
1436 inversion->calcForce(angle, doParticlePot_);
1437 RealType currInversionPot = inversion->getPotential();
1438 inversionPotential += inversion->getPotential();
1439 map<Inversion*, InversionDataSet>::iterator i =
1440 inversionDataSets.find(inversion);
1441 if (i == inversionDataSets.end()) {
1443 dataSet.prev.angle = dataSet.curr.angle = angle;
1444 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
1445 dataSet.deltaV = 0.0;
1446 inversionDataSets.insert(
1447 map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
1449 i->second.prev.angle = i->second.curr.angle;
1450 i->second.prev.potential = i->second.curr.potential;
1451 i->second.curr.angle = angle;
1452 i->second.curr.potential = currInversionPot;
1454 fabs(i->second.curr.potential - i->second.prev.potential);
1456 if (doPotentialSelection_) {
1457 if (seleMan_.isSelected(inversion->getAtomA()) ||
1458 seleMan_.isSelected(inversion->getAtomB()) ||
1459 seleMan_.isSelected(inversion->getAtomC()) ||
1460 seleMan_.isSelected(inversion->getAtomD())) {
1461 selectionPotential[
BONDED_FAMILY] += inversion->getPotential();
1471 MPI_Allreduce(MPI_IN_PLACE, &bondPotential, 1, MPI_REALTYPE, MPI_SUM,
1473 MPI_Allreduce(MPI_IN_PLACE, &bendPotential, 1, MPI_REALTYPE, MPI_SUM,
1475 MPI_Allreduce(MPI_IN_PLACE, &torsionPotential, 1, MPI_REALTYPE, MPI_SUM,
1477 MPI_Allreduce(MPI_IN_PLACE, &inversionPotential, 1, MPI_REALTYPE, MPI_SUM,
1479 MPI_Allreduce(MPI_IN_PLACE, &selectionPotential[
BONDED_FAMILY], 1,
1480 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
1485 curSnapshot->setBondPotential(bondPotential);
1486 curSnapshot->setBendPotential(bendPotential);
1487 curSnapshot->setTorsionPotential(torsionPotential);
1488 curSnapshot->setInversionPotential(inversionPotential);
1489 curSnapshot->setSelectionPotentials(selectionPotential);
1497 void ForceManager::selectedLongRangeInteractions(
Molecule* mol1,
1505 SimInfo::MoleculeIterator mi;
1506 Molecule::CutoffGroupIterator ci;
1510 for (cg = mol1->beginCutoffGroup(ci); cg != NULL;
1511 cg = mol1->nextCutoffGroup(ci)) {
1514 for (cg = mol2->beginCutoffGroup(ci); cg != NULL;
1515 cg = mol2->nextCutoffGroup(ci)) {
1521 cgConfig->position = config->position;
1525 fDecomp_->zeroWorkArrays();
1526 fDecomp_->distributeData();
1528 int cg1, cg2, atom1, atom2;
1530 RealType rgrpsq, rgrp;
1533 bool in_switching_region;
1534 RealType dswdr, swderiv;
1535 vector<int> atomListColumn, atomListRow;
1537 potVec longRangePotential(0.0);
1538 potVec selfPotential(0.0);
1539 potVec selectionPotential(0.0);
1540 RealType reciprocalPotential(0.0);
1541 RealType surfacePotential(0.0);
1547 vector<int>::iterator ia, jb;
1549 int loopStart, loopEnd;
1562 loopEnd = PAIR_LOOP;
1563 if (info_->requiresPrepair()) {
1564 loopStart = PREPAIR_LOOP;
1566 loopStart = PAIR_LOOP;
1568 for (
int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
1569 if (iLoop == loopStart) {
1570 bool update_nlist = fDecomp_->checkNeighborList(savedPositions_);
1573 if (!usePeriodicBoundaryConditions_)
1575 fDecomp_->buildNeighborList(neighborList_, point_, savedPositions_);
1579 for (cg1 = 0; cg1 < int(point_.size()) - 1; cg1++) {
1580 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
1583 for (
int m2 = point_[cg1]; m2 < point_[cg1 + 1]; m2++) {
1584 cg2 = neighborList_[m2];
1586 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
1592 if (rgrpsq < rCutSq_) {
1593 if (iLoop == PAIR_LOOP) {
1602 in_switching_region =
1603 switcher_->getSwitch(rgrpsq, idat.
sw, dswdr, rgrp);
1605 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
1607 if (doHeatFlux_) gvel2 = fDecomp_->getGroupVelocityColumn(cg2);
1609 for (ia = atomListRow.begin(); ia != atomListRow.end(); ++ia) {
1610 if (atomListRow.size() > 1) newAtom1 =
true;
1613 if (doPotentialSelection_) {
1614 gid1 = fDecomp_->getGlobalIDRow(atom1);
1615 idat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1618 for (jb = atomListColumn.begin(); jb != atomListColumn.end();
1622 if (doPotentialSelection_) {
1623 gid2 = fDecomp_->getGlobalIDCol(atom2);
1624 idat.
isSelected |= seleMan_.isGlobalIDSelected(gid2);
1627 if (!fDecomp_->skipAtomPair(atom1, atom2, cg1, cg2)) {
1636 fDecomp_->fillInteractionData(idat, atom1, atom2, newAtom1);
1640 fDecomp_->getTopologicalDistance(atom1, atom2);
1644 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
1647 if (doHeatFlux_) vel2 = gvel2;
1649 idat.
d = fDecomp_->getInteratomicVector(atom1, atom2);
1653 vel2 = fDecomp_->getAtomVelocityColumn(atom2);
1656 idat.
rij = sqrt(idat.
r2);
1658 if (iLoop == PREPAIR_LOOP) {
1659 interactionMan_->doPrePair(idat);
1660 fDecomp_->unpackPrePairData(idat, atom1, atom2);
1662 interactionMan_->doPair(idat);
1663 fDecomp_->unpackInteractionData(idat, atom1, atom2);
1666 virialTensor -= outProduct(idat.
d, idat.
f1);
1668 fDecomp_->addToHeatFlux(idat.
d *
dot(idat.
f1, vel2));
1674 if (iLoop == PAIR_LOOP) {
1675 if (in_switching_region) {
1676 swderiv = vij * dswdr / rgrp;
1677 fg = swderiv * d_grp;
1680 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
1681 if (!fDecomp_->skipAtomPair(atomListRow[0], atomListColumn[0],
1683 virialTensor -= outProduct(idat.
d, fg);
1685 fDecomp_->addToHeatFlux(idat.
d *
dot(fg, vel2));
1689 for (ia = atomListRow.begin(); ia != atomListRow.end(); ++ia) {
1691 mf = fDecomp_->getMassFactorRow(atom1);
1694 fg = swderiv * d_grp * mf;
1695 fDecomp_->addForceToAtomRow(atom1, fg);
1696 if (atomListRow.size() > 1) {
1697 if (info_->usesAtomicVirial()) {
1700 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
1701 virialTensor -= outProduct(dag, fg);
1703 fDecomp_->addToHeatFlux(dag *
dot(fg, vel2));
1707 for (jb = atomListColumn.begin(); jb != atomListColumn.end();
1710 mf = fDecomp_->getMassFactorColumn(atom2);
1713 fg = -swderiv * d_grp * mf;
1714 fDecomp_->addForceToAtomColumn(atom2, fg);
1716 if (atomListColumn.size() > 1) {
1717 if (info_->usesAtomicVirial()) {
1720 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
1721 virialTensor -= outProduct(dag, fg);
1723 fDecomp_->addToHeatFlux(dag *
dot(fg, vel2));
1738 if (iLoop == PREPAIR_LOOP) {
1739 if (info_->requiresPrepair()) {
1740 fDecomp_->collectIntermediateData();
1742 for (
unsigned int atom1 = 0; atom1 < info_->
getNAtoms(); atom1++) {
1743 if (doPotentialSelection_) {
1744 gid1 = fDecomp_->getGlobalID(atom1);
1745 sdat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1748 fDecomp_->fillPreForceData(sdat, atom1);
1749 interactionMan_->doPreForce(sdat);
1750 fDecomp_->unpackPreForceData(sdat, atom1);
1753 fDecomp_->distributeIntermediateData();
1759 fDecomp_->collectData();
1761 interactionMan_->doReciprocalSpaceSum(reciprocalPotential);
1762 curSnapshot->setReciprocalPotential(reciprocalPotential);
1765 if (useSurfaceTerm_) {
1766 interactionMan_->doSurfaceTerm(useSlabGeometry_, axis_, surfacePotential);
1767 curSnapshot->setSurfacePotential(surfacePotential);
1770 if (info_->requiresSelfCorrection()) {
1771 for (
unsigned int atom1 = 0; atom1 < info_->
getNAtoms(); atom1++) {
1772 if (doPotentialSelection_) {
1773 gid1 = fDecomp_->getGlobalID(atom1);
1774 sdat.
isSelected = seleMan_.isGlobalIDSelected(gid1);
1777 fDecomp_->fillSelfData(sdat, atom1);
1778 interactionMan_->doSelfCorrection(sdat);
1779 fDecomp_->unpackSelfData(sdat, atom1);
1784 fDecomp_->collectSelfData();
1786 longRangePotential = fDecomp_->getPairwisePotential();
1787 curSnapshot->setLongRangePotentials(longRangePotential);
1789 selfPotential = fDecomp_->getSelfPotential();
1790 curSnapshot->setSelfPotentials(selfPotential);
1792 curSnapshot->setExcludedPotentials(fDecomp_->getExcludedSelfPotential() +
1793 fDecomp_->getExcludedPotential());
1795 if (doPotentialSelection_) {
1796 selectionPotential = curSnapshot->getSelectionPotentials();
1797 selectionPotential += fDecomp_->getSelectedSelfPotential();
1798 selectionPotential += fDecomp_->getSelectedPotential();
1799 curSnapshot->setSelectionPotentials(selectionPotential);
1803 void ForceManager::selectedPostCalculation(
Molecule* mol1,
Molecule* mol2) {
1804 for (
auto& forceModifier : forceModifiers_)
1805 forceModifier->modifyForces();
1808 SimInfo::MoleculeIterator mi;
1809 Molecule::RigidBodyIterator rbIter;
1814 for (rb = mol1->beginRigidBody(rbIter); rb != NULL;
1815 rb = mol1->nextRigidBody(rbIter)) {
1817 virialTensor += rbTau;
1820 for (rb = mol2->beginRigidBody(rbIter); rb != NULL;
1821 rb = mol2->nextRigidBody(rbIter)) {
1823 virialTensor += rbTau;
1827 MPI_Allreduce(MPI_IN_PLACE, virialTensor.
getArrayPointer(), 9, MPI_REALTYPE,
1828 MPI_SUM, MPI_COMM_WORLD);
1830 curSnapshot->setVirialTensor(virialTensor);
Rotating Electric Field perturbation.
Uniform Magnetic Field perturbation.
virtual void calcForce(RealType &angle, bool doParticlePot)
vector< Vector3d > velocity
position array
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.
Applies an EM field representing light to the system.
Real * getArrayPointer()
Returns the pointer of internal array.
void updateAtoms()
update the positions of atoms belong to this rigidbody
Mat3x3d calcForcesAndTorquesAndVirial()
Converts Atomic forces and torques to total forces and torques and computes the rigid body contributi...
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.
void wrapVector(Vector3d &v)
Wrapping the vector according to periodic boundary condition.
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
void zeroForcesAndTorques()
Set the properties of this stuntDouble to zero.
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?