"...ssh:/git@developer.sourcefind.cn:2222/tsoc/openmm.git" did not exist on "f7f701363753918f51443d42150ea92f9d602923"
Commit 46f7b76b authored by Peter Eastman's avatar Peter Eastman
Browse files

AmoebaVdwForce works with triclinic boxes

parent 53690fef
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "openmm/System.h" #include "openmm/System.h"
#include "openmm/AmoebaVdwForce.h" #include "openmm/AmoebaVdwForce.h"
#include "openmm/LangevinIntegrator.h" #include "openmm/LangevinIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <stdlib.h> #include <stdlib.h>
...@@ -50,6 +51,7 @@ ...@@ -50,6 +51,7 @@
using namespace OpenMM; using namespace OpenMM;
using namespace std;
extern "C" void registerAmoebaCudaKernelFactories(); extern "C" void registerAmoebaCudaKernelFactories();
...@@ -1981,6 +1983,62 @@ void testVdwWater( int includeVdwDispersionCorrection, FILE* log ) { ...@@ -1981,6 +1983,62 @@ void testVdwWater( int includeVdwDispersionCorrection, FILE* log ) {
} }
} }
void testTriclinic() {
System system;
system.addParticle(1.0);
system.addParticle(1.0);
Vec3 a(3.1, 0, 0);
Vec3 b(0.4, 3.5, 0);
Vec3 c(-0.1, -0.5, 4.0);
system.setDefaultPeriodicBoxVectors(a, b, c);
LangevinIntegrator integrator(0.0, 0.1, 0.01);
AmoebaVdwForce* vdw = new AmoebaVdwForce();
vdw->setUseDispersionCorrection(false);
vdw->addParticle(0, 0.5, 1.0, 0.0);
vdw->addParticle(1, 0.5, 1.0, 0.0);
vdw->setNonbondedMethod(AmoebaVdwForce::CutoffPeriodic);
const double cutoff = 1.5;
vdw->setCutoff(cutoff);
system.addForce(vdw);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
vector<Vec3> positions(2);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int iteration = 0; iteration < 50; iteration++) {
// Generate random positions for the two particles.
positions[0] = a*genrand_real2(sfmt) + b*genrand_real2(sfmt) + c*genrand_real2(sfmt);
positions[1] = a*genrand_real2(sfmt) + b*genrand_real2(sfmt) + c*genrand_real2(sfmt);
context.setPositions(positions);
// Loop over all possible periodic copies and find the nearest one.
Vec3 delta;
double distance2 = 100.0;
for (int i = -1; i < 2; i++)
for (int j = -1; j < 2; j++)
for (int k = -1; k < 2; k++) {
Vec3 d = positions[1]-positions[0]+a*i+b*j+c*k;
if (d.dot(d) < distance2) {
delta = d;
distance2 = d.dot(d);
}
}
double distance = sqrt(distance2);
// See if the energy is correct.
State state = context.getState(State::Energy);
if (distance >= cutoff) {
ASSERT_EQUAL(0.0, state.getPotentialEnergy());
}
else if (distance < 0.9*cutoff) {
const double energy = pow(1.07/(distance+0.07), 7.0)*(1.12/(pow(distance, 7.0)+0.12)-2);
ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL);
}
}
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
try { try {
std::cout << "TestCudaAmoebaVdwForce running test..." << std::endl; std::cout << "TestCudaAmoebaVdwForce running test..." << std::endl;
...@@ -2029,6 +2087,10 @@ int main(int argc, char* argv[]) { ...@@ -2029,6 +2087,10 @@ int main(int argc, char* argv[]) {
includeVdwDispersionCorrection = 1; includeVdwDispersionCorrection = 1;
testVdwWater( includeVdwDispersionCorrection, log ); testVdwWater( includeVdwDispersionCorrection, log );
// test triclinic boxes
testTriclinic();
} catch(const std::exception& e) { } catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl; std::cout << "exception: " << e.what() << std::endl;
......
...@@ -976,14 +976,14 @@ double ReferenceCalcAmoebaVdwForceKernel::execute(ContextImpl& context, bool inc ...@@ -976,14 +976,14 @@ double ReferenceCalcAmoebaVdwForceKernel::execute(ContextImpl& context, bool inc
computeNeighborListVoxelHash( *neighborList, numParticles, posData, allExclusions, extractBoxVectors(context), usePBC, cutoff, 0.0); computeNeighborListVoxelHash( *neighborList, numParticles, posData, allExclusions, extractBoxVectors(context), usePBC, cutoff, 0.0);
if( usePBC ){ if( usePBC ){
vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::CutoffPeriodic); vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::CutoffPeriodic);
RealVec& box = extractBoxSize(context); RealVec* boxVectors = extractBoxVectors(context);
double minAllowedSize = 1.999999*cutoff; double minAllowedSize = 1.999999*cutoff;
if (box[0] < minAllowedSize || box[1] < minAllowedSize || box[2] < minAllowedSize){ if (boxVectors[0][0] < minAllowedSize || boxVectors[1][1] < minAllowedSize || boxVectors[2][2] < minAllowedSize){
throw OpenMMException("The periodic box size has decreased to less than twice the cutoff."); throw OpenMMException("The periodic box size has decreased to less than twice the cutoff.");
} }
vdwForce.setPeriodicBox(box); vdwForce.setPeriodicBox(boxVectors);
energy = vdwForce.calculateForceAndEnergy( numParticles, posData, indexIVs, sigmas, epsilons, reductions, *neighborList, forceData); energy = vdwForce.calculateForceAndEnergy( numParticles, posData, indexIVs, sigmas, epsilons, reductions, *neighborList, forceData);
energy += dispersionCoefficient/(box[0]*box[1]*box[2]); energy += dispersionCoefficient/(boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2]);
} else { } else {
vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::CutoffNonPeriodic); vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::CutoffNonPeriodic);
} }
......
...@@ -24,18 +24,18 @@ ...@@ -24,18 +24,18 @@
#include "AmoebaReferenceForce.h" #include "AmoebaReferenceForce.h"
#include "AmoebaReferenceVdwForce.h" #include "AmoebaReferenceVdwForce.h"
#include "ReferenceForce.h"
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
using std::vector; using std::vector;
using OpenMM::RealVec; using namespace OpenMM;
AmoebaReferenceVdwForce::AmoebaReferenceVdwForce( ) : _nonbondedMethod(NoCutoff), _cutoff(1.0e+10), _taperCutoffFactor(0.9) { AmoebaReferenceVdwForce::AmoebaReferenceVdwForce( ) : _nonbondedMethod(NoCutoff), _cutoff(1.0e+10), _taperCutoffFactor(0.9) {
setTaperCoefficients( _cutoff ); setTaperCoefficients( _cutoff );
setSigmaCombiningRule( "ARITHMETIC" ); setSigmaCombiningRule( "ARITHMETIC" );
setEpsilonCombiningRule( "GEOMETRIC" ); setEpsilonCombiningRule( "GEOMETRIC" );
_periodicBoxDimensions = RealVec( 0.0, 0.0, 0.0 );
} }
...@@ -44,7 +44,6 @@ AmoebaReferenceVdwForce::AmoebaReferenceVdwForce( const std::string& sigmaCombin ...@@ -44,7 +44,6 @@ AmoebaReferenceVdwForce::AmoebaReferenceVdwForce( const std::string& sigmaCombin
setTaperCoefficients( _cutoff ); setTaperCoefficients( _cutoff );
setSigmaCombiningRule( sigmaCombiningRule ); setSigmaCombiningRule( sigmaCombiningRule );
setEpsilonCombiningRule( epsilonCombiningRule ); setEpsilonCombiningRule( epsilonCombiningRule );
_periodicBoxDimensions = RealVec( 0.0, 0.0, 0.0 );
} }
AmoebaReferenceVdwForce::NonbondedMethod AmoebaReferenceVdwForce::getNonbondedMethod( void ) const { AmoebaReferenceVdwForce::NonbondedMethod AmoebaReferenceVdwForce::getNonbondedMethod( void ) const {
...@@ -77,12 +76,10 @@ double AmoebaReferenceVdwForce::getCutoff( void ) const { ...@@ -77,12 +76,10 @@ double AmoebaReferenceVdwForce::getCutoff( void ) const {
return _cutoff; return _cutoff;
} }
void AmoebaReferenceVdwForce::setPeriodicBox( const RealVec& box ){ void AmoebaReferenceVdwForce::setPeriodicBox(OpenMM::RealVec* vectors) {
_periodicBoxDimensions = box; _periodicBoxVectors[0] = vectors[0];
} _periodicBoxVectors[1] = vectors[1];
_periodicBoxVectors[2] = vectors[2];
RealVec AmoebaReferenceVdwForce::getPeriodicBox( void ) const {
return _periodicBoxDimensions;
} }
void AmoebaReferenceVdwForce::setSigmaCombiningRule( const std::string& sigmaCombiningRule ){ void AmoebaReferenceVdwForce::setSigmaCombiningRule( const std::string& sigmaCombiningRule ){
...@@ -181,7 +178,7 @@ void AmoebaReferenceVdwForce::addReducedForce( unsigned int particleI, unsigned ...@@ -181,7 +178,7 @@ void AmoebaReferenceVdwForce::addReducedForce( unsigned int particleI, unsigned
forces[particleIV][2] += sign*force[2]*(one - reduction); forces[particleIV][2] += sign*force[2]*(one - reduction);
} }
RealOpenMM AmoebaReferenceVdwForce::calculatePairIxn( RealOpenMM combindedSigma, RealOpenMM combindedEpsilon, RealOpenMM AmoebaReferenceVdwForce::calculatePairIxn( RealOpenMM combinedSigma, RealOpenMM combinedEpsilon,
const Vec3& particleIPosition, const Vec3& particleIPosition,
const Vec3& particleJPosition, const Vec3& particleJPosition,
Vec3& force ) const { Vec3& force ) const {
...@@ -197,36 +194,34 @@ RealOpenMM AmoebaReferenceVdwForce::calculatePairIxn( RealOpenMM combindedSigma, ...@@ -197,36 +194,34 @@ RealOpenMM AmoebaReferenceVdwForce::calculatePairIxn( RealOpenMM combindedSigma,
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
RealOpenMM xr = particleIPosition[0] - particleJPosition[0]; // get deltaR, R2, and R between 2 atoms
RealOpenMM yr = particleIPosition[1] - particleJPosition[1];
RealOpenMM zr = particleIPosition[2] - particleJPosition[2];
if( _nonbondedMethod == CutoffPeriodic ){ RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
xr -= static_cast<RealOpenMM>((floor(xr/_periodicBoxDimensions[0]+0.5)*_periodicBoxDimensions[0])); if (_nonbondedMethod == CutoffPeriodic)
yr -= static_cast<RealOpenMM>((floor(yr/_periodicBoxDimensions[1]+0.5)*_periodicBoxDimensions[1])); ReferenceForce::getDeltaRPeriodic(particleJPosition, particleIPosition, _periodicBoxVectors, deltaR);
zr -= static_cast<RealOpenMM>((floor(zr/_periodicBoxDimensions[2]+0.5)*_periodicBoxDimensions[2])); else
} ReferenceForce::getDeltaR(particleJPosition, particleIPosition, deltaR);
RealOpenMM r_ij_2 = xr*xr + yr*yr + zr*zr; RealOpenMM r_ij_2 = deltaR[ReferenceForce::R2Index];
RealOpenMM r_ij = SQRT(r_ij_2); RealOpenMM r_ij = deltaR[ReferenceForce::RIndex];
RealOpenMM sigma_7 = combindedSigma*combindedSigma*combindedSigma; RealOpenMM sigma_7 = combinedSigma*combinedSigma*combinedSigma;
sigma_7 = sigma_7*sigma_7*combindedSigma; sigma_7 = sigma_7*sigma_7*combinedSigma;
RealOpenMM r_ij_6 = r_ij_2*r_ij_2*r_ij_2; RealOpenMM r_ij_6 = r_ij_2*r_ij_2*r_ij_2;
RealOpenMM r_ij_7 = r_ij_6*r_ij; RealOpenMM r_ij_7 = r_ij_6*r_ij;
RealOpenMM rho = r_ij_7 + ghal*sigma_7; RealOpenMM rho = r_ij_7 + ghal*sigma_7;
RealOpenMM tau = (dhal + one)/(r_ij + dhal*combindedSigma); RealOpenMM tau = (dhal + one)/(r_ij + dhal*combinedSigma);
RealOpenMM tau_7 = tau*tau*tau; RealOpenMM tau_7 = tau*tau*tau;
tau_7 = tau_7*tau_7*tau; tau_7 = tau_7*tau_7*tau;
RealOpenMM dtau = tau/(dhal + one); RealOpenMM dtau = tau/(dhal + one);
RealOpenMM ratio = (sigma_7/rho); RealOpenMM ratio = (sigma_7/rho);
RealOpenMM gtau = combindedEpsilon*tau_7*r_ij_6*(ghal+one)*ratio*ratio; RealOpenMM gtau = combinedEpsilon*tau_7*r_ij_6*(ghal+one)*ratio*ratio;
RealOpenMM energy = combindedEpsilon*tau_7*sigma_7*( (ghal+one)*sigma_7/rho - two); RealOpenMM energy = combinedEpsilon*tau_7*sigma_7*( (ghal+one)*sigma_7/rho - two);
RealOpenMM dEdR = -seven*(dtau*energy + gtau); RealOpenMM dEdR = -seven*(dtau*energy + gtau);
...@@ -242,9 +237,9 @@ RealOpenMM AmoebaReferenceVdwForce::calculatePairIxn( RealOpenMM combindedSigma, ...@@ -242,9 +237,9 @@ RealOpenMM AmoebaReferenceVdwForce::calculatePairIxn( RealOpenMM combindedSigma,
dEdR /= r_ij; dEdR /= r_ij;
force[0] = dEdR*xr; force[0] = dEdR*deltaR[0];
force[1] = dEdR*yr; force[1] = dEdR*deltaR[1];
force[2] = dEdR*zr; force[2] = dEdR*deltaR[2];
return energy; return energy;
...@@ -315,11 +310,11 @@ RealOpenMM AmoebaReferenceVdwForce::calculateForceAndEnergy( int numParticles, ...@@ -315,11 +310,11 @@ RealOpenMM AmoebaReferenceVdwForce::calculateForceAndEnergy( int numParticles,
for( unsigned int jj = ii+1; jj < static_cast<unsigned int>(numParticles); jj++ ){ for( unsigned int jj = ii+1; jj < static_cast<unsigned int>(numParticles); jj++ ){
if( exclusions[jj] == 0 ){ if( exclusions[jj] == 0 ){
RealOpenMM combindedSigma = (this->*_combineSigmas)(sigmaI, sigmas[jj] ); RealOpenMM combinedSigma = (this->*_combineSigmas)(sigmaI, sigmas[jj] );
RealOpenMM combindedEpsilon = (this->*_combineEpsilons)(epsilonI, epsilons[jj] ); RealOpenMM combinedEpsilon = (this->*_combineEpsilons)(epsilonI, epsilons[jj] );
Vec3 force; Vec3 force;
energy += calculatePairIxn( combindedSigma, combindedEpsilon, energy += calculatePairIxn( combinedSigma, combinedEpsilon,
reducedPositions[ii], reducedPositions[jj], reducedPositions[ii], reducedPositions[jj],
force ); force );
...@@ -384,11 +379,11 @@ RealOpenMM AmoebaReferenceVdwForce::calculateForceAndEnergy( int numParticles, ...@@ -384,11 +379,11 @@ RealOpenMM AmoebaReferenceVdwForce::calculateForceAndEnergy( int numParticles,
int siteI = pair.first; int siteI = pair.first;
int siteJ = pair.second; int siteJ = pair.second;
RealOpenMM combindedSigma = (this->*_combineSigmas)( sigmas[siteI], sigmas[siteJ] ); RealOpenMM combinedSigma = (this->*_combineSigmas)( sigmas[siteI], sigmas[siteJ] );
RealOpenMM combindedEpsilon = (this->*_combineEpsilons)( epsilons[siteI], epsilons[siteJ] ); RealOpenMM combinedEpsilon = (this->*_combineEpsilons)( epsilons[siteI], epsilons[siteJ] );
Vec3 force; Vec3 force;
energy += calculatePairIxn( combindedSigma, combindedEpsilon, energy += calculatePairIxn( combinedSigma, combinedEpsilon,
reducedPositions[siteI], reducedPositions[siteJ], force ); reducedPositions[siteI], reducedPositions[siteJ], force );
if( indexIVs[siteI] == siteI ){ if( indexIVs[siteI] == siteI ){
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
using namespace OpenMM; namespace OpenMM {
class AmoebaReferenceVdwForce; class AmoebaReferenceVdwForce;
typedef RealOpenMM (AmoebaReferenceVdwForce::*CombiningFunction)( RealOpenMM x, RealOpenMM y) const; typedef RealOpenMM (AmoebaReferenceVdwForce::*CombiningFunction)( RealOpenMM x, RealOpenMM y) const;
...@@ -174,21 +174,11 @@ public: ...@@ -174,21 +174,11 @@ public:
Set box dimensions Set box dimensions
@param box box dimensions @param vectors the vectors defining the periodic box
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
void setPeriodicBox( const RealVec& box ); void setPeriodicBox(OpenMM::RealVec* vectors);
/**---------------------------------------------------------------------------------------
Get box dimensions
@return box dimensions
--------------------------------------------------------------------------------------- */
RealVec getPeriodicBox( void ) const;
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -253,7 +243,7 @@ private: ...@@ -253,7 +243,7 @@ private:
double _taperCutoffFactor; double _taperCutoffFactor;
double _taperCutoff; double _taperCutoff;
RealOpenMM _taperCoefficients[3]; RealOpenMM _taperCoefficients[3];
RealVec _periodicBoxDimensions; RealVec _periodicBoxVectors[3];
CombiningFunction _combineSigmas; CombiningFunction _combineSigmas;
RealOpenMM arithmeticSigmaCombiningRule( RealOpenMM sigmaI, RealOpenMM sigmaJ ) const; RealOpenMM arithmeticSigmaCombiningRule( RealOpenMM sigmaI, RealOpenMM sigmaJ ) const;
RealOpenMM geometricSigmaCombiningRule( RealOpenMM sigmaI, RealOpenMM sigmaJ ) const; RealOpenMM geometricSigmaCombiningRule( RealOpenMM sigmaI, RealOpenMM sigmaJ ) const;
...@@ -333,6 +323,7 @@ private: ...@@ -333,6 +323,7 @@ private:
}; };
}
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
#endif // _AmoebaReferenceVdwForce___ #endif // _AmoebaReferenceVdwForce___
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "openmm/System.h" #include "openmm/System.h"
#include "openmm/AmoebaVdwForce.h" #include "openmm/AmoebaVdwForce.h"
#include "openmm/LangevinIntegrator.h" #include "openmm/LangevinIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <stdlib.h> #include <stdlib.h>
...@@ -50,6 +51,7 @@ ...@@ -50,6 +51,7 @@
using namespace OpenMM; using namespace OpenMM;
using namespace std;
extern "C" OPENMM_EXPORT void registerAmoebaReferenceKernelFactories(); extern "C" OPENMM_EXPORT void registerAmoebaReferenceKernelFactories();
...@@ -1981,6 +1983,62 @@ void testVdwWater( int includeVdwDispersionCorrection, FILE* log ) { ...@@ -1981,6 +1983,62 @@ void testVdwWater( int includeVdwDispersionCorrection, FILE* log ) {
} }
} }
void testTriclinic() {
System system;
system.addParticle(1.0);
system.addParticle(1.0);
Vec3 a(3.1, 0, 0);
Vec3 b(0.4, 3.5, 0);
Vec3 c(-0.1, -0.5, 4.0);
system.setDefaultPeriodicBoxVectors(a, b, c);
LangevinIntegrator integrator(0.0, 0.1, 0.01);
AmoebaVdwForce* vdw = new AmoebaVdwForce();
vdw->setUseDispersionCorrection(false);
vdw->addParticle(0, 0.5, 1.0, 0.0);
vdw->addParticle(1, 0.5, 1.0, 0.0);
vdw->setNonbondedMethod(AmoebaVdwForce::CutoffPeriodic);
const double cutoff = 1.5;
vdw->setCutoff(cutoff);
system.addForce(vdw);
Context context(system, integrator, Platform::getPlatformByName("Reference"));
vector<Vec3> positions(2);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int iteration = 0; iteration < 50; iteration++) {
// Generate random positions for the two particles.
positions[0] = a*genrand_real2(sfmt) + b*genrand_real2(sfmt) + c*genrand_real2(sfmt);
positions[1] = a*genrand_real2(sfmt) + b*genrand_real2(sfmt) + c*genrand_real2(sfmt);
context.setPositions(positions);
// Loop over all possible periodic copies and find the nearest one.
Vec3 delta;
double distance2 = 100.0;
for (int i = -1; i < 2; i++)
for (int j = -1; j < 2; j++)
for (int k = -1; k < 2; k++) {
Vec3 d = positions[1]-positions[0]+a*i+b*j+c*k;
if (d.dot(d) < distance2) {
delta = d;
distance2 = d.dot(d);
}
}
double distance = sqrt(distance2);
// See if the energy is correct.
State state = context.getState(State::Energy);
if (distance >= cutoff) {
ASSERT_EQUAL(0.0, state.getPotentialEnergy());
}
else if (distance < 0.9*cutoff) {
const double energy = pow(1.07/(distance+0.07), 7.0)*(1.12/(pow(distance, 7.0)+0.12)-2);
ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL);
}
}
}
int main( int numberOfArguments, char* argv[] ) { int main( int numberOfArguments, char* argv[] ) {
try { try {
...@@ -2029,6 +2087,10 @@ int main( int numberOfArguments, char* argv[] ) { ...@@ -2029,6 +2087,10 @@ int main( int numberOfArguments, char* argv[] ) {
includeVdwDispersionCorrection = 1; includeVdwDispersionCorrection = 1;
testVdwWater( includeVdwDispersionCorrection, log ); testVdwWater( includeVdwDispersionCorrection, log );
// test triclinic boxes
testTriclinic();
} catch(const std::exception& e) { } catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl; std::cout << "exception: " << e.what() << std::endl;
......
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