Commit 297538f7 authored by Mark Friedrichs's avatar Mark Friedrichs
Browse files

Reference code for GB/VI

parent 04b90973
......@@ -36,6 +36,7 @@
#include "BrownianIntegrator.h"
#include "CMMotionRemover.h"
#include "GBSAOBCForce.h"
#include "GBVIForce.h"
#include "HarmonicAngleForce.h"
#include "HarmonicBondForce.h"
#include "KernelImpl.h"
......@@ -277,6 +278,39 @@ public:
virtual double executeEnergy(OpenMMContextImpl& context) = 0;
};
/**
* This kernel is invoked by GBVIForce to calculate the forces acting on the system and the energy of the system.
*/
class CalcGBVIForceKernel : public KernelImpl {
public:
static std::string Name() {
return "CalcGBVIForces";
}
CalcGBVIForceKernel(std::string name, const Platform& platform) : KernelImpl(name, platform) {
}
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the GBVIForce this kernel will be used for
* @param scaledRadii scaled radii
*/
virtual void initialize(const System& system, const GBVIForce& force, const std::vector<double>& scaledRadii) = 0;
/**
* Execute the kernel to calculate the forces.
*
* @param context the context in which to execute this kernel
*/
virtual void executeForces(OpenMMContextImpl& context) = 0;
/**
* Execute the kernel to calculate the energy.
*
* @param context the context in which to execute this kernel
* @return the potential energy due to the GBVIForce
*/
virtual double executeEnergy(OpenMMContextImpl& context) = 0;
};
/**
* This kernel is invoked by VerletIntegrator to take one time step.
*/
......
#ifndef OPENMM_GBVIFORCEFIELD_H_
#define OPENMM_GBVIFORCEFIELD_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2009 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "Force.h"
#include <vector>
#include "internal/windowsExport.h"
namespace OpenMM {
/**
* This class implements an implicit solvation force using the GB/VI model.
* <p>
* If the System also contains a NonbondedForce, this force will use the cutoffs
* and periodic boundary conditions specified in it.
*/
class OPENMM_EXPORT GBVIForce : public Force {
public:
/*
* Create a GBVIForce.
*
* @param numParticles the number of particles in the system
*/
GBVIForce(int numParticles);
/**
* Get the number of particles in the system.
*/
int getNumParticles() const {
return particles.size();
}
/**
* Get the force field parameters for a particle.
*
* @param index the index of the particle for which to get parameters
* @param charge the charge of the particle, measured in units of the proton charge
* @param radius the GBSA radius of the particle, measured in nm
* @param gamma the gamma parameter
*/
void getParticleParameters(int index, double& charge, double& radius, double& gamma) const;
/**
* Set the force field parameters for a particle.
*
* @param index the index of the particle for which to set parameters
* @param charge the charge of the particle, measured in units of the proton charge
* @param radius the GB/VI radius of the particle, measured in nm
* @param gamma the gamma parameter
*/
void setParticleParameters(int index, double charge, double radius, double gamma);
/**
* Get the dielectric constant for the solvent.
*/
double getSolventDielectric() const {
return solventDielectric;
}
/**
* Set the dielectric constant for the solvent.
*/
void setSolventDielectric(double dielectric) {
solventDielectric = dielectric;
}
/**
* Get the dielectric constant for the solute.
*/
double getSoluteDielectric() const {
return soluteDielectric;
}
/**
* Set the dielectric constant for the solute.
*/
void setSoluteDielectric(double dielectric) {
soluteDielectric = dielectric;
}
protected:
ForceImpl* createImpl();
private:
class ParticleInfo;
double solventDielectric, soluteDielectric;
// Retarded visual studio compiler complains about being unable to
// export private stl class members.
// This stanza explains that it should temporarily shut up.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4251)
#endif
std::vector<ParticleInfo> particles;
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
};
class GBVIForce::ParticleInfo {
public:
double charge, radius, gamma;
ParticleInfo() {
charge = radius = gamma = 0.0;
}
};
} // namespace OpenMM
#endif /*OPENMM_GBVIFORCEFIELD_H_*/
#ifndef OPENMM_GBVIFORCEFIELDIMPL_H_
#define OPENMM_GBVIFORCEFIELDIMPL_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "ForceImpl.h"
#include "GBVIForce.h"
#include "Kernel.h"
#include <string>
namespace OpenMM {
/**
* This is the internal implementation of GBVIForce.
*/
class GBVIForceImpl : public ForceImpl {
public:
GBVIForceImpl(GBVIForce& owner);
void initialize(OpenMMContextImpl& context);
GBVIForce& getOwner() {
return owner;
}
// calculate scaled radii (Eq. 5 of Labute paper [JCC 29 1693-1698 2008])
void findScaledRadii( int numberOfParticles, const std::vector<std::vector<int> >& bondIndices,
const std::vector<double> & bondLengths, std::vector<double> & scaledRadii) const;
void updateContextState(OpenMMContextImpl& context) {
// This force field doesn't update the state directly.
}
void calcForces(OpenMMContextImpl& context, Stream& forces);
double calcEnergy(OpenMMContextImpl& context);
std::map<std::string, double> getDefaultParameters() {
return std::map<std::string, double>(); // This force field doesn't define any parameters.
}
std::vector<std::string> getKernelNames();
private:
GBVIForce& owner;
Kernel kernel;
};
} // namespace OpenMM
#endif /*OPENMM_GBVIFORCEFIELDIMPL_H_*/
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "Force.h"
#include "OpenMMException.h"
#include "GBVIForce.h"
#include "internal/GBVIForceImpl.h"
using namespace OpenMM;
GBVIForce::GBVIForce(int numParticles) : particles(numParticles), solventDielectric(78.3), soluteDielectric(1.0) {
}
void GBVIForce::getParticleParameters(int index, double& charge, double& radius, double& gamma) const {
charge = particles[index].charge;
radius = particles[index].radius;
gamma = particles[index].gamma;
}
void GBVIForce::setParticleParameters(int index, double charge, double radius, double gamma) {
particles[index].charge = charge;
particles[index].radius = radius;
particles[index].gamma = gamma;
}
ForceImpl* GBVIForce::createImpl() {
return new GBVIForceImpl(*this);
}
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "internal/GBVIForceImpl.h"
#include "internal/OpenMMContextImpl.h"
#include "OpenMMException.h"
#include "kernels.h"
#include <vector>
#include <math.h>
using namespace OpenMM;
using std::vector;
GBVIForceImpl::GBVIForceImpl(GBVIForce& owner) : owner(owner) {
}
void GBVIForceImpl::initialize(OpenMMContextImpl& context) {
kernel = context.getPlatform().createKernel(CalcGBVIForceKernel::Name(), context);
// load 1-2 atom pairs along w/ bond distance using HarmonicBondForce & constraints
System& system = context.getSystem();
int numberOfParticles = owner.getNumParticles();
vector<vector<int> > bondIndices;
vector<double> bondLengths;
for (int i = 0; i < system.getNumForces(); i++) {
if (dynamic_cast<HarmonicBondForce*>(&system.getForce(i)) != NULL) {
const HarmonicBondForce& force = dynamic_cast<const HarmonicBondForce&>(system.getForce(i));
bondIndices.resize(force.getNumBonds());
for (int j = 0; j < force.getNumBonds(); ++j) {
int particle1, particle2;
double length, k;
force.getBondParameters(j, particle1, particle2, length, k);
bondIndices[j].push_back(particle1);
bondIndices[j].push_back(particle2);
bondLengths.push_back(length);
}
break;
}
}
// Also treat constrained distances as bonds.
int numBonds = bondIndices.size();
bondIndices.resize(numBonds+system.getNumConstraints());
for (int j = 0; j < system.getNumConstraints(); j++) {
int particle1, particle2;
double distance;
system.getConstraintParameters(j, particle1, particle2, distance);
bondIndices[j+numBonds].push_back(particle1);
bondIndices[j+numBonds].push_back(particle2);
bondLengths.push_back(distance);
}
vector<double> scaledRadii;
scaledRadii.resize(numberOfParticles);
findScaledRadii( numberOfParticles, bondIndices, bondLengths, scaledRadii);
dynamic_cast<CalcGBVIForceKernel&>(kernel.getImpl()).initialize(context.getSystem(), owner, scaledRadii);
}
#define GBVIDebug 1
void GBVIForceImpl::findScaledRadii( int numberOfParticles, const std::vector<std::vector<int> >& bondIndices,
const std::vector<double> & bondLengths, std::vector<double> & scaledRadii) const {
// load 1-2 indicies for each atom
std::vector<std::vector<int> > bonded12(numberOfParticles);
for (int i = 0; i < (int) bondIndices.size(); ++i) {
bonded12[bondIndices[i][0]].push_back(i);
bonded12[bondIndices[i][1]].push_back(i);
}
int errors = 0;
// compute scaled radii (Eq. 5 of Labute paper [JCC 29 p. 1693-1698 2008])
for (int j = 0; j < (int) bonded12.size(); ++j){
double charge;
double gamma;
double radiusJ;
double scaledRadiusJ;
owner.getParticleParameters(j, charge, radiusJ, gamma);
if( bonded12[j].size() == 0 ){
(void) fprintf( stderr, "Warning GBVIForceImpl::findScaledRadii atom %d has no covalent bonds; using atomic radius=%.3f.\n", j, radiusJ );
scaledRadiusJ = radiusJ;
// errors++;
} else {
double rJ2 = radiusJ*radiusJ;
// loop over bonded neighbors of atom j, applying Eq. 5 in Labute
scaledRadiusJ = 0.0;
for (int i = 0; i < (int) bonded12[j].size(); ++i){
int index = bonded12[j][i];
int bondedAtomIndex = (j == bondIndices[index][0]) ? bondIndices[index][1] : bondIndices[index][0];
double radiusI;
owner.getParticleParameters(bondedAtomIndex, charge, radiusI, gamma);
double rI2 = radiusI*radiusI;
double a_ij = (radiusI - bondLengths[index]);
a_ij *= a_ij;
a_ij = (rJ2 - a_ij)/(2.0*bondLengths[index]);
double a_ji = radiusJ - bondLengths[index];
a_ji *= a_ji;
a_ji = (rI2 - a_ji)/(2.0*bondLengths[index]);
scaledRadiusJ += a_ij*a_ij*(3.0*radiusI - a_ij) + a_ji*a_ji*( 3.0*radiusJ - a_ji );
}
scaledRadiusJ = (radiusJ*radiusJ*radiusJ) - 0.125*scaledRadiusJ;
if( scaledRadiusJ > 0.0 ){
scaledRadiusJ = 0.95*pow( scaledRadiusJ, (1.0/3.0) );
} else {
scaledRadiusJ = 0.0;
}
}
scaledRadii[j] = scaledRadiusJ;
}
// abort if errors
if( errors ){
throw OpenMMException("GBVIForceImpl::findScaledRadii errors -- aborting");
}
#if GBVIDebug
(void) fprintf( stderr, " R q gamma scaled radii no. bnds\n" );
double totalQ = 0.0;
for( int i = 0; i < (int) scaledRadii.size(); i++ ){
double charge;
double gamma;
double radiusI;
owner.getParticleParameters(i, charge, radiusI, gamma);
totalQ += charge;
(void) fprintf( stderr, "%4d %14.5e %14.5e %14.5e %14.5e %d\n", i, radiusI, charge, gamma, scaledRadii[i], (int) bonded12[i].size() );
}
(void) fprintf( stderr, "Total charge=%e\n", totalQ );
(void) fflush( stderr );
#endif
#undef GBVIDebug
}
void GBVIForceImpl::calcForces(OpenMMContextImpl& context, Stream& forces) {
dynamic_cast<CalcGBVIForceKernel&>(kernel.getImpl()).executeForces(context);
}
double GBVIForceImpl::calcEnergy(OpenMMContextImpl& context) {
return dynamic_cast<CalcGBVIForceKernel&>(kernel.getImpl()).executeEnergy(context);
}
std::vector<std::string> GBVIForceImpl::getKernelNames() {
std::vector<std::string> names;
names.push_back(CalcGBVIForceKernel::Name());
return names;
}
......@@ -52,6 +52,8 @@ KernelImpl* ReferenceKernelFactory::createKernelImpl(std::string name, const Pla
return new ReferenceCalcRBTorsionForceKernel(name, platform);
else if (name == CalcGBSAOBCForceKernel::Name())
return new ReferenceCalcGBSAOBCForceKernel(name, platform);
else if (name == CalcGBVIForceKernel::Name())
return new ReferenceCalcGBVIForceKernel(name, platform);
else if (name == IntegrateVerletStepKernel::Name())
return new ReferenceIntegrateVerletStepKernel(name, platform);
else if (name == IntegrateLangevinStepKernel::Name())
......
......@@ -32,6 +32,7 @@
#include "ReferenceKernels.h"
#include "ReferenceFloatStreamImpl.h"
#include "gbsa/CpuObc.h"
#include "gbsa/CpuGBVI.h"
#include "SimTKReference/ReferenceAndersenThermostat.h"
#include "SimTKReference/ReferenceAngleBondIxn.h"
#include "SimTKReference/ReferenceBondForce.h"
......@@ -442,7 +443,7 @@ void ReferenceCalcGBSAOBCForceKernel::initialize(const System& system, const GBS
const NonbondedForce* nonbonded = dynamic_cast<const NonbondedForce*>(&system.getForce(i));
if (nonbonded != NULL) {
if (nonbonded->getNonbondedMethod() != NonbondedForce::NoCutoff)
obcParameters->setUseCutoff(nonbonded->getCutoffDistance());
obcParameters->setUseCutoff(static_cast<RealOpenMM>(nonbonded->getCutoffDistance()));
if (nonbonded->getNonbondedMethod() == NonbondedForce::CutoffPeriodic) {
Vec3 boxVectors[3];
nonbonded->getPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]);
......@@ -473,6 +474,79 @@ double ReferenceCalcGBSAOBCForceKernel::executeEnergy(OpenMMContextImpl& context
return obc->getEnergy();
}
ReferenceCalcGBVIForceKernel::~ReferenceCalcGBVIForceKernel() {
if (gbvi) {
delete gbvi;
}
}
void ReferenceCalcGBVIForceKernel::initialize(const System& system, const GBVIForce& force, const std::vector<double> & inputScaledRadii ) {
int numParticles = system.getNumParticles();
charges.resize(numParticles);
vector<RealOpenMM> atomicRadii(numParticles);
vector<RealOpenMM> scaledRadii(numParticles);
vector<RealOpenMM> gammas(numParticles);
for (int i = 0; i < numParticles; ++i) {
double charge, radius, gamma;
force.getParticleParameters(i, charge, radius, gamma);
charges[i] = static_cast<RealOpenMM>(charge);
atomicRadii[i] = static_cast<RealOpenMM>(radius);
gammas[i] = static_cast<RealOpenMM>(gamma);
scaledRadii[i] = static_cast<RealOpenMM>(inputScaledRadii[i]);
}
GBVIParameters * gBVIParameters = new GBVIParameters(numParticles);
gBVIParameters->setAtomicRadii(atomicRadii);
gBVIParameters->setGammaParameters(gammas);
gBVIParameters->setScaledRadii(scaledRadii);
gBVIParameters->setSolventDielectric( static_cast<RealOpenMM>(force.getSolventDielectric()) );
gBVIParameters->setSoluteDielectric( static_cast<RealOpenMM>(force.getSoluteDielectric()) );
// If there is a NonbondedForce in this system, use it to initialize cutoffs and periodic boundary conditions.
for (int i = 0; i < system.getNumForces(); i++) {
const NonbondedForce* nonbonded = dynamic_cast<const NonbondedForce*>(&system.getForce(i));
if (nonbonded != NULL) {
if (nonbonded->getNonbondedMethod() != NonbondedForce::NoCutoff)
gBVIParameters->setUseCutoff( static_cast<RealOpenMM>(nonbonded->getCutoffDistance()));
if (nonbonded->getNonbondedMethod() == NonbondedForce::CutoffPeriodic) {
Vec3 boxVectors[3];
nonbonded->getPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]);
RealOpenMM periodicBoxSize[3];
periodicBoxSize[0] = (RealOpenMM) boxVectors[0][0];
periodicBoxSize[1] = (RealOpenMM) boxVectors[1][1];
periodicBoxSize[2] = (RealOpenMM) boxVectors[2][2];
gBVIParameters->setPeriodic(periodicBoxSize);
}
break;
}
}
gbvi = new CpuGBVI(gBVIParameters);
}
void ReferenceCalcGBVIForceKernel::executeForces(OpenMMContextImpl& context) {
RealOpenMM** posData = const_cast<RealOpenMM**>(((ReferenceFloatStreamImpl&) context.getPositions().getImpl()).getData()); // Reference code needs to be made const correct
RealOpenMM** forceData = ((ReferenceFloatStreamImpl&) context.getForces().getImpl()).getData();
RealOpenMM* bornRadii = new RealOpenMM[context.getSystem().getNumParticles()];
gbvi->computeBornRadii(posData, bornRadii, NULL );
gbvi->computeBornForces(bornRadii, posData, &charges[0], forceData);
delete[] bornRadii;
}
double ReferenceCalcGBVIForceKernel::executeEnergy(OpenMMContextImpl& context) {
RealOpenMM** posData = const_cast<RealOpenMM**>(((ReferenceFloatStreamImpl&) context.getPositions().getImpl()).getData()); // Reference code needs to be made const correct
RealOpenMM* bornRadii = new RealOpenMM[context.getSystem().getNumParticles()];
gbvi->computeBornRadii(posData, bornRadii, NULL );
RealOpenMM energy = gbvi->computeBornEnergy(bornRadii ,posData, &charges[0]);
delete[] bornRadii;
return static_cast<double>(energy);
}
ReferenceIntegrateVerletStepKernel::~ReferenceIntegrateVerletStepKernel() {
if (dynamics)
delete dynamics;
......
......@@ -37,6 +37,7 @@
#include "SimTKReference/ReferenceNeighborList.h"
class CpuObc;
class CpuGBVI;
class ReferenceAndersenThermostat;
class ReferenceBrownianDynamics;
class ReferenceStochasticDynamics;
......@@ -276,6 +277,40 @@ private:
std::vector<RealOpenMM> charges;
};
/**
* This kernel is invoked by GBVIForce to calculate the forces acting on the system.
*/
class ReferenceCalcGBVIForceKernel : public CalcGBVIForceKernel {
public:
ReferenceCalcGBVIForceKernel(std::string name, const Platform& platform) : CalcGBVIForceKernel(name, platform) {
}
~ReferenceCalcGBVIForceKernel();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the GBVIForce this kernel will be used for
* @param scaled radii the scaled radii (Eq. 5 of Labute paper)
*/
void initialize(const System& system, const GBVIForce& force, const std::vector<double> & scaledRadii);
/**
* Execute the kernel to calculate the forces.
*
* @param context the context in which to execute this kernel
*/
void executeForces(OpenMMContextImpl& context);
/**
* Execute the kernel to calculate the energy.
*
* @param context the context in which to execute this kernel
* @return the potential energy due to the GBVIForce
*/
double executeEnergy(OpenMMContextImpl& context);
private:
CpuGBVI * gbvi;
std::vector<RealOpenMM> charges;
};
/**
* This kernel is invoked by VerletIntegrator to take one time step.
*/
......
......@@ -45,6 +45,7 @@ ReferencePlatform::ReferencePlatform() {
registerKernelFactory(CalcRBTorsionForceKernel::Name(), factory);
registerKernelFactory(CalcNonbondedForceKernel::Name(), factory);
registerKernelFactory(CalcGBSAOBCForceKernel::Name(), factory);
registerKernelFactory(CalcGBVIForceKernel::Name(), factory);
registerKernelFactory(IntegrateVerletStepKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinStepKernel::Name(), factory);
registerKernelFactory(IntegrateBrownianStepKernel::Name(), factory);
......
This diff is collapsed.
/* Portions copyright (c) 2006 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __CpuGBVI_H__
#define __CpuGBVI_H__
#include "GBVIParameters.h"
#include "CpuImplicitSolvent.h"
// ---------------------------------------------------------------------------------------
class CpuGBVI : public CpuImplicitSolvent {
private:
// GB/VI parameters
GBVIParameters* _gbviParameters;
// initialize data members (more than
// one constructor, so centralize intialization here)
void _initializeGBVIDataMembers( void );
public:
/**---------------------------------------------------------------------------------------
Constructor
@param implicitSolventParameters ImplicitSolventParameters reference
@return CpuImplicitSolvent object
--------------------------------------------------------------------------------------- */
CpuGBVI( ImplicitSolventParameters* gbviParameters );
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~CpuGBVI( );
/**---------------------------------------------------------------------------------------
Return GBVIParameters
@return GBVIParameters
--------------------------------------------------------------------------------------- */
GBVIParameters* getGBVIParameters( void ) const;
/**---------------------------------------------------------------------------------------
Set ImplicitSolventParameters
@param ImplicitSolventParameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setGBVIParameters( GBVIParameters* gbviParameters );
/**---------------------------------------------------------------------------------------
Get Born radii based on Eq. 3 of Labute paper [JCC 29 p. 1693-1698 2008])
@param atomCoordinates atomic coordinates
@param bornRadii output array of Born radii
@param gbviChain not used
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int computeBornRadii( RealOpenMM** atomCoordinates, RealOpenMM* bornRadii,
RealOpenMM* gbviChain = NULL );
/**---------------------------------------------------------------------------------------
Get Born energy and forces (not used)
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return force array
--------------------------------------------------------------------------------------- */
int computeBornEnergyForces( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces );
int computeBornEnergyForcesPrint( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces );
/**---------------------------------------------------------------------------------------
Get state
title title (optional)
@return state string
--------------------------------------------------------------------------------------- */
std::string getStateString( const char* title ) const;
/**---------------------------------------------------------------------------------------
Write Born energy and forces (Simbios)
@param atomCoordinates atomic coordinates
@param partialCharges partial atom charges
@param forces force array
@param resultsFileName output file name
@return SimTKOpenMMCommon::DefaultReturn if file opened; else return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int writeBornEnergyForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces,
const std::string& resultsFileName ) const;
/**---------------------------------------------------------------------------------------
Write results from first loop
@param atomCoordinates atomic coordinates
@param RealOpenMM forces forces
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
static int writeForceLoop1( int numberOfAtoms, RealOpenMM** forces, const RealOpenMM* bornForce,
const std::string& outputFileName );
/**---------------------------------------------------------------------------------------
Write results
@param numberOfAtoms number of atoms
@param chunkSizes vector of chunk sizes for realRealOpenMMVector
@param realRealOpenMMVector vector of RealOpenMM**
@param realVector vector of RealOpenMM*
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
static int writeForceLoop( int numberOfAtoms, const IntVector& chunkSizes,
const RealOpenMMPtrPtrVector& realRealOpenMMVector,
const RealOpenMMPtrVector& realVector,
const std::string& outputFileName );
/**---------------------------------------------------------------------------------------
Get volume Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return volume
--------------------------------------------------------------------------------------- */
static RealOpenMM getVolume( RealOpenMM r, RealOpenMM R, RealOpenMM S );
/**---------------------------------------------------------------------------------------
Get L (analytical solution for volume integrals)
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return L value (Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static RealOpenMM getL( RealOpenMM r, RealOpenMM x, RealOpenMM S );
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt r
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static RealOpenMM dL_dr( RealOpenMM r, RealOpenMM x, RealOpenMM S );
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt x
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static RealOpenMM dL_dx( RealOpenMM r, RealOpenMM x, RealOpenMM S );
/**---------------------------------------------------------------------------------------
Sgb function
@param t r*r*G_i*G_j
@return Sgb (p. 1694 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static RealOpenMM Sgb( RealOpenMM t );
/**---------------------------------------------------------------------------------------
Get GB/VI energy
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@return energy
--------------------------------------------------------------------------------------- */
RealOpenMM computeBornEnergy( const RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges );
/**---------------------------------------------------------------------------------------
Get GB/VI forces
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces output forces
@return SimTKOpenMMCommon::DefaultReturn;
--------------------------------------------------------------------------------------- */
int computeBornForces( const RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** inputForces );
/**---------------------------------------------------------------------------------------
Get volume Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return volume
--------------------------------------------------------------------------------------- */
static double getVolumeD( double r, double R, double S );
/**---------------------------------------------------------------------------------------
Get L (analytical solution for volume integrals)
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return L value (Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static double getLD( double r, double x, double S );
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt r
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static double dL_drD( double r, double x, double S );
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt x
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static double dL_dxD( double r, double x, double S );
};
// ---------------------------------------------------------------------------------------
#endif // __CpuGBVI_H__
This diff is collapsed.
/* Portions copyright (c) 2006-2009 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __GBVIParameters_H__
#define __GBVIParameters_H__
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "ImplicitSolventParameters.h"
// ---------------------------------------------------------------------------------------
class GBVIParameters : public ImplicitSolventParameters {
public:
static const std::string ParameterFileName;
private:
// scaled radii
int _ownScaledRadii;
RealOpenMM* _scaledRadii;
// gamma parameters
int _ownGammaParameters;
RealOpenMM* _gammaParameters;
// cutoff and periodic boundary conditions
bool cutoff;
bool periodic;
RealOpenMM periodicBoxSize[3];
RealOpenMM cutoffDistance;
public:
/**---------------------------------------------------------------------------------------
GBVIParameters constructor (Simbios)
@param numberOfAtoms number of atoms
--------------------------------------------------------------------------------------- */
GBVIParameters( int numberOfAtoms );
/**---------------------------------------------------------------------------------------
GBVIParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
~GBVIParameters( );
/**---------------------------------------------------------------------------------------
Return scaled radii
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* getScaledRadii( void ) const;
/**---------------------------------------------------------------------------------------
Return scaled radii
@return array
--------------------------------------------------------------------------------------- */
int setScaledRadii( RealOpenMM* scaledRadii );
#if RealOpenMMType == 2
int setScaledRadii( float* scaledRadii );
#endif
int setScaledRadii( const RealOpenMMVector& scaledRadii );
/**---------------------------------------------------------------------------------------
Set flag indicating whether scaled radii array should be deleted
@param ownScaledRadiusFactors flag indicating whether scaled radii
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOwnScaledRadii( int ownScaledRadii );
/**---------------------------------------------------------------------------------------
Get AtomicRadii array w/ dielectric offset applied
@return array of atom volumes
--------------------------------------------------------------------------------------- */
RealOpenMM* getAtomicRadii( void ) const;
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setAtomicRadii( RealOpenMM* atomicRadii );
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setAtomicRadii( const RealOpenMMVector& atomicRadii );
/**---------------------------------------------------------------------------------------
Set flag indicating whether gamma parameter array should be deleted
@param ownGammaParameters flag indicating whether gamma parameter
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOwnGammaParameters( int ownGammaParameters );
/**---------------------------------------------------------------------------------------
Get GammaParameters array
@return array of gamma values
--------------------------------------------------------------------------------------- */
RealOpenMM* getGammaParameters( void ) const;
/**---------------------------------------------------------------------------------------
Set GammaParameters array
@param gammaParameters array of gamma parameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setGammaParameters( RealOpenMM* gammaParameters );
/**---------------------------------------------------------------------------------------
Set GammaParameters array
@param gammaParameters array of gamma parameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setGammaParameters( const RealOpenMMVector& gammaParameters );
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string
--------------------------------------------------------------------------------------- */
std::string getStateString( const char* title ) const;
/**---------------------------------------------------------------------------------------
Return zero value if all parameters set; else return nonzero
@return ready status
--------------------------------------------------------------------------------------- */
int isNotReady( void ) const;
/**---------------------------------------------------------------------------------------
Set the force to use a cutoff.
@param distance the cutoff distance
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setUseCutoff( RealOpenMM distance );
/**---------------------------------------------------------------------------------------
Get whether to use a cutoff.
--------------------------------------------------------------------------------------- */
bool getUseCutoff();
/**---------------------------------------------------------------------------------------
Get the cutoff distance.
--------------------------------------------------------------------------------------- */
RealOpenMM getCutoffDistance();
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
@param boxSize the X, Y, and Z widths of the periodic box
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setPeriodic( RealOpenMM* boxSize );
/**---------------------------------------------------------------------------------------
Get whether to use periodic boundary conditions.
--------------------------------------------------------------------------------------- */
bool getPeriodic();
/**---------------------------------------------------------------------------------------
Get the periodic box dimension
--------------------------------------------------------------------------------------- */
const RealOpenMM* getPeriodicBox();
/**---------------------------------------------------------------------------------------
Get tau prefactor
@return (1/e1 - 1/e0), where e1 = solute dielectric, e0 = solvent dielectric
--------------------------------------------------------------------------------------- */
RealOpenMM getTau( void ) const;
};
#endif // __GBVIParameters_H__
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2009 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the reference implementation of GBVIForce.
*/
#include "../../../tests/AssertionUtilities.h"
#include "OpenMMContext.h"
#include "ReferencePlatform.h"
#include "HarmonicBondForce.h"
#include "GBVIForce.h"
#include "GBSAOBCForce.h"
#include "System.h"
#include "LangevinIntegrator.h"
#include "NonbondedForce.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "../src/sfmt/SFMT.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testSingleParticle() {
ReferencePlatform platform;
System system(1, 0);
system.setParticleMass(0, 2.0);
LangevinIntegrator integrator(0, 0.1, 0.01);
GBVIForce* forceField = new GBVIForce(1);
double charge = 0.0;
double radius = 0.15;
double gamma = 1.0;
forceField->setParticleParameters(0, charge, radius, gamma);
system.addForce(forceField);
OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(1);
positions[0] = Vec3(0, 0, 0);
context.setPositions(positions);
State state = context.getState(State::Energy);
double bornRadius = radius;
double eps0 = EPSILON0;
double tau = (1.0/forceField->getSoluteDielectric()-1.0/forceField->getSolventDielectric());
double bornEnergy = (-charge*charge/(8*PI_M*eps0))*tau/bornRadius;
double nonpolarEnergy = -CAL2JOULE*gamma*tau*std::pow( radius/bornRadius, 3.0);
double expectedE = (bornEnergy+nonpolarEnergy);
double obtainedE = state.getPotentialEnergy();
double diff = fabs( obtainedE - expectedE );
(void) fprintf( stderr, "testSingleParticle expected=%14.6e obtained=%14.6e diff=%14.6e breakdown:[%14.6e %14.6e]\n",
expectedE, obtainedE, diff, bornEnergy, nonpolarEnergy );
ASSERT_EQUAL_TOL((bornEnergy+nonpolarEnergy), state.getPotentialEnergy(), 0.01);
}
/*
void testCutoffAndPeriodic() {
ReferencePlatform platform;
System system(2, 0);
LangevinIntegrator integrator(0, 0.1, 0.01);
GBSAOBCForce* gbsa = new GBSAOBCForce(2);
NonbondedForce* nonbonded = new NonbondedForce(2, 0);
gbsa->setParticleParameters(0, -1, 0.15, 1);
nonbonded->setParticleParameters(0, -1, 1, 0);
gbsa->setParticleParameters(1, 1, 0.15, 1);
nonbonded->setParticleParameters(1, 1, 1, 0);
const double cutoffDistance = 3.0;
const double boxSize = 10.0;
nonbonded->setCutoffDistance(cutoffDistance);
nonbonded->setPeriodicBoxVectors(Vec3(boxSize, 0, 0), Vec3(0, boxSize, 0), Vec3(0, 0, boxSize));
system.addForce(gbsa);
system.addForce(nonbonded);
vector<Vec3> positions(2);
positions[0] = Vec3(0, 0, 0);
positions[1] = Vec3(2, 0, 0);
// Calculate the forces for both cutoff and periodic with two different atom positions.
nonbonded->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
OpenMMContext context(system, integrator, platform);
context.setPositions(positions);
State state1 = context.getState(State::Forces);
nonbonded->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
context.reinitialize();
context.setPositions(positions);
State state2 = context.getState(State::Forces);
positions[1][0]+= boxSize;
nonbonded->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
context.reinitialize();
context.setPositions(positions);
State state3 = context.getState(State::Forces);
nonbonded->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
context.reinitialize();
context.setPositions(positions);
State state4 = context.getState(State::Forces);
// All forces should be identical, exception state3 which should be zero.
ASSERT_EQUAL_VEC(state1.getForces()[0], state2.getForces()[0], 0.01);
ASSERT_EQUAL_VEC(state1.getForces()[1], state2.getForces()[1], 0.01);
ASSERT_EQUAL_VEC(state1.getForces()[0], state4.getForces()[0], 0.01);
ASSERT_EQUAL_VEC(state1.getForces()[1], state4.getForces()[1], 0.01);
ASSERT_EQUAL_VEC(state3.getForces()[0], Vec3(0, 0, 0), 0.01);
ASSERT_EQUAL_VEC(state3.getForces()[1], Vec3(0, 0, 0), 0.01);
}
*/
void testEnergyEthane() {
ReferencePlatform platform;
const int numParticles = 8;
System system(numParticles, 0);
LangevinIntegrator integrator(0, 0.1, 0.01);
//void HarmonicBondForce::getBondParameters(int index, int& particle1, int& particle2, double& length, double& k)
double C_HBondDistance = 0.1097;
double C_CBondDistance = 0.1504;
HarmonicBondForce* bonds = new HarmonicBondForce(7);
bonds->setBondParameters(0, 0, 1, C_HBondDistance, 0.0);
bonds->setBondParameters(1, 2, 1, C_HBondDistance, 0.0);
bonds->setBondParameters(2, 3, 1, C_HBondDistance, 0.0);
bonds->setBondParameters(3, 1, 4, C_CBondDistance, 0.0);
bonds->setBondParameters(4, 5, 4, C_HBondDistance, 0.0);
bonds->setBondParameters(5, 6, 4, C_HBondDistance, 0.0);
bonds->setBondParameters(6, 7, 4, C_HBondDistance, 0.0);
system.addForce(bonds);
double C_radius, C_gamma, C_charge, H_radius, H_gamma, H_charge;
int AM1_BCC = 1;
H_charge = -0.053;
C_charge = -3.0*H_charge;
if( AM1_BCC ){
C_radius = 0.180;
C_gamma = -0.2863;
H_radius = 0.125;
H_gamma = 0.2437;
} else {
C_radius = 0.215;
C_gamma = -1.1087;
H_radius = 0.150;
H_gamma = 0.1237;
}
int VI = 1;
if( VI ){
(void) fprintf( stderr, "Applying GB/VI\n" );
GBVIForce* forceField = new GBVIForce(numParticles);
for( int i = 0; i < numParticles; i++ ){
forceField->setParticleParameters(i, H_charge, H_radius, H_gamma);
}
forceField->setParticleParameters(1, C_charge, C_radius, C_gamma);
forceField->setParticleParameters(4, C_charge, C_radius, C_gamma);
system.addForce(forceField);
} else {
(void) fprintf( stderr, "Applying GBSA OBC\n" );
GBSAOBCForce* forceField = new GBSAOBCForce(numParticles);
double H_scale = 0.85;
double C_scale = 0.72;
for( int i = 0; i < numParticles; i++ ){
forceField->setParticleParameters(i, H_charge, H_radius, H_scale );
}
forceField->setParticleParameters(1, C_charge, C_radius, C_scale);
forceField->setParticleParameters(4, C_charge, C_radius, C_scale);
system.addForce(forceField);
}
OpenMMContext context(system, integrator, platform);
/*
0.5480 1.7661 0.0000 H 0 0 0 0 0 0 0 0 0
0.7286 0.8978 0.6468 C 0 0 0 0 0 0 0 0 0
0.4974 0.0000 0.0588 H 0 0 0 0 0 0 0 0 0
0.0000 0.9459 1.4666 H 0 0 0 0 0 0 0 0 0
2.1421 0.8746 1.1615 C 0 0 0 0 0 0 0 0 0
2.3239 0.0050 1.8065 H 0 0 0 0 0 0 0 0 0
2.8705 0.8295 0.3416 H 0 0 0 0 0 0 0 0 0
2.3722 1.7711 1.7518 H 0 0 0 0 0 0 0 0 0
*/
vector<Vec3> positions(numParticles);
positions[0] = Vec3(0.5480, 1.7661, 0.0000);
positions[1] = Vec3(0.7286, 0.8978, 0.6468);
positions[2] = Vec3(0.4974, 0.0000, 0.0588);
positions[3] = Vec3(0.0000, 0.9459, 1.4666);
positions[4] = Vec3(2.1421, 0.8746, 1.1615);
positions[5] = Vec3(2.3239, 0.0050, 1.8065);
positions[6] = Vec3(2.8705, 0.8295, 0.3416);
positions[7] = Vec3(2.3722, 1.7711, 1.7518);
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
(void) fprintf( stderr, "Energy %.4e\n", state.getPotentialEnergy() );
// Take a small step in the direction of the energy gradient.
double norm = 0.0;
double forceSum[3] = { 0.0, 0.0, 0.0 };
for (int i = 0; i < numParticles; ++i) {
Vec3 f = state.getForces()[i];
(void) fprintf( stderr, "F %d [%14.6e %14.6e %14.6e]\n", i, f[0], f[1], f[2] );
norm += f[0]*f[0] + f[1]*f[1] + f[2]*f[2];
forceSum[0] += f[0];
forceSum[1] += f[1];
forceSum[2] += f[2];
}
norm = std::sqrt(norm);
(void) fprintf( stderr, "Fsum [%14.6e %14.6e %14.6e] norm=%14.6e\n", forceSum[0], forceSum[1], forceSum[2], norm );
const double delta = 1e-4;
double step = delta/norm;
for (int i = 0; i < numParticles; ++i) {
Vec3 p = positions[i];
Vec3 f = state.getForces()[i];
positions[i] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step);
}
context.setPositions(positions);
State state2 = context.getState(State::Energy);
(void) fprintf( stderr, "Energies %.8e %.8e\n", state.getPotentialEnergy(), state2.getPotentialEnergy() );
// See whether the potential energy changed by the expected amount.
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta, 0.01)
}
void testEnergyTwoParticle() {
ReferencePlatform platform;
const int numParticles = 2;
System system(numParticles, 0);
LangevinIntegrator integrator(0, 0.1, 0.01);
//void HarmonicBondForce::getBondParameters(int index, int& particle1, int& particle2, double& length, double& k)
double C_HBondDistance = 3.0;
HarmonicBondForce* bonds = new HarmonicBondForce(1);
bonds->setBondParameters(0, 0, 1, C_HBondDistance, 0.0);
system.addForce(bonds);
double C_radius, C_gamma, C_charge, H_radius, H_gamma, H_charge;
/*
H_charge = -1.0;
C_charge = 1.0;
H_gamma = 1.0;
C_gamma = 1.0;
H_radius = 1.0;
C_radius = 1.0;
*/
H_charge = -0.5;
C_charge = 0.5;
H_gamma = 0.5;
C_gamma = 0.5;
H_radius = 1.5;
C_radius = 1.5;
int VI = 1;
if( VI ){
(void) fprintf( stderr, "Applying GB/VI\n" );
GBVIForce* forceField = new GBVIForce(numParticles);
forceField->setParticleParameters(0, H_charge, H_radius, H_gamma);
forceField->setParticleParameters(1, C_charge, C_radius, C_gamma);
system.addForce(forceField);
} else {
(void) fprintf( stderr, "Applying GBSA OBC\n" );
GBSAOBCForce* forceField = new GBSAOBCForce(numParticles);
forceField->setParticleParameters(0, H_charge, H_radius, 1.0);
forceField->setParticleParameters(1, C_charge, C_radius, 1.0);
system.addForce(forceField);
}
OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(numParticles);
positions[0] = Vec3( 0.0000, 0.0000, 0.0000);
positions[1] = Vec3(C_HBondDistance, 0.0000, 0.0000);
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
// Take a small step in the direction of the energy gradient.
double norm = 0.0;
double forceSum[3] = { 0.0, 0.0, 0.0 };
for (int i = 0; i < numParticles; ++i) {
Vec3 f = state.getForces()[i];
(void) fprintf( stderr, "F %d [%14.6e %14.6e %14.6e]\n", i, f[0], f[1], f[2] );
norm += f[0]*f[0] + f[1]*f[1] + f[2]*f[2];
forceSum[0] += f[0];
forceSum[1] += f[1];
forceSum[2] += f[2];
}
norm = std::sqrt(norm);
(void) fprintf( stderr, "Fsum [%14.6e %14.6e %14.6e] norm=%14.6e\n", forceSum[0], forceSum[1], forceSum[2], norm );
const double delta = 1e-4;
double step = delta/norm;
for (int i = 0; i < numParticles; ++i) {
Vec3 p = positions[i];
Vec3 f = state.getForces()[i];
positions[i] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step);
}
context.setPositions(positions);
State state2 = context.getState(State::Energy);
double diff = fabs( norm - (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta );
(void) fprintf( stderr, "Energies %14.6e %14.6e diff=%14.6e [%14.6e %14.6e]\n",
state.getPotentialEnergy(), state2.getPotentialEnergy(), diff, norm, (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta );
// See whether the potential energy changed by the expected amount.
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta, 0.01)
}
int main() {
try {
/*
testSingleParticle();
testCutoffAndPeriodic();
testForce();
testEnergyEthane();
testEnergy1();
*/
// testSingleParticle();
testEnergyTwoParticle();
testEnergyEthane();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
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