54#include "brains/ForceModifier.hpp"
55#include "nonbonded/NonBondedInteraction.hpp"
57#include "types/FixedChargeAdapter.hpp"
58#include "types/FluctuatingChargeAdapter.hpp"
59#include "types/MultipoleAdapter.hpp"
60#include "utils/Constants.hpp"
63 UniformGradient::UniformGradient(
SimInfo* info) :
64 ForceModifier {info}, initialized {false}, doUniformGradient {false},
65 doParticlePot {false} {
66 simParams = info_->getSimParams();
69 void UniformGradient::initialize() {
74 if (simParams->haveUniformGradientDirection1()) {
75 std::vector<RealType> d1 = simParams->getUniformGradientDirection1();
77 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
78 "uniformGradientDirection1: Incorrect number of parameters\n"
79 "\tspecified. There should be 3 parameters, but %zu were\n"
93 if (simParams->haveUniformGradientDirection2()) {
94 std::vector<RealType> d2 = simParams->getUniformGradientDirection2();
96 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
97 "uniformGradientDirection2: Incorrect number of parameters\n"
98 "\tspecified. There should be 3 parameters, but %zu were\n"
101 painCave.isFatal = 1;
112 if (simParams->haveUniformGradientStrength()) {
113 g_ = simParams->getUniformGradientStrength();
117 if (haveA && haveB && haveG) {
118 doUniformGradient =
true;
121 Grad_(0, 0) = 2.0 * (a_.x() * b_.x() - cpsi_ / 3.0);
122 Grad_(0, 1) = a_.x() * b_.y() + a_.y() * b_.x();
123 Grad_(0, 2) = a_.x() * b_.z() + a_.z() * b_.x();
124 Grad_(1, 0) = Grad_(0, 1);
125 Grad_(1, 1) = 2.0 * (a_.y() * b_.y() - cpsi_ / 3.0);
126 Grad_(1, 2) = a_.y() * b_.z() + a_.z() * b_.y();
127 Grad_(2, 0) = Grad_(0, 2);
128 Grad_(2, 1) = Grad_(1, 2);
129 Grad_(2, 2) = 2.0 * (a_.z() * b_.z() - cpsi_ / 3.0);
135 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
136 "UniformGradient: uniformGradientDirection1 not specified.\n");
137 painCave.isFatal = 1;
141 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
142 "UniformGradient: uniformGradientDirection2 not specified.\n");
143 painCave.isFatal = 1;
147 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
148 "UniformGradient: uniformGradientStrength not specified.\n");
149 painCave.isFatal = 1;
154 int storageLayout_ = info_->getSnapshotManager()->getAtomStorageLayout();
155 if (storageLayout_ & DataStorage::dslParticlePot) doParticlePot =
true;
159 void UniformGradient::modifyForces() {
160 if (!initialized) initialize();
162 SimInfo::MoleculeIterator i;
163 Molecule::AtomIterator j;
167 potVec longRangePotential(0.0);
183 if (doUniformGradient) {
187 for (mol = info_->beginMolecule(i); mol != NULL;
188 mol = info_->nextMolecule(i)) {
189 for (atom = mol->beginAtom(j); atom != NULL; atom = mol->nextAtom(j)) {
193 atype = atom->getAtomType();
196 info_->getSnapshotManager()->getCurrentSnapshot()->wrapVector(r);
200 atom->addElectricField(EF * Constants::chargeFieldConvert);
202 FixedChargeAdapter fca = FixedChargeAdapter(atype);
203 if (fca.isFixedCharge()) {
208 FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atype);
209 if (fqa.isFluctuatingCharge()) {
211 C += atom->getFlucQPos();
212 atom->addFlucQFrc(
dot(r, EF) * Constants::chargeFieldConvert);
216 f = EF * C * Constants::chargeFieldConvert;
220 if (doParticlePot) { atom->addParticlePot(U); }
224 MultipoleAdapter ma = MultipoleAdapter(atype);
226 D = atom->getDipole() * Constants::dipoleFieldConvert;
235 if (doParticlePot) { atom->addParticlePot(U); }
239 if (ma.isQuadrupole()) {
240 Q = atom->getQuadrupole() * Constants::dipoleFieldConvert;
242 t = 2.0 *
mCross(Q, Grad_);
246 if (doParticlePot) { atom->addParticlePot(U); }
253 MPI_Allreduce(MPI_IN_PLACE, &fPot, 1, MPI_REALTYPE, MPI_SUM,
257 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
258 longRangePotential = snap->getLongRangePotentials();
260 snap->setLongRangePotentials(longRangePotential);
Abstract class for external ForceModifier classes.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Real doubleDot(const RectMatrix< Real, Row, Col > &t1, const RectMatrix< Real, Row, Col > &t2)
Returns the tensor contraction (double dot product) of two rank 2 tensors (or Matrices).
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
Vector< Real, Row > mCross(const RectMatrix< Real, Row, Col > &t1, const RectMatrix< Real, Row, Col > &t2)
Returns the vector (cross) product of two matrices.
@ ELECTROSTATIC_FAMILY
Coulombic and point-multipole interactions.