Commit 95b8dbd6 authored by Peter Eastman's avatar Peter Eastman
Browse files

Allow the user to specify the reaction field dielectric constant

parent e06e0ea7
...@@ -133,6 +133,14 @@ public: ...@@ -133,6 +133,14 @@ public:
* is NoCutoff, this value will have no effect. * is NoCutoff, this value will have no effect.
*/ */
void setCutoffDistance(double distance); void setCutoffDistance(double distance);
/**
* Get the dielectric constant to use for the solvent in the reaction field approximation.
*/
double getReactionFieldDielectric() const;
/**
* Set the dielectric constant to use for the solvent in the reaction field approximation.
*/
void setReactionFieldDielectric(double dielectric);
/** /**
* Get the error tolerance for Ewald summation. This corresponds to the fractional error in the forces * Get the error tolerance for Ewald summation. This corresponds to the fractional error in the forces
* which is acceptable. This value is used to select the reciprocal space cutoff and separation * which is acceptable. This value is used to select the reciprocal space cutoff and separation
...@@ -264,7 +272,7 @@ private: ...@@ -264,7 +272,7 @@ private:
class ParticleInfo; class ParticleInfo;
class ExceptionInfo; class ExceptionInfo;
NonbondedMethod nonbondedMethod; NonbondedMethod nonbondedMethod;
double cutoffDistance, ewaldErrorTol; double cutoffDistance, rfDielectric, ewaldErrorTol;
Vec3 periodicBoxVectors[3]; Vec3 periodicBoxVectors[3];
void addExclusionsToSet(const std::vector<std::set<int> >& bonded12, std::set<int>& exclusions, int baseParticle, int fromParticle, int currentLevel) const; void addExclusionsToSet(const std::vector<std::set<int> >& bonded12, std::set<int>& exclusions, int baseParticle, int fromParticle, int currentLevel) const;
......
...@@ -46,7 +46,7 @@ using std::string; ...@@ -46,7 +46,7 @@ using std::string;
using std::stringstream; using std::stringstream;
using std::vector; using std::vector;
NonbondedForce::NonbondedForce() : nonbondedMethod(NoCutoff), cutoffDistance(1.0), ewaldErrorTol(1e-4) { NonbondedForce::NonbondedForce() : nonbondedMethod(NoCutoff), cutoffDistance(1.0), rfDielectric(78.3), ewaldErrorTol(1e-4) {
periodicBoxVectors[0] = Vec3(2, 0, 0); periodicBoxVectors[0] = Vec3(2, 0, 0);
periodicBoxVectors[1] = Vec3(0, 2, 0); periodicBoxVectors[1] = Vec3(0, 2, 0);
periodicBoxVectors[2] = Vec3(0, 0, 2); periodicBoxVectors[2] = Vec3(0, 0, 2);
...@@ -68,6 +68,14 @@ void NonbondedForce::setCutoffDistance(double distance) { ...@@ -68,6 +68,14 @@ void NonbondedForce::setCutoffDistance(double distance) {
cutoffDistance = distance; cutoffDistance = distance;
} }
double NonbondedForce::getReactionFieldDielectric() const {
return rfDielectric;
}
void NonbondedForce::setReactionFieldDielectric(double dielectric) {
rfDielectric = dielectric;
}
double NonbondedForce::getEwaldErrorTolerance() const { double NonbondedForce::getEwaldErrorTolerance() const {
return ewaldErrorTol; return ewaldErrorTol;
} }
......
...@@ -290,7 +290,7 @@ void CudaCalcNonbondedForceKernel::initialize(const System& system, const Nonbon ...@@ -290,7 +290,7 @@ void CudaCalcNonbondedForceKernel::initialize(const System& system, const Nonbon
} }
CudaNonbondedMethod method = NO_CUTOFF; CudaNonbondedMethod method = NO_CUTOFF;
if (force.getNonbondedMethod() != NonbondedForce::NoCutoff) { if (force.getNonbondedMethod() != NonbondedForce::NoCutoff) {
gpuSetNonbondedCutoff(gpu, (float)force.getCutoffDistance(), 78.3f); gpuSetNonbondedCutoff(gpu, (float)force.getCutoffDistance(), force.getReactionFieldDielectric());
method = CUTOFF; method = CUTOFF;
} }
if (force.getNonbondedMethod() == NonbondedForce::CutoffPeriodic) { if (force.getNonbondedMethod() == NonbondedForce::CutoffPeriodic) {
......
...@@ -203,6 +203,8 @@ void testCutoff() { ...@@ -203,6 +203,8 @@ void testCutoff() {
forceField->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic); forceField->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
const double cutoff = 2.9; const double cutoff = 2.9;
forceField->setCutoffDistance(cutoff); forceField->setCutoffDistance(cutoff);
const double eps = 50.0;
forceField->setReactionFieldDielectric(eps);
system.addForce(forceField); system.addForce(forceField);
OpenMMContext context(system, integrator, platform); OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(3); vector<Vec3> positions(3);
...@@ -212,7 +214,6 @@ void testCutoff() { ...@@ -212,7 +214,6 @@ void testCutoff() {
context.setPositions(positions); context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy); State state = context.getState(State::Forces | State::Energy);
const vector<Vec3>& forces = state.getForces(); const vector<Vec3>& forces = state.getForces();
const double eps = 78.3;
const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0); const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0);
const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0); const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0);
const double force1 = 138.935485*(1.0)*(0.25-2.0*krf*2.0); const double force1 = 138.935485*(1.0)*(0.25-2.0*krf*2.0);
...@@ -237,6 +238,8 @@ void testCutoff14() { ...@@ -237,6 +238,8 @@ void testCutoff14() {
} }
const double cutoff = 3.5; const double cutoff = 3.5;
nonbonded->setCutoffDistance(cutoff); nonbonded->setCutoffDistance(cutoff);
const double eps = 30.0;
nonbonded->setReactionFieldDielectric(eps);
vector<pair<int, int> > bonds; vector<pair<int, int> > bonds;
bonds.push_back(pair<int, int>(0, 1)); bonds.push_back(pair<int, int>(0, 1));
bonds.push_back(pair<int, int>(1, 2)); bonds.push_back(pair<int, int>(1, 2));
...@@ -303,7 +306,6 @@ void testCutoff14() { ...@@ -303,7 +306,6 @@ void testCutoff14() {
context.setPositions(positions); context.setPositions(positions);
state = context.getState(State::Forces | State::Energy); state = context.getState(State::Forces | State::Energy);
const vector<Vec3>& forces2 = state.getForces(); const vector<Vec3>& forces2 = state.getForces();
const double eps = 78.3;
const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0); const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0);
const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0); const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0);
force = 138.935485*q*q*(1.0/(r*r)-2.0*krf*r); force = 138.935485*q*q*(1.0/(r*r)-2.0*krf*r);
......
...@@ -410,6 +410,7 @@ void ReferenceCalcNonbondedForceKernel::initialize(const System& system, const N ...@@ -410,6 +410,7 @@ void ReferenceCalcNonbondedForceKernel::initialize(const System& system, const N
if (kmax[2]%2 == 0) if (kmax[2]%2 == 0)
kmax[2]++; kmax[2]++;
} }
rfDielectric = force.getReactionFieldDielectric();
} }
void ReferenceCalcNonbondedForceKernel::executeForces(OpenMMContextImpl& context) { void ReferenceCalcNonbondedForceKernel::executeForces(OpenMMContextImpl& context) {
...@@ -421,7 +422,7 @@ void ReferenceCalcNonbondedForceKernel::executeForces(OpenMMContextImpl& context ...@@ -421,7 +422,7 @@ void ReferenceCalcNonbondedForceKernel::executeForces(OpenMMContextImpl& context
bool pme = (nonbondedMethod == PME); bool pme = (nonbondedMethod == PME);
if (nonbondedMethod != NoCutoff) { if (nonbondedMethod != NoCutoff) {
computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, (periodic || ewald || pme) ? periodicBoxSize : NULL, nonbondedCutoff, 0.0); computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, (periodic || ewald || pme) ? periodicBoxSize : NULL, nonbondedCutoff, 0.0);
clj.setUseCutoff(nonbondedCutoff, *neighborList, 78.3f); clj.setUseCutoff(nonbondedCutoff, *neighborList, rfDielectric);
} }
if (periodic||ewald||pme) if (periodic||ewald||pme)
clj.setPeriodic(periodicBoxSize); clj.setPeriodic(periodicBoxSize);
...@@ -433,7 +434,7 @@ void ReferenceCalcNonbondedForceKernel::executeForces(OpenMMContextImpl& context ...@@ -433,7 +434,7 @@ void ReferenceCalcNonbondedForceKernel::executeForces(OpenMMContextImpl& context
ReferenceBondForce refBondForce; ReferenceBondForce refBondForce;
ReferenceLJCoulomb14 nonbonded14; ReferenceLJCoulomb14 nonbonded14;
if (nonbondedMethod != NoCutoff) if (nonbondedMethod != NoCutoff)
nonbonded14.setUseCutoff(nonbondedCutoff, 78.3f); nonbonded14.setUseCutoff(nonbondedCutoff, rfDielectric);
refBondForce.calculateForce(num14, bonded14IndexArray, posData, bonded14ParamArray, forceData, 0, 0, 0, nonbonded14); refBondForce.calculateForce(num14, bonded14IndexArray, posData, bonded14ParamArray, forceData, 0, 0, 0, nonbonded14);
} }
...@@ -447,7 +448,7 @@ double ReferenceCalcNonbondedForceKernel::executeEnergy(OpenMMContextImpl& conte ...@@ -447,7 +448,7 @@ double ReferenceCalcNonbondedForceKernel::executeEnergy(OpenMMContextImpl& conte
bool pme = (nonbondedMethod == PME); bool pme = (nonbondedMethod == PME);
if (nonbondedMethod != NoCutoff) { if (nonbondedMethod != NoCutoff) {
computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, (periodic || ewald || pme) ? periodicBoxSize : NULL, nonbondedCutoff, 0.0); computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, (periodic || ewald || pme) ? periodicBoxSize : NULL, nonbondedCutoff, 0.0);
clj.setUseCutoff(nonbondedCutoff, *neighborList, 78.3f); clj.setUseCutoff(nonbondedCutoff, *neighborList, rfDielectric);
} }
if (periodic || ewald || pme) if (periodic || ewald || pme)
clj.setPeriodic(periodicBoxSize); clj.setPeriodic(periodicBoxSize);
...@@ -459,7 +460,7 @@ double ReferenceCalcNonbondedForceKernel::executeEnergy(OpenMMContextImpl& conte ...@@ -459,7 +460,7 @@ double ReferenceCalcNonbondedForceKernel::executeEnergy(OpenMMContextImpl& conte
ReferenceBondForce refBondForce; ReferenceBondForce refBondForce;
ReferenceLJCoulomb14 nonbonded14; ReferenceLJCoulomb14 nonbonded14;
if (nonbondedMethod != NoCutoff) if (nonbondedMethod != NoCutoff)
nonbonded14.setUseCutoff(nonbondedCutoff, 78.3f); nonbonded14.setUseCutoff(nonbondedCutoff, rfDielectric);
RealOpenMM* energyArray = new RealOpenMM[num14]; RealOpenMM* energyArray = new RealOpenMM[num14];
for (int i = 0; i < num14; ++i) for (int i = 0; i < num14; ++i)
energyArray[i] = 0; energyArray[i] = 0;
......
...@@ -267,7 +267,7 @@ private: ...@@ -267,7 +267,7 @@ private:
int numParticles, num14; int numParticles, num14;
int **exclusionArray, **bonded14IndexArray; int **exclusionArray, **bonded14IndexArray;
RealOpenMM **particleParamArray, **bonded14ParamArray; RealOpenMM **particleParamArray, **bonded14ParamArray;
RealOpenMM nonbondedCutoff, periodicBoxSize[3], ewaldAlpha; RealOpenMM nonbondedCutoff, periodicBoxSize[3], rfDielectric, ewaldAlpha;
int kmax[3]; int kmax[3];
std::vector<std::set<int> > exclusions; std::vector<std::set<int> > exclusions;
NonbondedMethod nonbondedMethod; NonbondedMethod nonbondedMethod;
......
...@@ -199,6 +199,8 @@ void testCutoff() { ...@@ -199,6 +199,8 @@ void testCutoff() {
forceField->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic); forceField->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
const double cutoff = 2.9; const double cutoff = 2.9;
forceField->setCutoffDistance(cutoff); forceField->setCutoffDistance(cutoff);
const double eps = 50.0;
forceField->setReactionFieldDielectric(eps);
system.addForce(forceField); system.addForce(forceField);
OpenMMContext context(system, integrator, platform); OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(3); vector<Vec3> positions(3);
...@@ -208,7 +210,6 @@ void testCutoff() { ...@@ -208,7 +210,6 @@ void testCutoff() {
context.setPositions(positions); context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy); State state = context.getState(State::Forces | State::Energy);
const vector<Vec3>& forces = state.getForces(); const vector<Vec3>& forces = state.getForces();
const double eps = 78.3;
const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0); const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0);
const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0); const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0);
const double force1 = 138.935485*(1.0)*(0.25-2.0*krf*2.0); const double force1 = 138.935485*(1.0)*(0.25-2.0*krf*2.0);
...@@ -233,6 +234,8 @@ void testCutoff14() { ...@@ -233,6 +234,8 @@ void testCutoff14() {
nonbonded->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic); nonbonded->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
const double cutoff = 3.5; const double cutoff = 3.5;
nonbonded->setCutoffDistance(cutoff); nonbonded->setCutoffDistance(cutoff);
const double eps = 30.0;
nonbonded->setReactionFieldDielectric(eps);
vector<pair<int, int> > bonds; vector<pair<int, int> > bonds;
bonds.push_back(pair<int, int>(0, 1)); bonds.push_back(pair<int, int>(0, 1));
bonds.push_back(pair<int, int>(1, 2)); bonds.push_back(pair<int, int>(1, 2));
...@@ -299,7 +302,6 @@ void testCutoff14() { ...@@ -299,7 +302,6 @@ void testCutoff14() {
context.setPositions(positions); context.setPositions(positions);
state = context.getState(State::Forces | State::Energy); state = context.getState(State::Forces | State::Energy);
const vector<Vec3>& forces2 = state.getForces(); const vector<Vec3>& forces2 = state.getForces();
const double eps = 78.3;
const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0); const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0);
const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0); const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0);
force = 138.935485*q*q*(1.0/(r*r)-2.0*krf*r); force = 138.935485*q*q*(1.0/(r*r)-2.0*krf*r);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment