Unverified Commit 61a908cd authored by Michael J. Schnieders's avatar Michael J. Schnieders Committed by GitHub
Browse files

Updates to AmoebaVdwForce, AmoebaGeneralizedKirkwoodForce and AmoebaWcaDispersionForce (#4647)

* Update the AMOEBA OpenMM API for vdW, GK and WCA

* Changes needed for the Corrigan et al Generalized Kirkwood model and minor changes to the vdW force to support CpHMD

* Add casts to real for uses of POW in GK; Pass force by reference within the WCA kernel

* Update swigInputConfig for Amoeba vdW and GK forces

* Update TestAPIUnits.testAmoebaVdwForce

* Set the units for getSolventDielectric and getSoluteDielectric to None

* Update default dispersion offset parameter for the AmoebaWcaDispersionForce

* Remove overloaded getParticleParameters and setParticleParameters from AmoebaGeneralizedKirkwoodForce

* Update the AmoebaWcaDispersionForce TestAPIUnits tests to reflect using the correct units for the C++ parameter default values; Update the alanine-dipeptide-amoeba-forces to reflect the updated GK model

* Move neck descreening constants into AmoebaGeneralizedKirkwoodForceImpl; set the default GK dielecticOffset to 0.09; set the default WCA shctd parameter to 0.82

* Fix Python test cases for WCA and GK

* Load AMOEBA/GK parameters into an array of float4

* Cleaned up the AmoebaGeneralizedKirkwoodForce based on feedback from Peter; the one case where backwards compatibility remains a challenge is application of the dielectric offset parameter - in the prior code this was only applied to the nonpolar cavity term, but not to calculation of Born radii; in this revision the dielectric offset is applied to BOTH the nonpolar cavity term and to calculation of Born radii. At this point I can't think of elegant way to maintain backwards compatibility that isn't confusing, nor does it make sense (at least to me) to only apply the concept of the dieletric offset to one aspect (i.e. only to nonpolar cavity or only to Born radii calculation) but not to both.

* Remove 'using std::vector' from AmoebaGeneralizedKirkwoodForceImpl.h; divide by 10 instead of multiplying by 0.1f in amoebaGk.cc

* Added a parameter called descreenOffset, which is applied during calculation of effective Born radii for GK. The parameter dielectricOffset is only used for the nonpolar cavity term consistent with its prior use. All tests in TestAmoebaGeneralizedKirkwoodForce.h are now backwards compatible with their behavior prior to this PR.

* Change two constants in amoebaGk.cc to single precision; Improved the documentation for getNeckConstants in AmoebaGeneralizedKirkwoodForceImpl.h

* Fix comment for setTanhRescaling in AmoebaGeneralizedKirkwoodForce.h, Fix comment for setTanhParameters in AmoebaReferenceGeneralizedKirkwoodForce.h; set the type of parameter GeneralizedKirkwoodTanhRescaling to bool in AmoebaGeneralizedKirkwoodForceProxy.cpp; In ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel return references of per particle parameters instead of copies; update AmoebaReferenceKernels.h method signatures for per particle parameters to return const vector references

* Minor tweaks to the documentation for the tanh rescaling flag

* Improve the comments for the get and setTanhParameters in AmoebaGeneralizedKirkwoodForce.h and AmoebaReferenceGeneralizedKirkwoodForce.h
parent 78c15368
...@@ -49,6 +49,7 @@ void AmoebaReferenceVdwForce::initialize(const AmoebaVdwForce& force) { ...@@ -49,6 +49,7 @@ void AmoebaReferenceVdwForce::initialize(const AmoebaVdwForce& force) {
int numParticles = force.getNumParticles(); int numParticles = force.getNumParticles();
indexIVs.resize(numParticles); indexIVs.resize(numParticles);
reductions.resize(numParticles); reductions.resize(numParticles);
scaleFactors.resize(numParticles);
isAlchemical.resize(numParticles); isAlchemical.resize(numParticles);
allExclusions.clear(); allExclusions.clear();
allExclusions.resize(numParticles); allExclusions.resize(numParticles);
...@@ -57,7 +58,7 @@ void AmoebaReferenceVdwForce::initialize(const AmoebaVdwForce& force) { ...@@ -57,7 +58,7 @@ void AmoebaReferenceVdwForce::initialize(const AmoebaVdwForce& force) {
double sigma, epsilon; double sigma, epsilon;
bool alchemical; bool alchemical;
vector<int> exclusions; vector<int> exclusions;
force.getParticleParameters(i, indexIVs[i], sigma, epsilon, reductions[i], alchemical, type); force.getParticleParameters(i, indexIVs[i], sigma, epsilon, reductions[i], alchemical, type, scaleFactors[i]);
isAlchemical[i] = alchemical; isAlchemical[i] = alchemical;
force.getParticleExclusions(i, exclusions); force.getParticleExclusions(i, exclusions);
for (unsigned int j = 0; j < exclusions.size(); j++) for (unsigned int j = 0; j < exclusions.size(); j++)
...@@ -224,6 +225,9 @@ double AmoebaReferenceVdwForce::calculateForceAndEnergy(int numParticles, double ...@@ -224,6 +225,9 @@ double AmoebaReferenceVdwForce::calculateForceAndEnergy(int numParticles, double
double combinedEpsilon = epsilonMatrix[particleType[ii]][particleType[jj]]; double combinedEpsilon = epsilonMatrix[particleType[ii]][particleType[jj]];
double softcore = 0.0; double softcore = 0.0;
// Apply per particle scale factors (for CpHMD).
combinedEpsilon *= scaleFactors[ii] * scaleFactors[jj];
if (this->_alchemicalMethod == AmoebaVdwForce::Decouple && (isAlchemicalI != isAlchemical[jj])) { if (this->_alchemicalMethod == AmoebaVdwForce::Decouple && (isAlchemicalI != isAlchemical[jj])) {
combinedEpsilon *= pow(lambda, this->_n); combinedEpsilon *= pow(lambda, this->_n);
softcore = this->_alpha * pow(1.0 - lambda, 2); softcore = this->_alpha * pow(1.0 - lambda, 2);
...@@ -287,6 +291,9 @@ double AmoebaReferenceVdwForce::calculateForceAndEnergy(int numParticles, double ...@@ -287,6 +291,9 @@ double AmoebaReferenceVdwForce::calculateForceAndEnergy(int numParticles, double
double combinedSigma = sigmaMatrix[particleType[siteI]][particleType[siteJ]]; double combinedSigma = sigmaMatrix[particleType[siteI]][particleType[siteJ]];
double combinedEpsilon = epsilonMatrix[particleType[siteI]][particleType[siteJ]]; double combinedEpsilon = epsilonMatrix[particleType[siteI]][particleType[siteJ]];
// Apply per particle scale factors (for CpHMD).
combinedEpsilon *= scaleFactors[siteI] * scaleFactors[siteJ];
double softcore = 0.0; double softcore = 0.0;
int isAlchemicalI = isAlchemical[siteI]; int isAlchemicalI = isAlchemical[siteI];
int isAlchemicalJ = isAlchemical[siteJ]; int isAlchemicalJ = isAlchemical[siteJ];
......
...@@ -135,6 +135,7 @@ private: ...@@ -135,6 +135,7 @@ private:
std::vector<std::vector<double> > epsilonMatrix; std::vector<std::vector<double> > epsilonMatrix;
std::vector<int> indexIVs; std::vector<int> indexIVs;
std::vector<double> reductions; std::vector<double> reductions;
std::vector<double> scaleFactors;
std::vector<bool> isAlchemical; std::vector<bool> isAlchemical;
std::vector<std::set<int> > allExclusions; std::vector<std::set<int> > allExclusions;
Vec3 _periodicBoxVectors[3]; Vec3 _periodicBoxVectors[3];
......
...@@ -23,8 +23,9 @@ ...@@ -23,8 +23,9 @@
*/ */
#ifdef WIN32 #ifdef WIN32
#define _USE_MATH_DEFINES // Needed to get M_PI #define _USE_MATH_DEFINES // Needed to get M_PI
#endif #endif
#include "AmoebaReferenceForce.h" #include "AmoebaReferenceForce.h"
#include "AmoebaReferenceWcaDispersionForce.h" #include "AmoebaReferenceWcaDispersionForce.h"
#include <cmath> #include <cmath>
...@@ -32,280 +33,240 @@ ...@@ -32,280 +33,240 @@
using std::vector; using std::vector;
using namespace OpenMM; using namespace OpenMM;
AmoebaReferenceWcaDispersionForce::AmoebaReferenceWcaDispersionForce(double epso, double epsh, double rmino, double rminh, AmoebaReferenceWcaDispersionForce::AmoebaReferenceWcaDispersionForce(double epso, double epsh, double rmino,
double awater, double shctd, double dispoff, double slevy) : double rminh, double awater, double shctd,
_epso(epso), _epsh(epsh), _rmino(rmino), _rminh(rminh), _awater(awater), _shctd(shctd), _dispoff(dispoff), _slevy(slevy) { double dispoff, double slevy) :
} _epso(epso), _epsh(epsh), _rmino(rmino), _rminh(rminh), _awater(awater), _shctd(shctd), _dispoff(dispoff),
_slevy(slevy) {
}
double AmoebaReferenceWcaDispersionForce::calculatePairIxn(double radiusI, double radiusK,
const Vec3& particleIPosition,
const Vec3& particleJPosition,
const double* const intermediateValues,
Vec3& force) const {
static const double PI = M_PI;
double xr = particleIPosition[0] - particleJPosition[0];
double yr = particleIPosition[1] - particleJPosition[1];
double zr = particleIPosition[2] - particleJPosition[2];
double r2 = xr*xr + yr*yr + zr*zr;
double r = sqrt(r2);
double r3 = r2*r;
double sK = radiusK*_shctd;
double sK2 = sK*sK;
double rmixo = intermediateValues[RMIXO];
double rmixo7 = intermediateValues[RMIXO7];
double emixo = intermediateValues[EMIXO];
double rmixh = intermediateValues[RMIXH];
double rmixh7 = intermediateValues[RMIXH7];
double emixh = intermediateValues[EMIXH];
double ao = intermediateValues[AO];
double ah = intermediateValues[AH];
double sum = 0.0;
double de = 0.0;
if (radiusI < (r + sK)) {
double rmax = (radiusI > (r - sK)) ? radiusI : (r - sK);
double lik = rmax;
double lik2 = lik*lik;
double lik3 = lik2*lik;
double lik4 = lik2*lik2;
if (lik < rmixo) { static double integralBeforeRMin(double eps, double r, double r2, double sk2,
double lik2, double lik3, double lik4,
double uik2, double uik3, double uik4) {
return -eps * (4.0e0 * M_PI / (48.0e0 * r) *
(3.0e0 * (lik4 - uik4) - 8.0e0 * r * (lik3 - uik3) + 6.0e0 * (r2 - sk2) * (lik2 - uik2)));
}
double uik = (r + sK) < rmixo ? (r + sK) : rmixo; static double
double uik2 = uik*uik; integralBeforeRminDerivative(double ri, double eps, double rmin, double r, double r2, double r3, double sk, double sk2,
double uik3 = uik2*uik; double lik, double lik2, double lik3, double uik, double uik2, double uik3) {
double uik4 = uik2*uik2; double dl;
if (ri > r - sk) {
dl = (-lik2 + 2.0 * r2 + 2.0 * sk2) * lik2;
} else {
dl = (-lik3 + 4.0 * lik2 * r - 6.0 * lik * r2 + 2.0 * lik * sk2 + 4.0 * r3 - 4.0 * r * sk2) * lik;
}
double du;
if (r + sk > rmin) {
du = -(-uik2 + 2.0 * r2 + 2.0 * sk2) * uik2;
} else {
du = -(-uik3 + 4.0 * uik2 * r - 6.0 * uik * r2 + 2.0 * uik * sk2 + 4.0 * r3 - 4.0 * r * sk2) * uik;
}
return -eps * M_PI * (dl + du) / (4.0 * r2);
}
double term = 4.0*PI/(48.0*r)* (3.0*(lik4-uik4) - 8.0*r*(lik3-uik3) + 6.0*(r2-sK2)*(lik2-uik2)); static double integralAfterRmin(double eps, double rmin7, double r, double r2, double sk2,
double lik, double lik2, double lik3, double lik4, double lik5, double lik10,
double lik11, double lik12, double uik, double uik2, double uik3, double uik4,
double uik5, double uik10, double uik11, double uik12) {
double er7 = eps * rmin7;
double term = 4.0 * M_PI / (120.0 * r * lik5 * uik5)
* (15.0 * uik * lik * r * (uik4 - lik4)
- 10.0 * uik2 * lik2 * (uik3 - lik3)
+ 6.0 * (sk2 - r2) * (uik5 - lik5));
double term2 = 4.0 * M_PI / (2640.0 * r * lik12 * uik12)
* (120.0 * uik * lik * r * (uik11 - lik11)
- 66.0 * uik2 * lik2 * (uik10 - lik10)
+ 55.0 * (sk2 - r2) * (uik12 - lik12));
double idisp = -2.0 * er7 * term;
double irep = er7 * rmin7 * term2;
return irep + idisp;
}
double dl; static double integralAfterRminDerivative(double ri, double eps, double rmin, double rmin7, double rmax,
if (radiusI > (r - sK)) { double r, double r2, double r3, double sk, double sk2, double lik,
dl = -lik2 + 2.0*(r2 + sK2); double lik2, double lik3, double lik5, double lik6, double lik12,
dl *= lik2; double lik13, double uik, double uik2, double uik3, double uik6,
} else { double uik13) {
dl = -lik3 + 4.0*lik2*r - 6.0*lik*r2 + 2.0*lik*sK2 + 4.0*r*(r2 - sK2); double er7 = eps * rmin7;
dl *= lik; double lowerTerm = lik2 * r + r3 - r * sk2;
} double upperTerm = uik2 * r + r3 - r * sk2;
double dl;
if (ri > r - sk || rmax < rmin) {
dl = -(-5.0 * lik2 + 3.0 * r2 + 3.0 * sk2) / lik5;
} else {
dl = (5.0 * lik3 - 33.0 * lik * r2 - 3.0 * lik * sk2 + 15.0 * lowerTerm) / lik6;
}
double du = -(5.0 * uik3 - 33.0 * uik * r2 - 3.0 * uik * sk2 + 15.0 * upperTerm) / uik6;
double de = -2.0 * M_PI * er7 * (dl + du) / (15.0 * r2);
double du; if (ri > r - sk || rmax < rmin) {
if ((r+sK) > rmixo) { dl = -(-6.0 * lik2 + 5.0 * r2 + 5.0 * sk2) / lik12;
du = -uik2 + 2.0*(r2 + sK2); } else {
du *= -uik2; dl = (6.0 * lik3 - 125.0 * lik * r2 - 5.0 * lik * sk2 + 60.0 * lowerTerm) / lik13;
} else { }
du = -uik3 + 4.0*uik2*r - 6.0*uik*r2 + 2.0*uik*sK2 + 4.0*r*(r2 - sK2); du = -(6.0 * uik3 - 125.0 * uik * r2 - 5.0 * uik * sk2 + 60.0 * upperTerm) / uik13;
du *= -uik; de += M_PI * er7 * rmin7 * (dl + du) / (60.0 * r2);
}
de = -emixo*PI*(dl+du)/(4.0*r2);
sum += -emixo*term;
}
if (lik < rmixh) { return de;
}
double uik = (r + sK) < rmixh ? (r + sK) : rmixh;
double uik2 = uik*uik;
double uik3 = uik2*uik;
double uik4 = uik2*uik2;
double term = 4.0*PI / (48.0*r)*(3.0*(lik4-uik4) - 8.0*r*(lik3-uik3) + 6.0*(r2-sK2)*(lik2-uik2));
double dl;
if (radiusI > (r-sK)) {
dl = -lik2 + 2.0*(r2 + sK2);
dl *= lik2;
} else {
dl = -lik3 + 4.0*lik2*r - 6.0*lik*r2 + 2.0*lik*sK2 + 4.0*r*(r2 -sK2);
dl *= lik;
}
double du;
if (r+sK > rmixh) {
du = -uik2 + 2.0*(r2 + sK2);
du *= -uik2;
} else {
du = -uik3 +4.0*uik2*r - 6.0*uik*r2 + 2.0*uik*sK2 +4.0*r*(r2 - sK2);
du *= -uik;
}
de -= 2.0*emixh*PI*(dl+du)/(4.0*r2);
sum -= 2.0*emixh*term;
}
double uik = r + sK; static double interact(double factor, double ri, double sk, double rmix, double emix,
double uik2 = uik * uik; double r, double r2, double r3, Vec3 &force) {
double uik3 = uik2 * uik; double sum = 0.0;
double uik4 = uik2 * uik2; // Nothing to do if the integral begins beyond r + sk (i.e. atom k does not exclude solvent)
double uik5 = uik3 * uik2; if (ri < r + sk) {
double uik6 = uik3 * uik3; // Zero out the derivative contribution of atom k.
double uik10 = uik5 * uik5; double de = 0.0;
double uik11 = uik5 * uik6; double sk2 = sk * sk;
double uik12 = uik6 * uik6; // Compute the maximum of 1) the beginning of the integral and 2) closest edge of atom K.
double uik13 = uik10 * uik3; double iStart = ri > r - sk ? ri : r - sk;
// Use this as the lower limit for integrating the constant eps value below Rmin.
if (uik > rmixo) { double lik = iStart;
// Interaction with water from lik to Rmin; nothing to do if the lower limit is greater than Rmin.
double lik = rmax > rmixo ? rmax : rmixo; if (lik < rmix) {
double lik2 = lik * lik; double lik2 = lik * lik;
double lik3 = lik2 * lik; double lik3 = lik2 * lik;
double lik4 = lik2 * lik2; double lik4 = lik3 * lik;
double lik5 = lik2 * lik3; // Upper limit is the minimum of Rmin and the farthest edge of atom K.
double lik6 = lik3 * lik3; double uik = r + sk < rmix ? r + sk : rmix;
double lik10 = lik5 * lik5; double uik2 = uik * uik;
double lik11 = lik5 * lik6; double uik3 = uik2 * uik;
double lik12 = lik6 * lik6; double uik4 = uik3 * uik;
double lik13 = lik10 * lik3; sum = integralBeforeRMin(emix, r, r2, sk2, lik2, lik3, lik4, uik2, uik3, uik4);
de = integralBeforeRminDerivative(ri, emix, rmix, r, r2, r3, sk, sk2, lik, lik2, lik3, uik, uik2, uik3);
double term = 4.0*PI/(120.0*r*lik5*uik5)*(15.0*uik*lik*r*(uik4-lik4) - 10.0*uik2*lik2*(uik3-lik3) + 6.0*(sK2-r2)*(uik5-lik5));
double dl;
if (radiusI > (r-sK) || rmax < rmixo) {
dl = -5.0*lik2 + 3.0*(r2 + sK2);
dl /= -lik5;
} else {
dl = 5.0*lik3 - 33.0*lik*r2 - 3.0*lik*sK2 + 15.0*(lik2*r+r3-r*sK2);
dl /= lik6;
}
double du = 5.0*uik3 - 33.0*uik*r2 - 3.0*uik*sK2 + 15.0*(uik2*r+r3-r*sK2);
du /= -uik6;
double idisp = -2.0*ao*term;
de -= 2.0*ao*PI*(dl + du)/(15.0*r2);
term = 4.0*PI/(2640.0*r*lik12*uik12) * (120.0*uik*lik*r*(uik11-lik11) - 66.0*uik2*lik2*(uik10-lik10) + 55.0*(sK2-r2)*(uik12-lik12));
if (radiusI > (r-sK) || rmax < rmixo) {
dl = -6.0*lik2 + 5.0*r2 + 5.0*sK2;
dl /= -lik12;
} else {
dl = 6.0*lik3 - 125.0*lik*r2 - 5.0*lik*sK2 + 60.0*(lik2*r+r3-r*sK2);
dl /= lik13;
}
du = 6.0*uik3 - 125.0*uik*r2 - 5.0*uik*sK2 + 60.0*(uik2*r+r3-r*sK2);
du /= -uik13;
de += ao*rmixo7*PI*(dl + du)/(60.0*r2);
sum += ao*rmixo7*term + idisp;
} }
if (uik > rmixh) { // Upper limit the variable part of Uwca always the farthest edge of atom K.
lik = rmax > rmixh ? rmax : rmixh; double uik = r + sk;
lik2 = lik * lik; // Interaction with water beyond Rmin, from lik to uik = r + sk.
lik3 = lik2 * lik; if (uik > rmix) {
lik4 = lik2 * lik2; // Start the integral at the max of 1) iStart and 2) Rmin.
double lik5 = lik2 * lik3; lik = iStart > rmix ? iStart : rmix;
double lik6 = lik3 * lik3; double lik2 = lik * lik;
double lik3 = lik2 * lik;
double lik4 = lik3 * lik;
double lik5 = lik4 * lik;
double lik6 = lik5 * lik;
double lik10 = lik5 * lik5; double lik10 = lik5 * lik5;
double lik11 = lik5 * lik6; double lik11 = lik10 * lik;
double lik12 = lik6 * lik6; double lik12 = lik11 * lik;
double lik13 = lik3 * lik10; double uik2 = uik * uik;
double uik3 = uik2 * uik;
double term = 4.0*PI / (120.0*r*lik5*uik5)*(15.0*uik*lik*r*(uik4-lik4) - 10.0*uik2*lik2*(uik3-lik3) + 6.0*(sK2-r2)*(uik5-lik5)); double uik4 = uik3 * uik;
double dl; double uik5 = uik4 * uik;
if (radiusI > (r-sK) || rmax < rmixh) { double uik10 = uik5 * uik5;
dl = -5.0*lik2 + 3.0*(r2 + sK2); double uik11 = uik10 * uik;
dl /= -lik5; double uik12 = uik11 * uik;
} else { double rmix3 = rmix * rmix * rmix;
dl = 5.0*lik3 - 33.0*lik*r2 - 3.0*lik*sK2 + 15.0*(lik2*r+r3-r*sK2); double rmix7 = rmix3 * rmix3 * rmix;
dl /= lik6; sum += integralAfterRmin(emix, rmix7, r, r2, sk2, lik, lik2, lik3, lik4, lik5, lik10, lik11, lik12, uik,
} uik2, uik3, uik4, uik5, uik10, uik11, uik12);
double du = 5.0*uik3 - 33.0*uik*r2 - 3.0*uik*sK2 + 15.0*(uik2*r+r3-r*sK2); double lik13 = lik12 * lik;
du /= -uik6; double uik6 = uik5 * uik;
double idisp = -4.0*ah*term; double uik13 = uik12 * uik;
de = de - 4.0*ah*PI*(dl + du)/(15.0*r2); de += integralAfterRminDerivative(ri, emix, rmix, rmix7, iStart, r, r2, r3, sk, sk2, lik, lik2, lik3,
term = 4.0*PI / (2640.0*r*lik12*uik12)* (120.0*uik*lik*r*(uik11-lik11)- 66.0*uik2*lik2*(uik10-lik10)+ 55.0*(sK2-r2)*(uik12-lik12)); lik5, lik6, lik12, lik13, uik, uik2, uik3, uik6, uik13);
if (radiusI > (r-sK) || rmax < rmixh) {
dl = -6.0*lik2 + 5.0*r2 + 5.0*sK2;
dl = -dl / lik12;
} else {;
dl = 6.0*lik3 - 125.0*lik*r2 - 5.0*lik*sK2 + 60.0*(lik2*r+r3-r*sK2);
dl = dl / lik13;
}
du = 6.0*uik3 - 125.0*uik*r2 - 5.0*uik*sK2 + 60.0*(uik2*r+r3-r*sK2);
du /= -uik13;
double irep = 2.0*ah*rmixh7*term;
de += ah*rmixh7*PI*(dl+du)/(30.0*r2);
sum += irep + idisp;
} }
// Increment the individual dispersion gradient components.
de *= factor / r;
force[0] += de;
force[1] += de;
force[2] += de;
} }
return factor * sum;
}
// increment the individual dispersion gradient components double AmoebaReferenceWcaDispersionForce::calculatePairIxn(double radiusJ,
const Vec3 &particleIPosition,
de *= (_slevy*_awater)/r; const Vec3 &particleJPosition,
const double *const intermediateValues,
force[0] = de*xr; Vec3 &force) const {
force[1] = de*yr; // Atomic separation
force[2] = de*zr; double xr = particleIPosition[0] - particleJPosition[0];
double yr = particleIPosition[1] - particleJPosition[1];
double zr = particleIPosition[2] - particleJPosition[2];
double r2 = xr * xr + yr * yr + zr * zr;
double r = sqrt(r2);
double r3 = r2 * r;
// Parameters for atom i with water oxygen.
double rmixo = intermediateValues[RMIXO];
double emixo = intermediateValues[EMIXO];
// Parameters for atom i with water hydrogen.
double rmixh = intermediateValues[RMIXH];
double emixh = intermediateValues[EMIXH];
// Start of integration of dispersion for atom i with water oxygen.
double riO = rmixo / 2.0e0 + _dispoff;
double nO = 1.0e0;
// Start of integration of dispersion for atom i with water hydrogen.
double riH = rmixh / 2.0e0 + _dispoff;
double nH = 2.0e0;
// Atom k blocks the interaction of atom i with solvent.
double sJ = radiusJ * _shctd;
double sum = interact(nO, riO, sJ, rmixo, emixo, r, r2, r3, force) +
interact(nH, riH, sJ, rmixh, emixh, r, r2, r3, force);
force[0] *= xr;
force[1] *= yr;
force[2] *= zr;
return sum; return sum;
} }
double AmoebaReferenceWcaDispersionForce::calculateForceAndEnergy(int numParticles, double AmoebaReferenceWcaDispersionForce::calculateForceAndEnergy(int numParticles,
const vector<Vec3>& particlePositions, const vector<Vec3> &particlePositions,
const std::vector<double>& radii, const std::vector<double> &radii,
const std::vector<double>& epsilons, const std::vector<double> &epsilons,
double totalMaximumDispersionEnergy, double totalMaximumDispersionEnergy,
vector<Vec3>& forces) const { vector<Vec3> &forces) const {
double energy = 0.0;
// loop over all ixns double rmino2 = _rmino * _rmino;
double rmino3 = rmino2 * _rmino;
double energy = 0.0; double rminh2 = _rminh * _rminh;
double rminh3 = rminh2 * _rminh;
double rmino2 = _rmino*_rmino;
double rmino3 = rmino2*_rmino;
double rminh2 = _rminh*_rminh;
double rminh3 = rminh2*_rminh;
double intermediateValues[LastIntermediateValueIndex]; double intermediateValues[LastIntermediateValueIndex];
// loop over all ixns
for (unsigned int ii = 0; ii < static_cast<unsigned int>(numParticles); ii++) { for (unsigned int ii = 0; ii < static_cast<unsigned int>(numParticles); ii++) {
double epsi = epsilons[ii];
double rmini = radii[ii];
double denominator = sqrt(_epso) + sqrt(epsi);
double emixo = 4.0*_epso*epsi/(denominator*denominator);
intermediateValues[EMIXO] = emixo;
double rminI2 = rmini*rmini;
double rminI3 = rminI2*rmini;
double rmixo = 2.0*(rmino3 + rminI3) / (rmino2 + rminI2);
intermediateValues[RMIXO] = rmixo;
double rmixo7 = rmixo*rmixo*rmixo; double epsi = epsilons[ii];
rmixo7 = rmixo7*rmixo7*rmixo; double rmini = radii[ii];
intermediateValues[RMIXO7] = rmixo7; double rminI2 = rmini * rmini;
double rminI3 = rminI2 * rmini;
intermediateValues[AO] = emixo*rmixo7; double denominator = sqrt(_epso) + sqrt(epsi);
double emixo = 4.0 * _epso * epsi / (denominator * denominator);
intermediateValues[EMIXO] = emixo;
denominator = sqrt(_epsh) + sqrt(epsi); double rmixo = 2.0 * (rmino3 + rminI3) / (rmino2 + rminI2);
intermediateValues[RMIXO] = rmixo;
double emixh = 4.0*_epsh*epsi/ (denominator*denominator); denominator = sqrt(_epsh) + sqrt(epsi);
double emixh = 4.0 * _epsh * epsi / (denominator * denominator);
intermediateValues[EMIXH] = emixh; intermediateValues[EMIXH] = emixh;
double rmixh = 2.0 * (rminh3 + rminI3) / (rminh2 + rminI2); double rmixh = 2.0 * (rminh3 + rminI3) / (rminh2 + rminI2);
intermediateValues[RMIXH] = rmixh; intermediateValues[RMIXH] = rmixh;
double rmixh7 = rmixh*rmixh*rmixh; // Remove dispersion for atom i by atom j.
rmixh7 = rmixh7*rmixh7*rmixh;
intermediateValues[RMIXH7] = rmixh7;
intermediateValues[AH] = emixh*rmixh7;
for (unsigned int jj = 0; jj < static_cast<unsigned int>(numParticles); jj++) { for (unsigned int jj = 0; jj < static_cast<unsigned int>(numParticles); jj++) {
if (ii == jj)continue; if (ii == jj) continue;
Vec3 force; Vec3 force = Vec3();
energy += calculatePairIxn(rmini, radii[jj], energy += calculatePairIxn(radii[jj], particlePositions[ii], particlePositions[jj],
particlePositions[ii], particlePositions[jj],
intermediateValues, force); intermediateValues, force);
force[0] *= _slevy * _awater;
force[1] *= _slevy * _awater;
force[2] *= _slevy * _awater;
forces[ii][0] += force[0]; forces[ii][0] += force[0];
forces[ii][1] += force[1]; forces[ii][1] += force[1];
forces[ii][2] += force[2]; forces[ii][2] += force[2];
...@@ -313,11 +274,12 @@ double AmoebaReferenceWcaDispersionForce::calculateForceAndEnergy(int numParticl ...@@ -313,11 +274,12 @@ double AmoebaReferenceWcaDispersionForce::calculateForceAndEnergy(int numParticl
forces[jj][0] -= force[0]; forces[jj][0] -= force[0];
forces[jj][1] -= force[1]; forces[jj][1] -= force[1];
forces[jj][2] -= force[2]; forces[jj][2] -= force[2];
} }
} }
energy = totalMaximumDispersionEnergy - _slevy*_awater*energy; energy = totalMaximumDispersionEnergy - _slevy * _awater * energy;
return energy; return energy;
} }
...@@ -91,13 +91,12 @@ private: ...@@ -91,13 +91,12 @@ private:
double _dispoff; double _dispoff;
double _slevy; double _slevy;
enum { EMIXO, RMIXO, RMIXO7, AO, EMIXH, RMIXH, RMIXH7, AH, LastIntermediateValueIndex }; enum { EMIXO, RMIXO, EMIXH, RMIXH, LastIntermediateValueIndex };
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Calculate pair ixn Calculate pair ixn
@param radiusI radius of particle I
@param radiusJ radius of particle J @param radiusJ radius of particle J
@param particleIPosition particle I position @param particleIPosition particle I position
@param particleJPosition particle J position @param particleJPosition particle J position
...@@ -108,7 +107,7 @@ private: ...@@ -108,7 +107,7 @@ private:
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
double calculatePairIxn(double radiusI, double radiusJ, double calculatePairIxn(double radiusJ,
const OpenMM::Vec3& particleIPosition, const OpenMM::Vec3& particleJPosition, const OpenMM::Vec3& particleIPosition, const OpenMM::Vec3& particleJPosition,
const double* const intermediateValues, const double* const intermediateValues,
Vec3& force) const; Vec3& force) const;
......
...@@ -42,46 +42,70 @@ AmoebaGeneralizedKirkwoodForceProxy::AmoebaGeneralizedKirkwoodForceProxy() : Ser ...@@ -42,46 +42,70 @@ AmoebaGeneralizedKirkwoodForceProxy::AmoebaGeneralizedKirkwoodForceProxy() : Ser
} }
void AmoebaGeneralizedKirkwoodForceProxy::serialize(const void* object, SerializationNode& node) const { void AmoebaGeneralizedKirkwoodForceProxy::serialize(const void* object, SerializationNode& node) const {
node.setIntProperty("version", 2); node.setIntProperty("version", 3);
const AmoebaGeneralizedKirkwoodForce& force = *reinterpret_cast<const AmoebaGeneralizedKirkwoodForce*>(object); const AmoebaGeneralizedKirkwoodForce& force = *reinterpret_cast<const AmoebaGeneralizedKirkwoodForce*>(object);
node.setIntProperty("forceGroup", force.getForceGroup()); node.setIntProperty("forceGroup", force.getForceGroup());
node.setStringProperty("name", force.getName()); node.setStringProperty("name", force.getName());
node.setDoubleProperty("GeneralizedKirkwoodSolventDielectric", force.getSolventDielectric()); node.setDoubleProperty("GeneralizedKirkwoodSolventDielectric", force.getSolventDielectric());
node.setDoubleProperty("GeneralizedKirkwoodSoluteDielectric", force.getSoluteDielectric()); node.setDoubleProperty("GeneralizedKirkwoodSoluteDielectric", force.getSoluteDielectric());
//node.setDoubleProperty("GeneralizedKirkwoodDielectricOffset", force.getDielectricOffset()); node.setDoubleProperty("GeneralizedKirkwoodDielectricOffset", force.getDielectricOffset());
node.setDoubleProperty("GeneralizedKirkwoodProbeRadius", force.getProbeRadius()); node.setDoubleProperty("GeneralizedKirkwoodProbeRadius", force.getProbeRadius());
node.setDoubleProperty("GeneralizedKirkwoodSurfaceAreaFactor", force.getSurfaceAreaFactor()); node.setDoubleProperty("GeneralizedKirkwoodSurfaceAreaFactor", force.getSurfaceAreaFactor());
node.setIntProperty( "GeneralizedKirkwoodIncludeCavityTerm", force.getIncludeCavityTerm()); node.setIntProperty( "GeneralizedKirkwoodIncludeCavityTerm", force.getIncludeCavityTerm());
node.setBoolProperty("GeneralizedKirkwoodTanhRescaling", force.getTanhRescaling());
double b0, b1, b2;
force.getTanhParameters(b0, b1, b2);
node.setDoubleProperty("GeneralizedKirkwoodTanhB0", b0);
node.setDoubleProperty("GeneralizedKirkwoodTanhB1", b1);
node.setDoubleProperty("GeneralizedKirkwoodTanhB2", b2);
node.setDoubleProperty("GeneralizedKirkwoodDescreenOffset", force.getDescreenOffset());
SerializationNode& particles = node.createChildNode("GeneralizedKirkwoodParticles"); SerializationNode& particles = node.createChildNode("GeneralizedKirkwoodParticles");
for (unsigned int ii = 0; ii < static_cast<unsigned int>(force.getNumParticles()); ii++) { for (unsigned int ii = 0; ii < static_cast<unsigned int>(force.getNumParticles()); ii++) {
double radius, charge, scalingFactor; double radius, charge, scalingFactor, descreenRadius, neckFactor;
force.getParticleParameters(ii, charge, radius, scalingFactor); force.getParticleParameters(ii, charge, radius, scalingFactor, descreenRadius, neckFactor);
particles.createChildNode("Particle").setDoubleProperty("charge", charge).setDoubleProperty("radius", radius).setDoubleProperty("scaleFactor", scalingFactor); particles.createChildNode("Particle").setDoubleProperty("charge", charge).setDoubleProperty("radius", radius).setDoubleProperty("scaleFactor", scalingFactor).setDoubleProperty("descreenRadius", descreenRadius).setDoubleProperty("neckFactor", neckFactor);
} }
} }
void* AmoebaGeneralizedKirkwoodForceProxy::deserialize(const SerializationNode& node) const { void* AmoebaGeneralizedKirkwoodForceProxy::deserialize(const SerializationNode& node) const {
int version = node.getIntProperty("version"); int version = node.getIntProperty("version");
if (version < 1 || version > 2) if (version < 1 || version > 3)
throw OpenMMException("Unsupported version number"); throw OpenMMException("Unsupported version number");
AmoebaGeneralizedKirkwoodForce* force = new AmoebaGeneralizedKirkwoodForce(); AmoebaGeneralizedKirkwoodForce* force = new AmoebaGeneralizedKirkwoodForce();
try { try {
force->setForceGroup(node.getIntProperty("forceGroup", 0)); force->setForceGroup(node.getIntProperty("forceGroup", 0));
force->setName(node.getStringProperty("name", force->getName())); force->setName(node.getStringProperty("name", force->getName()));
force->setSolventDielectric( node.getDoubleProperty("GeneralizedKirkwoodSolventDielectric")); force->setSolventDielectric(node.getDoubleProperty("GeneralizedKirkwoodSolventDielectric"));
force->setSoluteDielectric( node.getDoubleProperty("GeneralizedKirkwoodSoluteDielectric")); force->setSoluteDielectric(node.getDoubleProperty("GeneralizedKirkwoodSoluteDielectric"));
//force->setDielectricOffset( node.getDoubleProperty("GeneralizedKirkwoodDielectricOffset")); force->setProbeRadius(node.getDoubleProperty("GeneralizedKirkwoodProbeRadius"));
force->setProbeRadius( node.getDoubleProperty("GeneralizedKirkwoodProbeRadius")); force->setSurfaceAreaFactor(node.getDoubleProperty("GeneralizedKirkwoodSurfaceAreaFactor"));
force->setSurfaceAreaFactor( node.getDoubleProperty("GeneralizedKirkwoodSurfaceAreaFactor")); force->setIncludeCavityTerm(node.getIntProperty("GeneralizedKirkwoodIncludeCavityTerm"));
force->setIncludeCavityTerm( node.getIntProperty( "GeneralizedKirkwoodIncludeCavityTerm")); if (version > 2) {
force->setDielectricOffset(node.getDoubleProperty("GeneralizedKirkwoodDielectricOffset"));
force->setTanhRescaling(node.getBoolProperty("GeneralizedKirkwoodTanhRescaling"));
double b0 = node.getDoubleProperty("GeneralizedKirkwoodTanhB0");
double b1 = node.getDoubleProperty("GeneralizedKirkwoodTanhB1");
double b2 = node.getDoubleProperty("GeneralizedKirkwoodTanhB2");
force->setTanhParameters(b0, b1, b2);
force->setDescreenOffset(node.getDoubleProperty("GeneralizedKirkwoodDescreenOffset"));
}
const SerializationNode& particles = node.getChildNode("GeneralizedKirkwoodParticles"); const SerializationNode& particles = node.getChildNode("GeneralizedKirkwoodParticles");
for (unsigned int ii = 0; ii < particles.getChildren().size(); ii++) { for (unsigned int ii = 0; ii < particles.getChildren().size(); ii++) {
const SerializationNode& particle = particles.getChildren()[ii]; const SerializationNode& particle = particles.getChildren()[ii];
force->addParticle(particle.getDoubleProperty("charge"), particle.getDoubleProperty("radius"), particle.getDoubleProperty("scaleFactor")); double charge = particle.getDoubleProperty("charge");
double radius = particle.getDoubleProperty("radius");
double scaleFactor = particle.getDoubleProperty("scaleFactor");
double descreenRadius = radius;
double neckFactor = 0.0;
if (version > 2) {
descreenRadius = particle.getDoubleProperty("descreenRadius");
neckFactor = particle.getDoubleProperty("neckFactor");
}
force->addParticle(charge, radius, scaleFactor, descreenRadius, neckFactor);
} }
} }
catch (...) { catch (...) {
......
...@@ -42,7 +42,7 @@ AmoebaVdwForceProxy::AmoebaVdwForceProxy() : SerializationProxy("AmoebaVdwForce" ...@@ -42,7 +42,7 @@ AmoebaVdwForceProxy::AmoebaVdwForceProxy() : SerializationProxy("AmoebaVdwForce"
} }
void AmoebaVdwForceProxy::serialize(const void* object, SerializationNode& node) const { void AmoebaVdwForceProxy::serialize(const void* object, SerializationNode& node) const {
node.setIntProperty("version", 4); node.setIntProperty("version", 5);
const AmoebaVdwForce& force = *reinterpret_cast<const AmoebaVdwForce*>(object); const AmoebaVdwForce& force = *reinterpret_cast<const AmoebaVdwForce*>(object);
bool useTypes = force.getUseParticleTypes(); bool useTypes = force.getUseParticleTypes();
...@@ -62,14 +62,14 @@ void AmoebaVdwForceProxy::serialize(const void* object, SerializationNode& node) ...@@ -62,14 +62,14 @@ void AmoebaVdwForceProxy::serialize(const void* object, SerializationNode& node)
SerializationNode& particles = node.createChildNode("VdwParticles"); SerializationNode& particles = node.createChildNode("VdwParticles");
for (int i = 0; i < force.getNumParticles(); i++) { for (int i = 0; i < force.getNumParticles(); i++) {
int ivIndex, typeIndex; int ivIndex, typeIndex;
double sigma, epsilon, reductionFactor; double sigma, epsilon, reductionFactor, scaleFactor;
bool isAlchemical; bool isAlchemical;
force.getParticleParameters(i, ivIndex, sigma, epsilon, reductionFactor, isAlchemical, typeIndex); force.getParticleParameters(i, ivIndex, sigma, epsilon, reductionFactor, isAlchemical, typeIndex, scaleFactor);
SerializationNode& particle = particles.createChildNode("Particle"); SerializationNode& particle = particles.createChildNode("Particle");
if (useTypes) if (useTypes)
particle.setIntProperty("ivIndex", ivIndex).setIntProperty("type", typeIndex).setDoubleProperty("reductionFactor", reductionFactor).setBoolProperty("isAlchemical", isAlchemical); particle.setIntProperty("ivIndex", ivIndex).setIntProperty("type", typeIndex).setDoubleProperty("reductionFactor", reductionFactor).setBoolProperty("isAlchemical", isAlchemical).setDoubleProperty("scaleFactor", scaleFactor);
else else
particle.setIntProperty("ivIndex", ivIndex).setDoubleProperty("sigma", sigma).setDoubleProperty("epsilon", epsilon).setDoubleProperty("reductionFactor", reductionFactor).setBoolProperty("isAlchemical", isAlchemical); particle.setIntProperty("ivIndex", ivIndex).setDoubleProperty("sigma", sigma).setDoubleProperty("epsilon", epsilon).setDoubleProperty("reductionFactor", reductionFactor).setBoolProperty("isAlchemical", isAlchemical).setDoubleProperty("scaleFactor", scaleFactor);
std::vector< int > exclusions; std::vector< int > exclusions;
force.getParticleExclusions(i, exclusions); force.getParticleExclusions(i, exclusions);
...@@ -98,7 +98,7 @@ void AmoebaVdwForceProxy::serialize(const void* object, SerializationNode& node) ...@@ -98,7 +98,7 @@ void AmoebaVdwForceProxy::serialize(const void* object, SerializationNode& node)
void* AmoebaVdwForceProxy::deserialize(const SerializationNode& node) const { void* AmoebaVdwForceProxy::deserialize(const SerializationNode& node) const {
int version = node.getIntProperty("version"); int version = node.getIntProperty("version");
if (version < 1 || version > 4) if (version < 1 || version > 5)
throw OpenMMException("Unsupported version number"); throw OpenMMException("Unsupported version number");
AmoebaVdwForce* force = new AmoebaVdwForce(); AmoebaVdwForce* force = new AmoebaVdwForce();
try { try {
...@@ -128,16 +128,30 @@ void* AmoebaVdwForceProxy::deserialize(const SerializationNode& node) const { ...@@ -128,16 +128,30 @@ void* AmoebaVdwForceProxy::deserialize(const SerializationNode& node) const {
if (version < 3) if (version < 3)
force->addParticle(particle.getIntProperty("ivIndex"), particle.getDoubleProperty("sigma"), force->addParticle(particle.getIntProperty("ivIndex"), particle.getDoubleProperty("sigma"),
particle.getDoubleProperty("epsilon"), particle.getDoubleProperty("reductionFactor")); particle.getDoubleProperty("epsilon"), particle.getDoubleProperty("reductionFactor"));
else if (useTypes) else if (version == 4) {
force->addParticle(particle.getIntProperty("ivIndex"), particle.getIntProperty("type"), if (useTypes)
particle.getDoubleProperty("reductionFactor"), particle.getBoolProperty("isAlchemical")); force->addParticle(particle.getIntProperty("ivIndex"), particle.getIntProperty("type"),
else particle.getDoubleProperty("reductionFactor"),
force->addParticle(particle.getIntProperty("ivIndex"), particle.getDoubleProperty("sigma"), particle.getBoolProperty("isAlchemical"));
particle.getDoubleProperty("epsilon"), particle.getDoubleProperty("reductionFactor"), else
particle.getBoolProperty("isAlchemical")); force->addParticle(particle.getIntProperty("ivIndex"), particle.getDoubleProperty("sigma"),
particle.getDoubleProperty("epsilon"),
particle.getDoubleProperty("reductionFactor"),
particle.getBoolProperty("isAlchemical"));
} else {
// Version 5 includes per particle scale factor for CpHMD.
if (useTypes)
force->addParticle(particle.getIntProperty("ivIndex"), particle.getIntProperty("type"),
particle.getDoubleProperty("reductionFactor"),
particle.getBoolProperty("isAlchemical"), particle.getDoubleProperty("scaleFactor"));
else
force->addParticle(particle.getIntProperty("ivIndex"), particle.getDoubleProperty("sigma"),
particle.getDoubleProperty("epsilon"),
particle.getDoubleProperty("reductionFactor"),
particle.getBoolProperty("isAlchemical"), particle.getDoubleProperty("scaleFactor"));
}
// exclusions // exclusions
const SerializationNode& particleExclusions = particle.getChildNode("ParticleExclusions"); const SerializationNode& particleExclusions = particle.getChildNode("ParticleExclusions");
std::vector<int> exclusions; std::vector<int> exclusions;
for (int j = 0; j < particleExclusions.getChildren().size(); j++) for (int j = 0; j < particleExclusions.getChildren().size(); j++)
......
...@@ -47,46 +47,48 @@ void testSerialization() { ...@@ -47,46 +47,48 @@ void testSerialization() {
AmoebaGeneralizedKirkwoodForce force1; AmoebaGeneralizedKirkwoodForce force1;
force1.setForceGroup(3); force1.setForceGroup(3);
force1.setName("custom name"); force1.setName("custom name");
force1.setSolventDielectric( 80.0); force1.setSolventDielectric(80.0);
force1.setSoluteDielectric( 1.0); force1.setSoluteDielectric(1.0);
//force1.setDielectricOffset( 0.09); force1.setDielectricOffset( 0.09);
force1.setProbeRadius( 1.40); force1.setProbeRadius(1.40);
force1.setSurfaceAreaFactor( 0.888); force1.setSurfaceAreaFactor(0.888);
force1.setIncludeCavityTerm( 1); force1.setIncludeCavityTerm(1);
force1.setTanhRescaling(0);
force1.addParticle(1.0, 2.0, 0.9); force1.addParticle(1.0, 2.0, 0.9, 2.0, 0.0);
force1.addParticle(-1.1,2.1, 0.8); force1.addParticle(-1.1, 2.1, 0.8, 2.1, 0.0);
force1.addParticle(0.1, 2.2, 0.7); force1.addParticle(0.1, 2.2, 0.7, 2.2, 0.0);
// Serialize and then deserialize it. // Serialize and then deserialize it.
stringstream buffer; stringstream buffer;
XmlSerializer::serialize<AmoebaGeneralizedKirkwoodForce>(&force1, "Force", buffer); XmlSerializer::serialize<AmoebaGeneralizedKirkwoodForce>(&force1, "Force", buffer);
AmoebaGeneralizedKirkwoodForce* copy = XmlSerializer::deserialize<AmoebaGeneralizedKirkwoodForce>(buffer); AmoebaGeneralizedKirkwoodForce *copy = XmlSerializer::deserialize<AmoebaGeneralizedKirkwoodForce>(buffer);
// Compare the two forces to see if they are identical. // Compare the two forces to see if they are identical.
AmoebaGeneralizedKirkwoodForce& force2 = *copy; AmoebaGeneralizedKirkwoodForce &force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup()); ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getName(), force2.getName()); ASSERT_EQUAL(force1.getName(), force2.getName());
ASSERT_EQUAL(force1.getSolventDielectric(), force2.getSolventDielectric()); ASSERT_EQUAL(force1.getSolventDielectric(), force2.getSolventDielectric());
ASSERT_EQUAL(force1.getSoluteDielectric(), force2.getSoluteDielectric()); ASSERT_EQUAL(force1.getSoluteDielectric(), force2.getSoluteDielectric());
//ASSERT_EQUAL(force1.getDielectricOffset(), force2.getDielectricOffset()); ASSERT_EQUAL(force1.getDielectricOffset(), force2.getDielectricOffset());
ASSERT_EQUAL(force1.getProbeRadius(), force2.getProbeRadius()); ASSERT_EQUAL(force1.getProbeRadius(), force2.getProbeRadius());
ASSERT_EQUAL(force1.getSurfaceAreaFactor(), force2.getSurfaceAreaFactor()); ASSERT_EQUAL(force1.getSurfaceAreaFactor(), force2.getSurfaceAreaFactor());
ASSERT_EQUAL(force1.getIncludeCavityTerm(), force2.getIncludeCavityTerm()); ASSERT_EQUAL(force1.getIncludeCavityTerm(), force2.getIncludeCavityTerm());
ASSERT_EQUAL(force1.getNumParticles(), force2.getNumParticles()); ASSERT_EQUAL(force1.getNumParticles(), force2.getNumParticles());
for (unsigned int ii = 0; ii < static_cast<unsigned int>(force1.getNumParticles()); ii++) { for (unsigned int ii = 0; ii < static_cast<unsigned int>(force1.getNumParticles()); ii++) {
double radius1, charge1, scaleFactor1; double radius1, charge1, scaleFactor1, descreen1, neckFactor1;
double radius2, charge2, scaleFactor2; double radius2, charge2, scaleFactor2, descreen2, neckFactor2;
force1.getParticleParameters(ii, charge1, radius1, scaleFactor1); force1.getParticleParameters(ii, charge1, radius1, scaleFactor1, descreen1, neckFactor1);
force2.getParticleParameters(ii, charge2, radius2, scaleFactor2); force2.getParticleParameters(ii, charge2, radius2, scaleFactor2, descreen2, neckFactor2);
ASSERT_EQUAL(charge1, charge2); ASSERT_EQUAL(charge1, charge2)
ASSERT_EQUAL(radius1, radius2); ASSERT_EQUAL(radius1, radius2)
ASSERT_EQUAL(scaleFactor1, scaleFactor2); ASSERT_EQUAL(scaleFactor1, scaleFactor2)
ASSERT_EQUAL(descreen1, descreen2)
} }
} }
...@@ -95,7 +97,7 @@ int main() { ...@@ -95,7 +97,7 @@ int main() {
registerAmoebaSerializationProxies(); registerAmoebaSerializationProxies();
testSerialization(); testSerialization();
} }
catch(const exception& e) { catch (const exception &e) {
cout << "exception: " << e.what() << endl; cout << "exception: " << e.what() << endl;
return 1; return 1;
} }
......
...@@ -54,9 +54,9 @@ void testSerialization() { ...@@ -54,9 +54,9 @@ void testSerialization() {
force1.setAlchemicalMethod(AmoebaVdwForce::None); force1.setAlchemicalMethod(AmoebaVdwForce::None);
force1.setPotentialFunction(AmoebaVdwForce::Buffered147); force1.setPotentialFunction(AmoebaVdwForce::Buffered147);
force1.addParticle(0, 1.0, 2.0, 0.9, false); force1.addParticle(0, 1.0, 2.0, 0.9, false, 1.0);
force1.addParticle(1, 1.1, 2.1, 0.9, true); force1.addParticle(1, 1.1, 2.1, 0.9, true, 0.9);
force1.addParticle(2, 1.3, 4.1, 0.9, false); force1.addParticle(2, 1.3, 4.1, 0.9, false, 1.0);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
std::vector< int > exclusions; std::vector< int > exclusions;
exclusions.push_back(i); exclusions.push_back(i);
...@@ -90,14 +90,14 @@ void testSerialization() { ...@@ -90,14 +90,14 @@ void testSerialization() {
int ivIndex1, type1; int ivIndex1, type1;
int ivIndex2, type2; int ivIndex2, type2;
double sigma1, epsilon1, reductionFactor1; double sigma1, epsilon1, reductionFactor1, scaleFactor1;
double sigma2, epsilon2, reductionFactor2; double sigma2, epsilon2, reductionFactor2, scaleFactor2;
bool isAlchemical1; bool isAlchemical1;
bool isAlchemical2; bool isAlchemical2;
force1.getParticleParameters(i, ivIndex1, sigma1, epsilon1, reductionFactor1, isAlchemical1, type1); force1.getParticleParameters(i, ivIndex1, sigma1, epsilon1, reductionFactor1, isAlchemical1, type1, scaleFactor1);
force2.getParticleParameters(i, ivIndex2, sigma2, epsilon2, reductionFactor2, isAlchemical2, type2); force2.getParticleParameters(i, ivIndex2, sigma2, epsilon2, reductionFactor2, isAlchemical2, type2, scaleFactor2);
ASSERT_EQUAL(ivIndex1, ivIndex2); ASSERT_EQUAL(ivIndex1, ivIndex2);
ASSERT_EQUAL(sigma1, sigma2); ASSERT_EQUAL(sigma1, sigma2);
...@@ -105,6 +105,7 @@ void testSerialization() { ...@@ -105,6 +105,7 @@ void testSerialization() {
ASSERT_EQUAL(reductionFactor1, reductionFactor2); ASSERT_EQUAL(reductionFactor1, reductionFactor2);
ASSERT_EQUAL(isAlchemical1, isAlchemical2); ASSERT_EQUAL(isAlchemical1, isAlchemical2);
ASSERT_EQUAL(type1, type2); ASSERT_EQUAL(type1, type2);
ASSERT_EQUAL(scaleFactor1, scaleFactor2);
} }
for (int i = 0; i < force1.getNumParticles(); i++) { for (int i = 0; i < force1.getNumParticles(); i++) {
...@@ -131,10 +132,10 @@ void testSerializeTypes() { ...@@ -131,10 +132,10 @@ void testSerializeTypes() {
AmoebaVdwForce force1; AmoebaVdwForce force1;
force1.setPotentialFunction(AmoebaVdwForce::LennardJones); force1.setPotentialFunction(AmoebaVdwForce::LennardJones);
force1.addParticle(0, 2, 1.0, false); force1.addParticle(0, 2, 1.0, false, 1.0);
force1.addParticle(1, 2, 0.9, true); force1.addParticle(1, 2, 0.9, true, 0.0);
force1.addParticle(2, 0, 1.0, false); force1.addParticle(2, 0, 1.0, false, 0.5);
force1.addParticle(3, 1, 0.9, false); force1.addParticle(3, 1, 0.9, false, 0.9);
force1.addParticleType(1.1, 2.0); force1.addParticleType(1.1, 2.0);
force1.addParticleType(1.2, 2.1); force1.addParticleType(1.2, 2.1);
force1.addParticleType(1.3, 2.2); force1.addParticleType(1.3, 2.2);
...@@ -158,14 +159,14 @@ void testSerializeTypes() { ...@@ -158,14 +159,14 @@ void testSerializeTypes() {
int ivIndex1, type1; int ivIndex1, type1;
int ivIndex2, type2; int ivIndex2, type2;
double sigma1, epsilon1, reductionFactor1; double sigma1, epsilon1, reductionFactor1, scaleFactor1;
double sigma2, epsilon2, reductionFactor2; double sigma2, epsilon2, reductionFactor2, scaleFactor2;
bool isAlchemical1; bool isAlchemical1;
bool isAlchemical2; bool isAlchemical2;
force1.getParticleParameters(i, ivIndex1, sigma1, epsilon1, reductionFactor1, isAlchemical1, type1); force1.getParticleParameters(i, ivIndex1, sigma1, epsilon1, reductionFactor1, isAlchemical1, type1, scaleFactor1);
force2.getParticleParameters(i, ivIndex2, sigma2, epsilon2, reductionFactor2, isAlchemical2, type2); force2.getParticleParameters(i, ivIndex2, sigma2, epsilon2, reductionFactor2, isAlchemical2, type2, scaleFactor2);
ASSERT_EQUAL(ivIndex1, ivIndex2); ASSERT_EQUAL(ivIndex1, ivIndex2);
ASSERT_EQUAL(sigma1, sigma2); ASSERT_EQUAL(sigma1, sigma2);
...@@ -173,6 +174,7 @@ void testSerializeTypes() { ...@@ -173,6 +174,7 @@ void testSerializeTypes() {
ASSERT_EQUAL(reductionFactor1, reductionFactor2); ASSERT_EQUAL(reductionFactor1, reductionFactor2);
ASSERT_EQUAL(isAlchemical1, isAlchemical2); ASSERT_EQUAL(isAlchemical1, isAlchemical2);
ASSERT_EQUAL(type1, type2); ASSERT_EQUAL(type1, type2);
ASSERT_EQUAL(scaleFactor1, scaleFactor2);
} }
for (int i = 0; i < force1.getNumParticleTypes(); i++) { for (int i = 0; i < force1.getNumParticleTypes(); i++) {
double sigma1, epsilon1; double sigma1, epsilon1;
......
...@@ -289,10 +289,10 @@ static void setupMultipoleAmmonia(System& system, AmoebaGeneralizedKirkwoodForce ...@@ -289,10 +289,10 @@ static void setupMultipoleAmmonia(System& system, AmoebaGeneralizedKirkwoodForce
// addParticle: charge, radius, scalingFactor // addParticle: charge, radius, scalingFactor
   
for (unsigned int ii = 0; ii < 2; ii++) { for (unsigned int ii = 0; ii < 2; ii++) {
amoebaGeneralizedKirkwoodForce->addParticle( -5.7960000e-01, 1.5965000e-01, 6.9000000e-01); amoebaGeneralizedKirkwoodForce->addParticle( -5.7960000e-01, 1.5965000e-01, 6.9000000e-01, 1.5965000e-01, 0.0f);
amoebaGeneralizedKirkwoodForce->addParticle( 1.9320000e-01, 1.2360000e-01, 6.9000000e-01); amoebaGeneralizedKirkwoodForce->addParticle( 1.9320000e-01, 1.2360000e-01, 6.9000000e-01, 1.2360000e-01, 0.0f);
amoebaGeneralizedKirkwoodForce->addParticle( 1.9320000e-01, 1.2360000e-01, 6.9000000e-01); amoebaGeneralizedKirkwoodForce->addParticle( 1.9320000e-01, 1.2360000e-01, 6.9000000e-01, 1.2360000e-01, 0.0f);
amoebaGeneralizedKirkwoodForce->addParticle( 1.9320000e-01, 1.2360000e-01, 6.9000000e-01); amoebaGeneralizedKirkwoodForce->addParticle( 1.9320000e-01, 1.2360000e-01, 6.9000000e-01, 1.2360000e-01, 0.0f);
} }
system.addForce(amoebaGeneralizedKirkwoodForce); system.addForce(amoebaGeneralizedKirkwoodForce);
} }
...@@ -7167,9 +7167,9 @@ static void testGeneralizedKirkwoodAmmoniaMutualPolarizationWithCavityTerm() { ...@@ -7167,9 +7167,9 @@ static void testGeneralizedKirkwoodAmmoniaMutualPolarizationWithCavityTerm() {
// Try changing the particle parameters and make sure it's still correct. // Try changing the particle parameters and make sure it's still correct.
for (int i = 0; i < numberOfParticles; i++) { for (int i = 0; i < numberOfParticles; i++) {
double charge, radius, scale; double charge, radius, scale, descreenRadius, neckscale;
amoebaGeneralizedKirkwoodForce->getParticleParameters(i, charge, radius, scale); amoebaGeneralizedKirkwoodForce->getParticleParameters(i, charge, radius, scale, descreenRadius, neckscale);
amoebaGeneralizedKirkwoodForce->setParticleParameters(i, charge, 0.9*radius, 1.1*scale); amoebaGeneralizedKirkwoodForce->setParticleParameters(i, charge, 0.9*radius, 1.1*scale, 1.2*descreenRadius, 1.3*neckscale);
} }
LangevinIntegrator integrator2(0.0, 0.1, 0.01); LangevinIntegrator integrator2(0.0, 0.1, 0.01);
Context context2(system, integrator2, context.getPlatform()); Context context2(system, integrator2, context.getPlatform());
......
...@@ -133,12 +133,12 @@ void testVdw() { ...@@ -133,12 +133,12 @@ void testVdw() {
} }
for (int ii = 0; ii < amoebaVdwForce->getNumParticles(); ii++) { for (int ii = 0; ii < amoebaVdwForce->getNumParticles(); ii++) {
int indexIV, type; int indexIV, type;
double sigma, epsilon, reduction; double sigma, epsilon, reduction, scaleFactor;
bool isAlchemical; bool isAlchemical;
amoebaVdwForce->getParticleParameters(ii, indexIV, sigma, epsilon, reduction, isAlchemical, type); amoebaVdwForce->getParticleParameters(ii, indexIV, sigma, epsilon, reduction, isAlchemical, type, scaleFactor);
sigma *= AngstromToNm; sigma *= AngstromToNm;
epsilon *= CalToJoule; epsilon *= CalToJoule;
amoebaVdwForce->setParticleParameters(ii, indexIV, sigma, epsilon, reduction, isAlchemical, type); amoebaVdwForce->setParticleParameters(ii, indexIV, sigma, epsilon, reduction, isAlchemical, type, scaleFactor);
} }
Context context(system, integrator, platform); Context context(system, integrator, platform);
...@@ -163,10 +163,10 @@ void testVdw() { ...@@ -163,10 +163,10 @@ void testVdw() {
for (int i = 0; i < numberOfParticles; i++) { for (int i = 0; i < numberOfParticles; i++) {
int indexIV, type; int indexIV, type;
double mass, sigma, epsilon, reduction; double mass, sigma, epsilon, reduction, scaleFactor;
bool isAlchemical; bool isAlchemical;
amoebaVdwForce->getParticleParameters(i, indexIV, sigma, epsilon, reduction, isAlchemical, type); amoebaVdwForce->getParticleParameters(i, indexIV, sigma, epsilon, reduction, isAlchemical, type, scaleFactor);
amoebaVdwForce->setParticleParameters(i, indexIV, 0.9*sigma, 2.0*epsilon, 0.95*reduction, isAlchemical, type); amoebaVdwForce->setParticleParameters(i, indexIV, 0.9*sigma, 2.0*epsilon, 0.95*reduction, isAlchemical, type, scaleFactor);
} }
LangevinIntegrator integrator2(0.0, 0.1, 0.01); LangevinIntegrator integrator2(0.0, 0.1, 0.01);
Context context2(system, integrator2, platform); Context context2(system, integrator2, platform);
......
...@@ -42,103 +42,122 @@ ...@@ -42,103 +42,122 @@
#define ASSERT_EQUAL_TOL_MOD(expected, found, tol, testname) {double _scale_ = std::abs(expected) > 1.0 ? std::abs(expected) : 1.0; if (!(std::abs((expected)-(found))/_scale_ <= (tol))) {std::stringstream details; details << testname << " Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}}; #define ASSERT_EQUAL_TOL_MOD(expected, found, tol, testname) {double _scale_ = std::abs(expected) > 1.0 ? std::abs(expected) : 1.0; if (!(std::abs((expected)-(found))/_scale_ <= (tol))) {std::stringstream details; details << testname << " Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_EQUAL_VEC_MOD(expected, found, tol,testname) {ASSERT_EQUAL_TOL_MOD((expected)[0], (found)[0], (tol),(testname)); ASSERT_EQUAL_TOL_MOD((expected)[1], (found)[1], (tol),(testname)); ASSERT_EQUAL_TOL_MOD((expected)[2], (found)[2], (tol),(testname));}; #define ASSERT_EQUAL_VEC_MOD(expected, found, tol, testname) {ASSERT_EQUAL_TOL_MOD((expected)[0], (found)[0], (tol),(testname)); ASSERT_EQUAL_TOL_MOD((expected)[1], (found)[1], (tol),(testname)); ASSERT_EQUAL_TOL_MOD((expected)[2], (found)[2], (tol),(testname));};
using namespace OpenMM; using namespace OpenMM;
const double TOL = 1e-4; const double TOL = 1e-4;
void compareForcesEnergy(std::string& testName, double expectedEnergy, double energy, void compareForcesEnergy(std::string &testName, double expectedEnergy, double energy,
const std::vector<Vec3>& expectedForces, const std::vector<Vec3> &expectedForces,
const std::vector<Vec3>& forces, double tolerance) { const std::vector<Vec3> &forces, double tolerance) {
for (unsigned int ii = 0; ii < forces.size(); ii++) { for (unsigned int ii = 0; ii < forces.size(); ii++) {
ASSERT_EQUAL_VEC_MOD(expectedForces[ii], forces[ii], tolerance, testName); ASSERT_EQUAL_VEC_MOD(expectedForces[ii], forces[ii], tolerance, testName)
} }
ASSERT_EQUAL_TOL_MOD(expectedEnergy, energy, tolerance, testName); ASSERT_EQUAL_TOL_MOD(expectedEnergy, energy, tolerance, testName)
} }
// test Wca dispersion // Test Wca Dispersion
void testWcaDispersionAmmonia() { void testWcaDispersionAmmonia() {
std::string testName = "testWcaDispersionAmmonia"; std::string testName = "testWcaDispersionAmmonia";
int numberOfParticles = 8;
int numberOfParticles = 8;
// Create the system. // Create the system.
System system; System system;
AmoebaWcaDispersionForce* amoebaWcaDispersionForce = new AmoebaWcaDispersionForce();; AmoebaWcaDispersionForce *amoebaWcaDispersionForce = new AmoebaWcaDispersionForce();
// Convert kcal/mol to kJ/mol
double epso = 0.1100e0 * 4.184e0;
double epsh = 0.0135e0 * 4.184e0;
// Convert A to nm.
double rmino = 1.7025e-01;
double rminh = 1.3275e-01;
double dispoff = 1.056e-01;
// Convert water number density from water / A^3 to water / nm^3.
double awater = 0.033428e03;
// No units.
double slevy = 1.0e0;
double shctd = 0.75e0;
amoebaWcaDispersionForce->setEpso(epso);
amoebaWcaDispersionForce->setEpsh(epsh);
amoebaWcaDispersionForce->setRmino(rmino);
amoebaWcaDispersionForce->setRminh(rminh);
amoebaWcaDispersionForce->setDispoff(dispoff);
amoebaWcaDispersionForce->setAwater(awater);
amoebaWcaDispersionForce->setSlevy(slevy);
amoebaWcaDispersionForce->setShctd(shctd);
// Amoeba 2009
// vdwtype BUFFERED-14-7
// radiusrule CUBIC-MEAN
// radiustype R-MIN
// radiussize DIAMETER
// epsilonrule HHG
// vdw 45 3.710000000 0.105000000
// vdw 46 2.700000000 0.020000000 0.910
amoebaWcaDispersionForce->setEpso( 4.6024000e-01); for (unsigned int ii = 0; ii < 2; ii++) {
amoebaWcaDispersionForce->setEpsh( 5.6484000e-02); system.addParticle(1.4007000e+01);
amoebaWcaDispersionForce->setRmino( 1.7025000e-01); amoebaWcaDispersionForce->addParticle(3.71e-01 / 2.0e0, 0.105e0 * 4.184e0);
amoebaWcaDispersionForce->setRminh( 1.3275000e-01);
amoebaWcaDispersionForce->setDispoff(2.6000000e-02);
amoebaWcaDispersionForce->setAwater( 3.3428000e+01);
amoebaWcaDispersionForce->setSlevy( 1.0000000e+00);
amoebaWcaDispersionForce->setShctd( 8.1000000e-01);
// addParticle: radius, epsilon system.addParticle(1.0080000e+00);
amoebaWcaDispersionForce->addParticle(2.7e-01 / 2.0e0, 0.02e0 * 4.184e0);
for (unsigned int ii = 0; ii < 2; ii++) { system.addParticle(1.0080000e+00);
system.addParticle( 1.4007000e+01); amoebaWcaDispersionForce->addParticle(2.7e-01 / 2.0e0, 0.02e0 * 4.184e0);
amoebaWcaDispersionForce->addParticle( 1.8550000e-01, 4.3932000e-01);
system.addParticle(1.0080000e+00);
system.addParticle( 1.0080000e+00); amoebaWcaDispersionForce->addParticle(2.7e-01 / 2.0e0, 0.02e0 * 4.184e0);
amoebaWcaDispersionForce->addParticle( 1.3500000e-01, 8.3680000e-02);
system.addParticle( 1.0080000e+00);
amoebaWcaDispersionForce->addParticle( 1.3500000e-01, 8.3680000e-02);
system.addParticle( 1.0080000e+00);
amoebaWcaDispersionForce->addParticle( 1.3500000e-01, 8.3680000e-02);
} }
std::vector<Vec3> positions(numberOfParticles); std::vector<Vec3> positions(numberOfParticles);
positions[0] = Vec3( 1.5927280e-01, 1.7000000e-06, 1.6491000e-03); positions[0] = Vec3(1.57493055e-01, 0.00085545e-01, 0.12707740e-01);
positions[1] = Vec3( 2.0805540e-01, -8.1258800e-02, 3.7282500e-02); positions[1] = Vec3(1.94285651e-01, -0.81095826e-01, 0.60622179e-01);
positions[2] = Vec3( 2.0843610e-01, 8.0953200e-02, 3.7462200e-02); positions[2] = Vec3(1.95030610e-01, 0.80808023e-01, 0.60809749e-01);
positions[3] = Vec3( 1.7280780e-01, 2.0730000e-04, -9.8741700e-02); positions[3] = Vec3(1.99309092e-01, -0.00015413e-01, -0.79434283e-01);
positions[4] = Vec3( -1.6743680e-01, 1.5900000e-05, -6.6149000e-03); positions[4] = Vec3(-1.65212994e-01, 0.02174061e-01, -0.04650966e-01);
positions[5] = Vec3( -2.0428260e-01, 8.1071500e-02, 4.1343900e-02); positions[5] = Vec3(-1.97210029e-01, 0.82501943e-01, 0.47898953e-01);
positions[6] = Vec3( -6.7308300e-02, 1.2800000e-05, 1.0623300e-02); positions[6] = Vec3(-0.64164714e-01, 0.01492667e-01, 0.03495515e-01);
positions[7] = Vec3( -2.0426290e-01, -8.1231400e-02, 4.1033500e-02); positions[7] = Vec3(-1.98070588e-01, -0.79434787e-01, 0.45336787e-01);
system.addForce(amoebaWcaDispersionForce); system.addForce(amoebaWcaDispersionForce);
ASSERT(!amoebaWcaDispersionForce->usesPeriodicBoundaryConditions());
ASSERT(!system.usesPeriodicBoundaryConditions());
LangevinIntegrator integrator(0.0, 0.1, 0.01); LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, platform); Context context(system, integrator, platform);
context.setPositions(positions); context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy); State state = context.getState(State::Forces | State::Energy);
std::vector<Vec3> forces = state.getForces(); const std::vector<Vec3> &forces = state.getForces();
double energy = state.getPotentialEnergy(); double energy = state.getPotentialEnergy();
// TINKER-computed values // Force Field X / Tinker expected energy -5.55412658 * 4.184 and forces.
double expectedEnergy = -5.55412658 * 4.184;
std::vector<Vec3> expectedForces(numberOfParticles); std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = -2.6981209e+01;
expectedForces[0] = Vec3(-0.33370779, 0.00478895, -0.18780836);
expectedForces[0] = Vec3( 4.7839388e+00, -7.3510133e-04, -5.0382764e-01); expectedForces[1] = Vec3(1.15078615, 0.07363123, -0.04881103);
expectedForces[1] = Vec3( 1.4657758e+00, 1.2431003e+00, -6.7075886e-01); expectedForces[2] = Vec3(1.14509754, -0.08727205, -0.05086123);
expectedForces[2] = Vec3( 1.4563936e+00, -1.2399917e+00, -6.7443841e-01); expectedForces[3] = Vec3(0.97122614, -0.00473535, 0.09417216);
expectedForces[3] = Vec3( 2.1116744e+00, -2.7407512e-03, 1.3271245e+00); expectedForces[4] = Vec3(-1.64874538, 0.01074006, -0.08477238);
expectedForces[4] = Vec3( -4.7528440e+00, -1.5148066e-03, 1.2653813e+00); expectedForces[5] = Vec3(-1.28585908, 0.00494013, 0.05864744);
expectedForces[5] = Vec3( -1.1875619e+00, -1.2866678e+00, -3.9109060e-01); expectedForces[6] = Vec3(1.28677671, -0.00915430, 0.16081161);
expectedForces[6] = Vec3( -2.6885679e+00, -4.3038639e-04, 3.3763583e-02); expectedForces[7] = Vec3(-1.28557430, 0.00706132, 0.05862179);
expectedForces[7] = Vec3( -1.1888087e+00, 1.2889802e+00, -3.8615387e-01);
double tolerance = 1.0e-04;
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance); compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
// Try changing the particle parameters and make sure it's still correct. // Try changing the particle parameters and make sure it's still correct.
for (int i = 0; i < numberOfParticles; i++) { for (int i = 0; i < numberOfParticles; i++) {
double radius, epsilon; double radius, epsilon;
amoebaWcaDispersionForce->getParticleParameters(i, radius, epsilon); amoebaWcaDispersionForce->getParticleParameters(i, radius, epsilon);
amoebaWcaDispersionForce->setParticleParameters(i, 0.9*radius, 2.0*epsilon); amoebaWcaDispersionForce->setParticleParameters(i, 0.9 * radius, 2.0 * epsilon);
} }
LangevinIntegrator integrator2(0.0, 0.1, 0.01); LangevinIntegrator integrator2(0.0, 0.1, 0.01);
Context context2(system, integrator2, platform); Context context2(system, integrator2, platform);
...@@ -148,7 +167,8 @@ void testWcaDispersionAmmonia() { ...@@ -148,7 +167,8 @@ void testWcaDispersionAmmonia() {
bool exceptionThrown = false; bool exceptionThrown = false;
try { try {
// This should throw an exception. // This should throw an exception.
compareForcesEnergy(testName, state1.getPotentialEnergy(), state2.getPotentialEnergy(), state1.getForces(), state2.getForces(), tolerance); compareForcesEnergy(testName, state1.getPotentialEnergy(), state2.getPotentialEnergy(), state1.getForces(),
state2.getForces(), tolerance);
} }
catch (std::exception ex) { catch (std::exception ex) {
exceptionThrown = true; exceptionThrown = true;
...@@ -156,7 +176,8 @@ void testWcaDispersionAmmonia() { ...@@ -156,7 +176,8 @@ void testWcaDispersionAmmonia() {
ASSERT(exceptionThrown); ASSERT(exceptionThrown);
amoebaWcaDispersionForce->updateParametersInContext(context); amoebaWcaDispersionForce->updateParametersInContext(context);
state1 = context.getState(State::Forces | State::Energy); state1 = context.getState(State::Forces | State::Energy);
compareForcesEnergy(testName, state1.getPotentialEnergy(), state2.getPotentialEnergy(), state1.getForces(), state2.getForces(), tolerance); compareForcesEnergy(testName, state1.getPotentialEnergy(), state2.getPotentialEnergy(), state1.getForces(),
state2.getForces(), tolerance);
} }
void setupKernels(int argc, char* argv[]); void setupKernels(int argc, char* argv[]);
......
...@@ -240,12 +240,18 @@ UNITS = { ...@@ -240,12 +240,18 @@ UNITS = {
("SerializationProxy", "getTypeName") : (None, ()), ("SerializationProxy", "getTypeName") : (None, ()),
# check getSurfaceAreaFactor # check getSurfaceAreaFactor
("AmoebaGeneralizedKirkwoodForce", "getParticleParameters") : (None, ('unit.elementary_charge', 'unit.nanometer', None)), ("AmoebaGeneralizedKirkwoodForce", "getParticleParameters") : (None, ('unit.elementary_charge', 'unit.nanometer', None, 'unit.nanometer', None)),
("AmoebaGeneralizedKirkwoodForce", "getDielectricOffset") : ( 'unit.nanometer', ()), ("AmoebaGeneralizedKirkwoodForce", "getDielectricOffset") : ( 'unit.nanometer', ()),
("AmoebaGeneralizedKirkwoodForce", "getSolventDielectric") : (None, ()),
("AmoebaGeneralizedKirkwoodForce", "getSoluteDielectric") : (None, ()),
("AmoebaGeneralizedKirkwoodForce", "getIncludeCavityTerm") : ( None,()), ("AmoebaGeneralizedKirkwoodForce", "getIncludeCavityTerm") : ( None,()),
("AmoebaGeneralizedKirkwoodForce", "getTanhRescaling") : ( None,()),
("AmoebaGeneralizedKirkwoodForce", "getTanhParameters") : ( None,(None, None, None)),
("AmoebaGeneralizedKirkwoodForce", "getDescreenOffset") : ( 'unit.nanometer', ()),
("AmoebaGeneralizedKirkwoodForce", "getProbeRadius") : ( 'unit.nanometer', ()), ("AmoebaGeneralizedKirkwoodForce", "getProbeRadius") : ( 'unit.nanometer', ()),
("AmoebaGeneralizedKirkwoodForce", "getSurfaceAreaFactor") : ( 'unit.kilojoule_per_mole/(unit.nanometer*unit.nanometer)',()), ("AmoebaGeneralizedKirkwoodForce", "getSurfaceAreaFactor") : ( 'unit.kilojoule_per_mole/(unit.nanometer*unit.nanometer)',()),
("AmoebaMultipoleForce", "getNumMultipoles") : ( None,()), ("AmoebaMultipoleForce", "getNumMultipoles") : ( None,()),
("AmoebaMultipoleForce", "getPolarizationType") : ( None,()), ("AmoebaMultipoleForce", "getPolarizationType") : ( None,()),
("AmoebaMultipoleForce", "getCutoffDistance") : ( 'unit.nanometer',()), ("AmoebaMultipoleForce", "getCutoffDistance") : ( 'unit.nanometer',()),
...@@ -297,7 +303,7 @@ UNITS = { ...@@ -297,7 +303,7 @@ UNITS = {
("AmoebaVdwForce", "getSoftcorePower") : ( None, ()), ("AmoebaVdwForce", "getSoftcorePower") : ( None, ()),
("AmoebaVdwForce", "getSoftcoreAlpha") : ( None, ()), ("AmoebaVdwForce", "getSoftcoreAlpha") : ( None, ()),
("AmoebaVdwForce", "getCutoff") : ( 'unit.nanometer', ()), ("AmoebaVdwForce", "getCutoff") : ( 'unit.nanometer', ()),
("AmoebaVdwForce", "getParticleParameters") : ( None, (None, 'unit.nanometer', 'unit.kilojoule_per_mole', None, None, None)), ("AmoebaVdwForce", "getParticleParameters") : ( None, (None, 'unit.nanometer', 'unit.kilojoule_per_mole', None, None, None, None)),
("AmoebaVdwForce", "getParticleTypeParameters") : ( None, ('unit.nanometer', 'unit.kilojoule_per_mole')), ("AmoebaVdwForce", "getParticleTypeParameters") : ( None, ('unit.nanometer', 'unit.kilojoule_per_mole')),
("AmoebaVdwForce", "getTypePairParameters") : ( None, (None, None, 'unit.nanometer', 'unit.kilojoule_per_mole')), ("AmoebaVdwForce", "getTypePairParameters") : ( None, (None, None, 'unit.nanometer', 'unit.kilojoule_per_mole')),
......
...@@ -639,14 +639,14 @@ class TestAPIUnits(unittest.TestCase): ...@@ -639,14 +639,14 @@ class TestAPIUnits(unittest.TestCase):
self.assertEqual(force.getNumParticles(), 2) self.assertEqual(force.getNumParticles(), 2)
q, r, s = force.getParticleParameters(0) q, r, s, d, k = force.getParticleParameters(0)
self.assertAlmostEqualUnit(q, 1.0*coulomb) self.assertAlmostEqualUnit(q, 1.0*coulomb)
self.assertIs(q.unit, elementary_charge) self.assertIs(q.unit, elementary_charge)
self.assertEqual(r, 1.0*angstroms) self.assertEqual(r, 1.0*angstroms)
self.assertIs(r.unit, nanometer) self.assertIs(r.unit, nanometer)
self.assertEqual(s, 0.5) self.assertEqual(s, 0.5)
q, r, s = force.getParticleParameters(1) q, r, s, d, k = force.getParticleParameters(1)
self.assertAlmostEqualUnit(q, 1.0*elementary_charge) self.assertAlmostEqualUnit(q, 1.0*elementary_charge)
self.assertIs(q.unit, elementary_charge) self.assertIs(q.unit, elementary_charge)
self.assertEqual(r, 1.0*nanometer) self.assertEqual(r, 1.0*nanometer)
...@@ -759,44 +759,47 @@ class TestAPIUnits(unittest.TestCase): ...@@ -759,44 +759,47 @@ class TestAPIUnits(unittest.TestCase):
self.assertEqual(force.getNumParticles(), 3) self.assertEqual(force.getNumParticles(), 3)
p, sig, eps, scale, alchemical, type = force.getParticleParameters(0) p, sig, eps, reduction, alchemical, type, scale = force.getParticleParameters(0)
self.assertEqual(p, 0) self.assertEqual(p, 0)
self.assertEqual(sig, 0.1*nanometers) self.assertEqual(sig, 0.1*nanometers)
self.assertIs(sig.unit, nanometers) self.assertIs(sig.unit, nanometers)
self.assertEqual(eps, 1.0*kilojoules_per_mole) self.assertEqual(eps, 1.0*kilojoules_per_mole)
self.assertIs(eps.unit, kilojoules_per_mole) self.assertIs(eps.unit, kilojoules_per_mole)
self.assertEqual(scale, 1.0) self.assertEqual(reduction, 1.0)
self.assertEqual(type, -1) self.assertEqual(type, -1)
self.assertEqual(scale, 1.0)
p, sig, eps, scale, alchemical, type = force.getParticleParameters(1) p, sig, eps, reduction, alchemical, type, scale = force.getParticleParameters(1)
self.assertEqual(p, 1) self.assertEqual(p, 1)
self.assertEqual(sig, 1.0*angstroms) self.assertEqual(sig, 1.0*angstroms)
self.assertIs(sig.unit, nanometers) self.assertIs(sig.unit, nanometers)
self.assertEqual(eps, 1.0*kilocalories_per_mole) self.assertEqual(eps, 1.0*kilocalories_per_mole)
self.assertIs(eps.unit, kilojoules_per_mole) self.assertIs(eps.unit, kilojoules_per_mole)
self.assertEqual(scale, 0.5) self.assertEqual(reduction, 0.5)
self.assertEqual(type, -1) self.assertEqual(type, -1)
self.assertEqual(scale, 1.0)
p, sig, eps, scale, alchemical, type = force.getParticleParameters(2) p, sig, eps, reduction, alchemical, type, scale = force.getParticleParameters(2)
self.assertEqual(p, 1) self.assertEqual(p, 1)
self.assertAlmostEqualUnit(sig, 0.8*angstroms) self.assertAlmostEqualUnit(sig, 0.8*angstroms)
self.assertIs(sig.unit, nanometers) self.assertIs(sig.unit, nanometers)
self.assertEqual(eps, 2.0*kilocalories_per_mole) self.assertEqual(eps, 2.0*kilocalories_per_mole)
self.assertIs(eps.unit, kilojoules_per_mole) self.assertIs(eps.unit, kilojoules_per_mole)
self.assertEqual(scale, 0.25) self.assertEqual(reduction, 0.25)
self.assertEqual(type, -1) self.assertEqual(type, -1)
self.assertEqual(scale, 1.0)
def testAmoebaWcaDispersionForce(self): def testAmoebaWcaDispersionForce(self):
""" Tests the AmoebaWcaDispersionForce API features """ """ Tests the AmoebaWcaDispersionForce API features """
force = AmoebaWcaDispersionForce() force = AmoebaWcaDispersionForce()
self.assertEqual(force.getDispoff(), 0.26*nanometer) self.assertEqual(force.getDispoff(), 0.1056*nanometer)
self.assertEqual(force.getAwater(), 0.033428*nanometer**-3) self.assertEqual(force.getAwater(), 33.428*nanometer**-3)
self.assertEqual(force.getEpsh(), 0.0135*kilojoule_per_mole) self.assertEqual(force.getEpsh(), 0.056484*kilojoule_per_mole)
self.assertEqual(force.getEpso(), 0.11*kilojoule_per_mole) self.assertEqual(force.getEpso(), 0.46024000000000004*kilojoule_per_mole)
self.assertEqual(force.getRminh(), 1.3275*nanometer) self.assertEqual(force.getRminh(), 0.13275*nanometer)
self.assertEqual(force.getRmino(), 1.7025*nanometer) self.assertEqual(force.getRmino(), 0.17025*nanometer)
self.assertEqual(force.getShctd(), 0.81) self.assertEqual(force.getShctd(), 0.82)
self.assertEqual(force.getSlevy(), 1.0) self.assertEqual(force.getSlevy(), 1.0)
force.setDispoff(3*angstroms) force.setDispoff(3*angstroms)
......
<?xml version="1.0" ?> <?xml version="1.0" ?>
<State time="0" type="State" version="1"> <State openmmVersion="8.1" stepCount="0" time="0" type="State" version="1">
<PeriodicBoxVectors> <PeriodicBoxVectors>
<A x="2" y="0" z="0"/> <A x="2" y="0" z="0"/>
<B x="0" y="2" z="0"/> <B x="0" y="2" z="0"/>
<C x="0" y="0" z="2"/> <C x="0" y="0" z="2"/>
</PeriodicBoxVectors> </PeriodicBoxVectors>
<Forces> <Forces>
<Force x="-60.899006905648534" y="-704.8991281062977" z=".0364180169671772"/> <Force x="-60.48934767780512" y="-704.2905908945154" z=".03641801581402149"/>
<Force x="1179.7263311404506" y="629.2168542831286" z="1.563821009034657"/> <Force x="1180.5929374826017" y="629.7947038764579" z="1.563821030008981"/>
<Force x="-484.4401097634541" y="135.94210610096957" z="558.0155391926069"/> <Force x="-483.76818418432686" y="136.17122858237818" z="557.445557397338"/>
<Force x="-484.1625627429897" y="136.02915381525668" z="-557.7203977673528"/> <Force x="-483.4906371562492" y="136.2582762991838" z="-557.1504159715371"/>
<Force x="-804.8403408476064" y="-857.579131840898" z="118.43755474210333"/> <Force x="-804.7241107189593" y="-856.9162372174255" z="118.25073365873143"/>
<Force x="84.24441920455223" y="-421.86322192608037" z="120.734742628977"/> <Force x="83.81135991157873" y="-420.22160214948235" z="120.49617758444118"/>
<Force x="666.4942549112259" y="-479.03339298154526" z="19.66166555862896"/> <Force x="667.2849511622113" y="-479.3499008055406" z="19.235509803262467"/>
<Force x="-518.9062723002917" y="686.3850843706331" z=".7311137123231983"/> <Force x="-518.4733820988154" y="686.0855400714895" z=".7330333001425071"/>
<Force x="-105.62094199225953" y="710.9845370176521" z="-508.0677463920413"/> <Force x="-105.72909078977926" y="711.0668343181237" z="-508.83224725862544"/>
<Force x="285.6690654282444" y="-111.35548608152155" z="847.8096733172159"/> <Force x="285.3169350792583" y="-111.3017080984095" z="846.4662870215625"/>
<Force x="-396.4822698774795" y="24.462223992557014" z="297.9581483103431"/> <Force x="-397.35954566696427" y="24.822763038626682" z="299.33941483017065"/>
<Force x="-168.22340166944585" y="110.99779797739818" z="-824.0916382722021"/> <Force x="-168.27998965108577" y="111.03576033655848" z="-823.1461667946043"/>
<Force x="805.7023041833917" y="15.738288953519556" z="-340.2263402925698"/> <Force x="804.8766900716053" y="16.1343934366816" z="-339.5169767615949"/>
<Force x="366.3025998383222" y="-647.7535895818237" z="-273.83047817845636"/> <Force x="365.43779472611493" y="-647.3449172328129" z="-273.0689393022661"/>
<Force x="-649.7310636705703" y="-495.52797252280067" z="317.36013856851315"/> <Force x="-649.0369250626607" y="-495.932522816643" z="316.96471153570917"/>
<Force x="-480.120788018345" y="172.44477988154952" z="-16.235455767965004"/> <Force x="-479.0134208353095" y="171.79575146148863" z="-16.236401291749388"/>
<Force x="-486.20230228601736" y="982.6376366390087" z="127.20818643942287"/> <Force x="-486.9195278219171" y="982.2625867919138" z="126.98779152341059"/>
<Force x="820.5730252078641" y="-78.71234329038225" z="109.31395566365498"/> <Force x="819.7259822269968" y="-78.87846748631466" z="109.09059215425442"/>
<Force x="355.03388135028814" y="-1391.2776654673507" z=".9942543092954484"/> <Force x="354.68327095554434" y="-1392.2195705508666" z=".9942543256763656"/>
<Force x="-511.3467906691061" y="677.7717086552518" z=".008253291392112616"/> <Force x="-511.1150957463999" y="676.962020571201" z=".008253289146054499"/>
<Force x="293.66157422204157" y="452.68343054060256" z="502.83463917630775"/> <Force x="293.38125738064446" y="452.02037971976495" z="502.28873599651723"/>
<Force x="293.5683952568295" y="452.70832957117113" z="-502.49604726620026"/> <Force x="293.2880784137142" y="452.0452787481405" z="-501.95014408580874"/>
</Forces> </Forces>
</State> </State>
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