Commit 2d2f05ce authored by Andy Simmonett's avatar Andy Simmonett
Browse files

Merge branch 'master' of github.com:pandegroup/openmm into genpt

parents 94823d84 4d32047c
......@@ -128,21 +128,15 @@ State RPMDIntegrator::getState(int copy, int types, bool enforcePeriodicBox, int
center *= 1.0/molecules[i].size();
// Find the displacement to move it into the first periodic box.
int xcell = (int) floor(center[0]/periodicBoxSize[0][0]);
int ycell = (int) floor(center[1]/periodicBoxSize[1][1]);
int zcell = (int) floor(center[2]/periodicBoxSize[2][2]);
double dx = xcell*periodicBoxSize[0][0];
double dy = ycell*periodicBoxSize[1][1];
double dz = zcell*periodicBoxSize[2][2];
Vec3 diff;
diff += periodicBoxSize[2]*floor(center[2]/periodicBoxSize[2][2]);
diff += periodicBoxSize[1]*floor((center[1]-diff[1])/periodicBoxSize[1][1]);
diff += periodicBoxSize[0]*floor((center[0]-diff[0])/periodicBoxSize[0][0]);
// Translate all the particles in the molecule.
for (int j = 0; j < (int) molecules[i].size(); j++) {
Vec3& pos = positions[molecules[i][j]];
pos[0] -= dx;
pos[1] -= dy;
pos[2] -= dz;
pos -= diff;
}
}
......@@ -170,7 +164,7 @@ double RPMDIntegrator::computeKineticEnergy() {
void RPMDIntegrator::step(int steps) {
if (context == NULL)
throw OpenMMException("This Integrator is not bound to a context!");
throw OpenMMException("This Integrator is not bound to a context!");
if (!hasSetPosition) {
// Initialize the positions from the context.
......
......@@ -75,6 +75,6 @@ SET_TARGET_PROPERTIES(${SHARED_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS
INSTALL(TARGETS ${SHARED_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/plugins)
IF(BUILD_TESTING)
IF(BUILD_TESTING AND OPENMM_BUILD_REFERENCE_TESTS)
SUBDIRS (tests)
ENDIF(BUILD_TESTING)
ENDIF(BUILD_TESTING AND OPENMM_BUILD_REFERENCE_TESTS)
......@@ -6,6 +6,8 @@ INSTALL_FILES(/include/openmm/serialization FILES ${CMAKE_CURRENT_SOURCE_DIR}/in
INSTALL_FILES(/include/openmm/serialization FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/openmm/serialization/SerializationProxy.h)
INSTALL_FILES(/include/openmm/serialization FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/openmm/serialization/XmlSerializer.h)
IF(BUILD_TESTING)
SET(OPENMM_BUILD_SERIALIZATION_TESTS TRUE CACHE BOOL "Whether to build serialization test cases")
MARK_AS_ADVANCED(OPENMM_BUILD_SERIALIZATION_TESTS)
IF(BUILD_TESTING AND OPENMM_BUILD_SERIALIZATION_TESTS)
ADD_SUBDIRECTORY(tests)
ENDIF(BUILD_TESTING)
ENDIF(BUILD_TESTING AND OPENMM_BUILD_SERIALIZATION_TESTS)
#ifndef OPENMM_COMPOUND_INTEGRATOR_PROXY_H_
#define OPENMM_COMPOUND_INTEGRATOR_PROXY_H_
#include "openmm/serialization/XmlSerializer.h"
namespace OpenMM {
class CompoundIntegratorProxy : public SerializationProxy {
public:
CompoundIntegratorProxy();
void serialize(const void* object, SerializationNode& node) const;
void* deserialize(const SerializationNode& node) const;
};
}
#endif /*OPENMM_COMPOUND_INTEGRATOR_PROXY_H_*/
\ No newline at end of file
......@@ -105,7 +105,7 @@ public:
/**
* Determine whether this node has a property with a particular node.
*
* @param the name of the property to check for
* @param name the name of the property to check for
*/
bool hasProperty(const std::string& name) const;
/**
......
#ifndef OPENMM_GBVIFORCEFIELDIMPL_H_
#define OPENMM_GBVIFORCEFIELDIMPL_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
......@@ -9,7 +6,7 @@
* 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. *
* Portions copyright (c) 2015 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -32,46 +29,29 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "ForceImpl.h"
#include "openmm/GBVIForce.h"
#include "openmm/Kernel.h"
#include <string>
namespace OpenMM {
/**
* This is the internal implementation of GBVIForce.
*/
class GBVIForceImpl : public ForceImpl {
public:
GBVIForceImpl(const GBVIForce& owner);
void initialize(ContextImpl& context);
const GBVIForce& getOwner() const {
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;
// if bond info not set, then use bond forces/constraints
int getBondsFromForces(ContextImpl& context);
void updateContextState(ContextImpl& context) {
// This force field doesn't update the state directly.
}
double calcForcesAndEnergy(ContextImpl& context, bool includeForces, bool includeEnergy, int groups);
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:
const GBVIForce& owner;
Kernel kernel;
};
} // namespace OpenMM
#endif /*OPENMM_GBVIFORCEFIELDIMPL_H_*/
#include "openmm/serialization/CompoundIntegratorProxy.h"
#include <OpenMM.h>
using namespace std;
using namespace OpenMM;
CompoundIntegratorProxy::CompoundIntegratorProxy() : SerializationProxy("CompoundIntegrator") {
}
void CompoundIntegratorProxy::serialize(const void* object, SerializationNode& node) const {
node.setIntProperty("version", 1);
const CompoundIntegrator& integrator = *reinterpret_cast<const CompoundIntegrator*>(object);
node.setIntProperty("currentIntegrator", integrator.getCurrentIntegrator());
for (int i = 0; i < integrator.getNumIntegrators(); i++)
node.createChildNode("Integrator", &integrator.getIntegrator(i));
}
void* CompoundIntegratorProxy::deserialize(const SerializationNode& node) const {
if (node.getIntProperty("version") != 1)
throw OpenMMException("Unsupported version number");
CompoundIntegrator *integrator = new CompoundIntegrator();
for (int i = 0; i < node.getChildren().size(); i++)
integrator->addIntegrator(node.getChildren()[i].decodeObject<Integrator>());
integrator->setCurrentIntegrator(node.getIntProperty("currentIntegrator"));
return integrator;
}
\ No newline at end of file
/* -------------------------------------------------------------------------- *
* 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) 2010-2014 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 "openmm/serialization/GBVIForceProxy.h"
#include "openmm/serialization/SerializationNode.h"
#include "openmm/Force.h"
#include "openmm/GBVIForce.h"
#include <sstream>
using namespace OpenMM;
using namespace std;
GBVIForceProxy::GBVIForceProxy() : SerializationProxy("GBVIForce") {
}
void GBVIForceProxy::serialize(const void* object, SerializationNode& node) const {
node.setIntProperty("version", 2);
const GBVIForce& force = *reinterpret_cast<const GBVIForce*>(object);
node.setIntProperty("forceGroup", force.getForceGroup());
node.setIntProperty("method", (int) force.getNonbondedMethod());
node.setIntProperty("scalingMethod", (int) force.getBornRadiusScalingMethod());
node.setDoubleProperty("quinticLowerLimitFactor", force.getQuinticLowerLimitFactor());
node.setDoubleProperty("quinticUpperBornRadiusLimit", force.getQuinticUpperBornRadiusLimit());
node.setDoubleProperty("cutoff", force.getCutoffDistance());
node.setDoubleProperty("soluteDielectric", force.getSoluteDielectric());
node.setDoubleProperty("solventDielectric", force.getSolventDielectric());
SerializationNode& particles = node.createChildNode("Particles");
for (int i = 0; i < force.getNumParticles(); i++) {
double charge, radius, gamma;
force.getParticleParameters(i, charge, radius, gamma);
particles.createChildNode("Particle").setDoubleProperty("q", charge).setDoubleProperty("r", radius).setDoubleProperty("gamma", gamma);
}
SerializationNode& bonds = node.createChildNode("Bonds");
for (int i = 0; i < force.getNumBonds(); i++) {
int particle1, particle2;
double distance;
force.getBondParameters(i, particle1, particle2, distance);
bonds.createChildNode("Bond").setIntProperty("p1", particle1).setIntProperty("p2", particle2).setDoubleProperty("d", distance);
}
}
void* GBVIForceProxy::deserialize(const SerializationNode& node) const {
if (node.getIntProperty("version") != 1 && node.getIntProperty("version") != 2)
throw OpenMMException("Unsupported version number");
GBVIForce* force = new GBVIForce();
try {
force->setForceGroup(node.getIntProperty("forceGroup", 0));
force->setNonbondedMethod((GBVIForce::NonbondedMethod) node.getIntProperty("method"));
force->setCutoffDistance(node.getDoubleProperty("cutoff"));
force->setSoluteDielectric(node.getDoubleProperty("soluteDielectric"));
force->setSolventDielectric(node.getDoubleProperty("solventDielectric"));
if( node.getIntProperty("version") >= 2 ){
force->setBornRadiusScalingMethod( (GBVIForce::BornRadiusScalingMethod) node.getIntProperty( "scalingMethod"));
force->setQuinticLowerLimitFactor(node.getDoubleProperty("quinticLowerLimitFactor"));
force->setQuinticUpperBornRadiusLimit(node.getDoubleProperty("quinticUpperBornRadiusLimit"));
}
const SerializationNode& particles = node.getChildNode("Particles");
for (int i = 0; i < (int) particles.getChildren().size(); i++) {
const SerializationNode& particle = particles.getChildren()[i];
force->addParticle(particle.getDoubleProperty("q"), particle.getDoubleProperty("r"), particle.getDoubleProperty("gamma"));
}
const SerializationNode& bonds = node.getChildNode("Bonds");
for (int i = 0; i < (int) bonds.getChildren().size(); i++) {
const SerializationNode& bond = bonds.getChildren()[i];
force->addBond(bond.getIntProperty("p1"), bond.getIntProperty("p2"), bond.getDoubleProperty("d"));
}
}
catch (...) {
delete force;
throw;
}
return force;
}
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010-2014 Stanford University and the Authors. *
* Portions copyright (c) 2010-2015 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -33,6 +33,7 @@
#include "openmm/BrownianIntegrator.h"
#include "openmm/CMAPTorsionForce.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/CompoundIntegrator.h"
#include "openmm/CustomAngleForce.h"
#include "openmm/CustomBondForce.h"
#include "openmm/CustomCompoundBondForce.h"
......@@ -44,7 +45,6 @@
#include "openmm/CustomNonbondedForce.h"
#include "openmm/CustomTorsionForce.h"
#include "openmm/GBSAOBCForce.h"
#include "openmm/GBVIForce.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/LangevinIntegrator.h"
......@@ -65,6 +65,7 @@
#include "openmm/serialization/AndersenThermostatProxy.h"
#include "openmm/serialization/CMAPTorsionForceProxy.h"
#include "openmm/serialization/CMMotionRemoverProxy.h"
#include "openmm/serialization/CompoundIntegratorProxy.h"
#include "openmm/serialization/CustomAngleForceProxy.h"
#include "openmm/serialization/CustomBondForceProxy.h"
#include "openmm/serialization/CustomCompoundBondForceProxy.h"
......@@ -76,7 +77,6 @@
#include "openmm/serialization/CustomNonbondedForceProxy.h"
#include "openmm/serialization/CustomTorsionForceProxy.h"
#include "openmm/serialization/GBSAOBCForceProxy.h"
#include "openmm/serialization/GBVIForceProxy.h"
#include "openmm/serialization/HarmonicAngleForceProxy.h"
#include "openmm/serialization/HarmonicBondForceProxy.h"
#include "openmm/serialization/LangevinIntegratorProxy.h"
......@@ -112,6 +112,7 @@ extern "C" void registerSerializationProxies() {
SerializationProxy::registerProxy(typeid(BrownianIntegrator), new BrownianIntegratorProxy());
SerializationProxy::registerProxy(typeid(CMAPTorsionForce), new CMAPTorsionForceProxy());
SerializationProxy::registerProxy(typeid(CMMotionRemover), new CMMotionRemoverProxy());
SerializationProxy::registerProxy(typeid(CompoundIntegrator), new CompoundIntegratorProxy());
SerializationProxy::registerProxy(typeid(Continuous1DFunction), new Continuous1DFunctionProxy());
SerializationProxy::registerProxy(typeid(Continuous2DFunction), new Continuous2DFunctionProxy());
SerializationProxy::registerProxy(typeid(Continuous3DFunction), new Continuous3DFunctionProxy());
......@@ -129,7 +130,6 @@ extern "C" void registerSerializationProxies() {
SerializationProxy::registerProxy(typeid(Discrete2DFunction), new Discrete2DFunctionProxy());
SerializationProxy::registerProxy(typeid(Discrete3DFunction), new Discrete3DFunctionProxy());
SerializationProxy::registerProxy(typeid(GBSAOBCForce), new GBSAOBCForceProxy());
SerializationProxy::registerProxy(typeid(GBVIForce), new GBVIForceProxy());
SerializationProxy::registerProxy(typeid(HarmonicAngleForce), new HarmonicAngleForceProxy());
SerializationProxy::registerProxy(typeid(HarmonicBondForce), new HarmonicBondForceProxy());
SerializationProxy::registerProxy(typeid(LangevinIntegrator), new LangevinIntegratorProxy());
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2015 Stanford University and the Authors. *
* Authors: Peter Eastman, Yutong Zhao *
* Contributors: *
* *
......@@ -32,6 +32,7 @@
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/BrownianIntegrator.h"
#include "openmm/CompoundIntegrator.h"
#include "openmm/CustomIntegrator.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/VariableLangevinIntegrator.h"
......@@ -185,6 +186,29 @@ void testSerializeCustomIntegrator() {
delete intg2;
}
void testSerializeCompoundIntegrator() {
CompoundIntegrator integ;
integ.addIntegrator(new LangevinIntegrator(372.4, 1.234, 0.0018));
integ.addIntegrator(new VerletIntegrator(0.002));
integ.setCurrentIntegrator(1);
stringstream ss;
XmlSerializer::serialize<Integrator>(&integ, "CompoundIntegrator", ss);
CompoundIntegrator *integ2 = dynamic_cast<CompoundIntegrator*>(XmlSerializer::deserialize<Integrator>(ss));
ASSERT_EQUAL(integ.getCurrentIntegrator(), integ2->getCurrentIntegrator());
LangevinIntegrator& langevin1 = dynamic_cast<LangevinIntegrator&>(integ.getIntegrator(0));
LangevinIntegrator& langevin2 = dynamic_cast<LangevinIntegrator&>(integ2->getIntegrator(0));
ASSERT_EQUAL(langevin1.getConstraintTolerance(), langevin2.getConstraintTolerance());
ASSERT_EQUAL(langevin1.getStepSize(), langevin2.getStepSize());
ASSERT_EQUAL(langevin1.getTemperature(), langevin2.getTemperature());
ASSERT_EQUAL(langevin1.getFriction(), langevin2.getFriction());
ASSERT_EQUAL(langevin1.getRandomNumberSeed(), langevin2.getRandomNumberSeed());
VerletIntegrator& verlet1 = dynamic_cast<VerletIntegrator&>(integ.getIntegrator(1));
VerletIntegrator& verlet2 = dynamic_cast<VerletIntegrator&>(integ2->getIntegrator(1));
ASSERT_EQUAL(verlet1.getConstraintTolerance(), verlet2.getConstraintTolerance());
ASSERT_EQUAL(verlet1.getStepSize(), verlet2.getStepSize());
delete integ2;
}
int main() {
try {
testSerializeBrownianIntegrator();
......@@ -193,6 +217,7 @@ int main() {
testSerializeVariableLangevinIntegrator();
testSerializeVariableVerletIntegrator();
testSerializeLangevinIntegrator();
testSerializeCompoundIntegrator();
}
catch(const exception& e) {
return 1;
......
......@@ -6,7 +6,7 @@
* 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. *
* Portions copyright (c) 2015 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -29,214 +29,194 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the reference implementation of GBVIForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/BrownianIntegrator.h"
#include "openmm/CompoundIntegrator.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/GBVIForce.h"
#include "openmm/GBSAOBCForce.h"
#include "openmm/System.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
ReferencePlatform platform;
const double TOL = 1e-5;
void testSingleParticle() {
void testChangingIntegrator() {
System system;
system.addParticle(2.0);
LangevinIntegrator integrator(0, 0.1, 0.01);
GBVIForce* forceField = new GBVIForce();
double charge = -1.0;
double radius = 0.15;
double gamma = 1.0;
forceField->addParticle(charge, radius, gamma);
system.addForce(forceField);
ASSERT(!forceField->usesPeriodicBoundaryConditions());
ASSERT(!system.usesPeriodicBoundaryConditions());
Context 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 = -gamma*tau*std::pow(radius/bornRadius, 3.0);
double expectedE = (bornEnergy+nonpolarEnergy);
double obtainedE = state.getPotentialEnergy();
double diff = fabs((obtainedE - expectedE)/expectedE);
ASSERT_EQUAL_TOL((bornEnergy+nonpolarEnergy), state.getPotentialEnergy(), 0.01);
}
void testEnergyEthane(int applyBornRadiiScaling) {
const int numParticles = 8;
System system;
LangevinIntegrator integrator(0, 0.1, 0.01);
// harmonic bond
double C_HBondDistance = 0.1097;
double C_CBondDistance = 0.1504;
system.addParticle(2.0);
HarmonicBondForce* bonds = new HarmonicBondForce();
bonds->addBond(0, 1, C_HBondDistance, 0.0);
bonds->addBond(2, 1, C_HBondDistance, 0.0);
bonds->addBond(3, 1, C_HBondDistance, 0.0);
bonds->addBond(1, 4, C_CBondDistance, 0.0);
bonds->addBond(5, 4, C_HBondDistance, 0.0);
bonds->addBond(6, 4, C_HBondDistance, 0.0);
bonds->addBond(7, 4, C_HBondDistance, 0.0);
bonds->addBond(0, 1, 1.5, 1);
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;
CompoundIntegrator integrator;
integrator.addIntegrator(new VerletIntegrator(0.01));
integrator.addIntegrator(new LangevinIntegrator(300.0, 10.0, 0.011));
integrator.addIntegrator(new BrownianIntegrator(300.0, 10.0, 0.012));
Context context(system, integrator, platform);
ASSERT_EQUAL(0, integrator.getCurrentIntegrator());
vector<Vec3> positions(2);
positions[0] = Vec3(-1, 0, 0);
positions[1] = Vec3(1, 0, 0);
for (int iteration = 0; iteration < 2; ++iteration) {
context.setPositions(positions);
// First integrate with the Verlet integrator and compare it to the analytical solution.
const double freq = 1.0;
State state = context.getState(State::Energy);
const double initialEnergy = state.getKineticEnergy()+state.getPotentialEnergy();
for (int i = 0; i < 100; ++i) {
state = context.getState(State::Positions | State::Velocities | State::Energy);
double time = state.getTime();
double expectedDist = 1.5+0.5*std::cos(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 0.02);
double expectedSpeed = -0.5*freq*std::sin(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedSpeed, 0, 0), state.getVelocities()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedSpeed, 0, 0), state.getVelocities()[1], 0.02);
double energy = state.getKineticEnergy()+state.getPotentialEnergy();
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
integrator.step(1);
}
ASSERT_EQUAL_TOL(100*0.01, context.getState(0).getTime(), 1e-5);
// Switch to the Langevin integrator and make sure that it heats up.
integrator.setCurrentIntegrator(1);
integrator.step(100);
double ke = 0.0;
for (int i = 0; i < 1000; ++i) {
integrator.step(10);
state = context.getState(State::Energy);
ke += state.getKineticEnergy();
}
double expectedKE = 0.5*2*3*BOLTZ*300.0;
ASSERT_USUALLY_EQUAL_TOL(expectedKE, ke/1000, 0.1);
ASSERT_EQUAL_TOL(100*0.01+10100*0.011, context.getState(0).getTime(), 1e-5);
// Now reinitialize the context and repeat all of these tests to make sure that works correctly.
context.reinitialize();
integrator.setCurrentIntegrator(0);
}
}
NonbondedForce* nonbonded = new NonbondedForce();
nonbonded->setNonbondedMethod(NonbondedForce::NoCutoff);
GBVIForce* forceField = new GBVIForce();
if (applyBornRadiiScaling) {
forceField->setBornRadiusScalingMethod(GBVIForce::QuinticSpline);
void testChangingParameters() {
System system;
system.addParticle(1.0);
CompoundIntegrator integrator;
integrator.addIntegrator(new VerletIntegrator(0.01));
integrator.addIntegrator(new LangevinIntegrator(300.0, 10.0, 0.02));
integrator.addIntegrator(new BrownianIntegrator(300.0, 10.0, 0.03));
// Try getting and setting the step size for different component integrators.
for (int i = 0; i < 3; i++) {
integrator.setCurrentIntegrator(i);
ASSERT_EQUAL_TOL(0.01*(i+1), integrator.getStepSize(), 1e-7);
}
else {
forceField->setBornRadiusScalingMethod(GBVIForce::NoScaling);
for (int i = 0; i < 3; i++) {
integrator.setCurrentIntegrator(i);
integrator.setStepSize(0.02*(i+1));
ASSERT_EQUAL_TOL(0.02*(i+1), integrator.getStepSize(), 1e-7);
}
for (int i = 0; i < numParticles; i++) {
system.addParticle(1.0);
forceField->addParticle(H_charge, H_radius, H_gamma);
nonbonded->addParticle( H_charge, H_radius, 0.0);
for (int i = 0; i < 3; i++) {
integrator.setCurrentIntegrator(i);
ASSERT_EQUAL_TOL(0.02*(i+1), integrator.getStepSize(), 1e-7);
}
forceField->setParticleParameters(1, C_charge, C_radius, C_gamma);
forceField->setParticleParameters(4, C_charge, C_radius, C_gamma);
nonbonded->setParticleParameters( 1, C_charge, C_radius, 0.0);
nonbonded->setParticleParameters( 4, C_charge, C_radius, 0.0);
forceField->addBond(0, 1, C_HBondDistance);
forceField->addBond(2, 1, C_HBondDistance);
forceField->addBond(3, 1, C_HBondDistance);
forceField->addBond(1, 4, C_CBondDistance);
forceField->addBond(5, 4, C_HBondDistance);
forceField->addBond(6, 4, C_HBondDistance);
forceField->addBond(7, 4, C_HBondDistance);
std::vector<pair<int, int> > bondExceptions;
std::vector<double> bondDistances;
bondExceptions.push_back(pair<int, int>(0, 1));
bondDistances.push_back(C_HBondDistance);
bondExceptions.push_back(pair<int, int>(2, 1));
bondDistances.push_back(C_HBondDistance);
bondExceptions.push_back(pair<int, int>(3, 1));
bondDistances.push_back(C_HBondDistance);
// Try getting and setting the constraint tolerance for different component integrators.
bondExceptions.push_back(pair<int, int>(1, 4));
bondDistances.push_back(C_CBondDistance);
bondExceptions.push_back(pair<int, int>(5, 4));
bondDistances.push_back(C_HBondDistance);
bondExceptions.push_back(pair<int, int>(6, 4));
bondDistances.push_back(C_HBondDistance);
bondExceptions.push_back(pair<int, int>(7, 4));
bondDistances.push_back(C_HBondDistance);
nonbonded->createExceptionsFromBonds(bondExceptions, 0.0, 0.0);
system.addForce(forceField);
system.addForce(nonbonded);
for (int i = 0; i < 3; i++) {
integrator.setCurrentIntegrator(i);
ASSERT_EQUAL_TOL(1e-5, integrator.getConstraintTolerance(), 1e-7);
}
for (int i = 0; i < 3; i++) {
integrator.setCurrentIntegrator(i);
integrator.setConstraintTolerance(1e-4*(i+1));
ASSERT_EQUAL_TOL(1e-4*(i+1), integrator.getConstraintTolerance(), 1e-7);
}
for (int i = 0; i < 3; i++) {
integrator.setCurrentIntegrator(i);
ASSERT_EQUAL_TOL(1e-4*(i+1), integrator.getConstraintTolerance(), 1e-7);
}
}
void testDifferentStepSizes() {
System system;
system.addParticle(2.0);
system.addParticle(2.0);
HarmonicBondForce* bonds = new HarmonicBondForce();
bonds->addBond(0, 1, 1.5, 1);
system.addForce(bonds);
CompoundIntegrator integrator;
integrator.addIntegrator(new VerletIntegrator(0.005));
integrator.addIntegrator(new VerletIntegrator(0.01));
Context context(system, integrator, platform);
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);
ASSERT_EQUAL(0, integrator.getCurrentIntegrator());
vector<Vec3> positions(2);
positions[0] = Vec3(-1, 0, 0);
positions[1] = Vec3(1, 0, 0);
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];
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];
// Integrate with the first Verlet integrator and compare it to the analytical solution.
const double freq = 1.0;
double expectedTime = 0;
for (int i = 0; i < 100; ++i) {
State state = context.getState(State::Positions);
double time = state.getTime();
ASSERT_EQUAL_TOL(expectedTime, time, 1e-5);
double expectedDist = 1.5+0.5*std::cos(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 0.02);
integrator.step(1);
expectedTime += 0.005;
}
norm = std::sqrt(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);
// See whether the potential energy changed by the expected amount.
// Now switch to the second Verlet integrator which has a different step size.
integrator.setCurrentIntegrator(1);
for (int i = 0; i < 100; ++i) {
State state = context.getState(State::Positions);
double time = state.getTime();
ASSERT_EQUAL_TOL(expectedTime, time, 1e-5);
double expectedDist = 1.5+0.5*std::cos(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 0.02);
integrator.step(1);
expectedTime += 0.01;
}
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta, 0.01)
// Finally, switch back to the first one again.
integrator.setCurrentIntegrator(0);
for (int i = 0; i < 100; ++i) {
State state = context.getState(State::Positions);
double time = state.getTime();
ASSERT_EQUAL_TOL(expectedTime, time, 1e-5);
double expectedDist = 1.5+0.5*std::cos(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 0.02);
integrator.step(1);
expectedTime += 0.005;
}
}
int main() {
void runPlatformTests();
int main(int argc, char* argv[]) {
try {
testSingleParticle();
testEnergyEthane(0);
testEnergyEthane(1);
initializeTests(argc, argv);
testChangingIntegrator();
testChangingParameters();
testDifferentStepSizes();
runPlatformTests();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
......
......@@ -167,6 +167,38 @@ void testPeriodic() {
}
}
void testZeroPeriodicDistance() {
Vec3 vx(5, 0, 0);
Vec3 vy(0, 6, 0);
Vec3 vz(1, 2, 7);
double x0 = 51, y0 = -17, z0 = 11.2;
System system;
system.setDefaultPeriodicBoxVectors(vx, vy, vz);
system.addParticle(1.0);
CustomExternalForce* force = new CustomExternalForce("periodicdistance(x, y, z, x0, y0, z0)^2");
force->addPerParticleParameter("x0");
force->addPerParticleParameter("y0");
force->addPerParticleParameter("z0");
vector<double> params(3);
params[0] = x0;
params[1] = y0;
params[2] = z0;
force->addParticle(0, params);
system.addForce(force);
ASSERT(force->usesPeriodicBoundaryConditions());
ASSERT(system.usesPeriodicBoundaryConditions());
VerletIntegrator integrator(0.01);
Context context(system, integrator, platform);
vector<Vec3> positions(1);
positions[0] = Vec3(x0, y0, z0);
context.setPositions(positions);
State state = context.getState(State::Positions | State::Forces | State::Energy);
vector<Vec3> forces = state.getForces();
for (int i = 0; i < 3; i++)
ASSERT_EQUAL(forces[0][i], forces[0][i]);
}
void testIllegalVariable() {
System system;
system.addParticle(1.0);
......@@ -192,6 +224,7 @@ int main(int argc, char* argv[]) {
testForce();
testManyParameters();
testPeriodic();
testZeroPeriodicDistance();
testIllegalVariable();
runPlatformTests();
}
......
......@@ -6,8 +6,8 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010-2014 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Portions copyright (c) 2010-2015 Stanford University and the Authors. *
* Authors: Robert McGibbon *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
......@@ -30,74 +30,70 @@
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/GBVIForce.h"
#include "openmm/serialization/XmlSerializer.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <sstream>
using namespace OpenMM;
using namespace std;
void testSerialization() {
// Create a Force.
GBVIForce force;
force.setForceGroup(3);
force.setNonbondedMethod(GBVIForce::CutoffPeriodic);
force.setBornRadiusScalingMethod(GBVIForce::QuinticSpline);
force.setQuinticLowerLimitFactor(0.123);
force.setQuinticUpperBornRadiusLimit(5.123);
force.setCutoffDistance(2.0);
force.setSoluteDielectric(5.1);
force.setSolventDielectric(50.0);
force.addParticle(1, 0.1, 0.01);
force.addParticle(0.5, 0.2, 0.02);
force.addParticle(-0.5, 0.3, 0.03);
force.addBond(0, 1, 2.0);
force.addBond(3, 5, 1.2);
// Serialize and then deserialize it.
stringstream buffer;
XmlSerializer::serialize<GBVIForce>(&force, "Force", buffer);
GBVIForce* copy = XmlSerializer::deserialize<GBVIForce>(buffer);
// Compare the two forces to see if they are identical.
GBVIForce& force2 = *copy;
ASSERT_EQUAL(force.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force.getNonbondedMethod(), force2.getNonbondedMethod());
ASSERT_EQUAL(force.getCutoffDistance(), force2.getCutoffDistance());
ASSERT_EQUAL(force.getSoluteDielectric(), force2.getSoluteDielectric());
ASSERT_EQUAL(force.getSolventDielectric(), force2.getSolventDielectric());
ASSERT_EQUAL(force.getNumParticles(), force2.getNumParticles());
ASSERT_EQUAL(force.getQuinticUpperBornRadiusLimit(), force2.getQuinticUpperBornRadiusLimit());
ASSERT_EQUAL(force.getQuinticLowerLimitFactor(), force2.getQuinticLowerLimitFactor());
ASSERT_EQUAL(force.getBornRadiusScalingMethod(), force2.getBornRadiusScalingMethod());
for (int i = 0; i < force.getNumParticles(); i++) {
double charge1, radius1, scale1;
double charge2, radius2, scale2;
force.getParticleParameters(i, charge1, radius1, scale1);
force2.getParticleParameters(i, charge2, radius2, scale2);
ASSERT_EQUAL(charge1, charge2);
ASSERT_EQUAL(radius1, radius2);
ASSERT_EQUAL(scale1, scale2);
void testTruncatedOctahedron() {
const int numMolecules = 50;
const int numParticles = numMolecules*2;
const float cutoff = 2.0;
Vec3 a(6.7929, 0, 0);
Vec3 b(-2.264163559406279, 6.404455775962287, 0);
Vec3 c(-2.264163559406279, -3.2019384603140684, 5.54658849047036);
System system;
system.setDefaultPeriodicBoxVectors(a, b, c);
NonbondedForce* force = new NonbondedForce();
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
vector<Vec3> positions(numParticles);
force->setCutoffDistance(cutoff);
force->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
for (int i = 0; i < numMolecules; i++) {
system.addParticle(1.0);
system.addParticle(1.0);
force->addParticle(-1, 0.2, 0.2);
force->addParticle(1, 0.2, 0.2);
positions[2*i] = a*(5*genrand_real2(sfmt)-2) + b*(5*genrand_real2(sfmt)-2) + c*(5*genrand_real2(sfmt)-2);
positions[2*i+1] = positions[2*i] + Vec3(1.0, 0.0, 0.0);
system.addConstraint(2*i, 2*i+1, 1.0);
}
ASSERT_EQUAL(force.getNumBonds(), force2.getNumBonds());
for (int i = 0; i < force.getNumBonds(); i++) {
int a1, a2, b1, b2;
double da, db;
force.getBondParameters(i, a1, a2, da);
force2.getBondParameters(i, b1, b2, db);
ASSERT_EQUAL(a1, b1);
ASSERT_EQUAL(a2, b2);
ASSERT_EQUAL(da, db);
system.addForce(force);
VerletIntegrator integrator(0.01);
Context context(system, integrator, Platform::getPlatformByName("Reference"));
context.setPositions(positions);
State initialState = context.getState(State::Positions | State::Energy, true);
for (int i = 0; i < numMolecules; i++) {
Vec3 center = (initialState.getPositions()[2*i]+initialState.getPositions()[2*i+1])*0.5;
ASSERT(center[0] >= 0.0);
ASSERT(center[1] >= 0.0);
ASSERT(center[2] >= 0.0);
ASSERT(center[0] <= a[0]);
ASSERT(center[1] <= b[1]);
ASSERT(center[2] <= c[2]);
}
double initialEnergy = initialState.getPotentialEnergy();
context.setState(initialState);
State finalState = context.getState(State::Positions | State::Energy, true);
double finalEnergy = finalState.getPotentialEnergy();
ASSERT_EQUAL_TOL(initialEnergy, finalEnergy, 1e-4);
}
int main() {
int main(int argc, char* argv[]) {
try {
testSerialization();
testTruncatedOctahedron();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
......
......@@ -255,7 +255,7 @@ void testForce(int numParticles, NonbondedForce::NonbondedMethod method, GBSAOBC
State state2 = context.getState(State::Energy);
context.setPositions(positions3);
State state3 = context.getState(State::Energy);
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state3.getPotentialEnergy())/delta, 1e-2)
ASSERT_EQUAL_TOL(state2.getPotentialEnergy(), state3.getPotentialEnergy()+norm*delta, 1e-5)
}
}
......
......@@ -251,8 +251,8 @@ void testRandomSeed() {
for (int i = 0; i < numParticles; i++) {
for (int j = 0; j < 3; j++) {
ASSERT(state1.getPositions()[i][j] == state2.getPositions()[i][j]);
ASSERT(state3.getPositions()[i][j] == state4.getPositions()[i][j]);
ASSERT_EQUAL_TOL(state1.getPositions()[i][j], state2.getPositions()[i][j], 1e-6);
ASSERT_EQUAL_TOL(state3.getPositions()[i][j], state4.getPositions()[i][j], 1e-6);
ASSERT(state1.getPositions()[i][j] != state3.getPositions()[i][j]);
}
}
......
......@@ -78,7 +78,7 @@ void testLargeSystem() {
const int numParticles = numMolecules*2;
const double cutoff = 2.0;
const double boxSize = 4.0;
const double tolerance = 10;
const double tolerance = 15;
System system;
system.setDefaultPeriodicBoxVectors(Vec3(boxSize, 0, 0), Vec3(0, boxSize, 0), Vec3(0, 0, boxSize));
NonbondedForce* nonbonded = new NonbondedForce();
......
......@@ -149,6 +149,8 @@ void testMathFunctions() {
ASSERT_VEC4_EQUAL(max(f1, f2), 1.1, 1.9, 1.3, -3.8);
ASSERT_VEC4_EQUAL(sqrt(fvec4(1.5, 3.1, 4.0, 15.0)), sqrt(1.5), sqrt(3.1), sqrt(4.0), sqrt(15.0));
ASSERT_VEC4_EQUAL(rsqrt(fvec4(1.5, 3.1, 4.0, 15.0)), 1.0/sqrt(1.5), 1.0/sqrt(3.1), 1.0/sqrt(4.0), 1.0/sqrt(15.0));
ASSERT_VEC4_EQUAL(exp(fvec4(-2.1, -0.5, 1.5, 3.1)), expf(-2.1), expf(-0.5), expf(1.5), expf(3.1));
ASSERT_VEC4_EQUAL(log(fvec4(1.5, 3.1, 4.0, 15.0)), logf(1.5), logf(3.1), logf(4.0), logf(15.0));
ASSERT_EQUAL_TOL(f1[0]*f2[0]+f1[1]*f2[1]+f1[2]*f2[2], dot3(f1, f2), 1e-6);
ASSERT_EQUAL_TOL(f1[0]*f2[0]+f1[1]*f2[1]+f1[2]*f2[2]+f1[3]*f2[3], dot4(f1, f2), 1e-6);
ASSERT(any(f1 > 0.5));
......
......@@ -69,6 +69,7 @@ foreach(SUBDIR ${SUBDIRS})
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.str"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*psf"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/charmm22.*"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/par*.inp"
)
foreach(file ${STAGING_INPUT_FILES1})
set(STAGING_INPUT_FILES ${STAGING_INPUT_FILES} "${file}")
......
from __future__ import print_function
import re
import sys
import textwrap
from inspect import cleandoc
from numpydoc.docscrape import NumpyDocString
# Doxygen does a bad job of generating documentation based on docstrings. This script is run as a filter
# on each file, and converts the docstrings into Doxygen style comments so we get better documentation.
# Doxygen does a bad job of generating documentation based on docstrings.
# This script is run as a filter
# on each file, and converts the docstrings into Doxygen style comments
# so we get better documentation.
input = open(sys.argv[1])
while True:
line = input.readline()
if len(line) == 0:
......@@ -15,46 +24,57 @@ while True:
split = stripped.split()
if split[0] == 'class' and split[1][0].islower():
# Classes that start with a lowercase letter were defined by SWIG. We want to hide them.
print("%s## @private" % prefix)
print("%s## @private" % prefix, end='')
if split[1][0] == '_' and split[1][1] != '_':
# Names starting with a single _ are assumed to be private.
print("%s## @private" % prefix)
print("%s## @private" % prefix, end='')
# We're at the start of a class or function definition. Find all lines that contain the declaration.
declaration = line
while len(line) > 0 and line.find(':') == -1:
line = input.readline()
declaration += line
# Now look for a docstring.
docstrings = []
docstringlines = []
line = input.readline()
stripped = line.lstrip()
if stripped.startswith('"""'):
line = stripped[3:]
readingParameters = False
while line.find('"""') == -1:
docstrings.append(line)
l = line.strip()
if l.startswith('"""') or l.startswith("'''"):
if l.count('"""') == 2 or l.count("'''") == 2:
docstringlines.append(l[3:-3])
else:
docstringlines.append(l[3:])
line = input.readline()
if line.strip() == 'Parameters:':
readingParameters = True
l = line.strip()
while l.find('"""') == -1 and l.find("'''") == -1:
docstringlines.append(line.rstrip())
line = input.readline()
stripped = line.lstrip()
if readingParameters and stripped.startswith('- '):
line = "@param %s" % stripped[2:]
elif stripped.startswith('Returns:'):
line = "@return %s" % stripped[8:]
line = line[:line.find('"""')]
docstrings.append(line)
l = line.strip()
if line.rstrip().endswith('"""') or line.rstrip().endswith("'''"):
# last line
docstringlines.append(line.rstrip()[:-3])
docstring = NumpyDocString(cleandoc('\n'.join(docstringlines)))
# print(docstringlines)
# Print out the docstring in Doxygen syntax, followed by the declaration.
for s in docstrings:
print("%s##%s" % (prefix, s.strip()))
print(declaration)
if len(docstrings) == 0:
print(line)
for line in docstring['Summary']:
print('{prefix}## {line}'.format(prefix=prefix, line=line))
if len(docstring['Extended Summary']) > 0:
print('{prefix}##'.format(prefix=prefix))
for line in docstring['Extended Summary']:
print('{prefix}## {line}'.format(prefix=prefix, line=line.strip()))
print('{prefix}##'.format(prefix=prefix))
for name, type, descr in docstring['Parameters']:
print('{prefix}## @param {name} ({type}) {descr}'.format(prefix=prefix, type=type, name=name, descr=' '.join(descr)))
for name, type, descr in docstring['Returns']:
if type == '':
type = name
print('{prefix}## @return ({type}) {descr}'.format(prefix=prefix, type=type, name=name, descr=' '.join(descr)))
print(declaration, end='')
if len(docstringlines) == 0:
print(line, end='')
else:
print(line)
\ No newline at end of file
print(line, end='')
......@@ -193,6 +193,13 @@ def buildKeywordDictionary(major_version_num=MAJOR_VERSION_NUM,
if platform.system() == 'Darwin':
extra_compile_args += ['-stdlib=libc++', '-mmacosx-version-min=10.7']
extra_link_args += ['-stdlib=libc++', '-mmacosx-version-min=10.7', '-Wl', '-rpath', openmm_lib_path]
# Hard-code CC and CXX to clang, since gcc/g++ will *not* work with
# Anaconda, despite the fact that distutils will try to use them.
# System Python, homebrew, and MacPorts on Macs will always use
# clang, so this hack should always work and fix issues with users
# that have GCC installed from MacPorts or homebrew *and* Anaconda
os.environ['CC'] = 'clang'
os.environ['CXX'] = 'clang++'
library_dirs=[openmm_lib_path]
include_dirs=openmm_include_path.split(';')
......
......@@ -10,7 +10,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Peter Eastman, Steffen Lindert
Contributors:
Permission is hereby granted, free of charge, to any person obtaining a
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,
......@@ -37,22 +37,26 @@ from simtk.unit import kilojoules_per_mole, is_quantity
class AMDIntegrator(CustomIntegrator):
"""AMDIntegrator implements the aMD integration algorithm.
The system is integrated based on a modified potential. Whenever the energy V(r) is less than a
cutoff value E, the following effective potential is used:
V*(r) = V(r) + (E-V(r))^2 / (alpha+E-V(r))
For details, see Hamelberg et al., J. Chem. Phys. 127, 155102 (2007).
"""
def __init__(self, dt, alpha, E):
"""Create an AMDIntegrator.
Parameters:
- dt (time) The integration time step to use
- alpha (energy) The alpha parameter to use
- E (energy) The energy cutoff to use
Parameters
----------
dt : time
The integration time step to use
alpha : energy
The alpha parameter to use
E : energy
The energy cutoff to use
"""
CustomIntegrator.__init__(self, dt)
self.addGlobalVariable("alpha", alpha)
......@@ -64,23 +68,23 @@ class AMDIntegrator(CustomIntegrator):
self.addComputePerDof("x", "x+dt*v")
self.addConstrainPositions()
self.addComputePerDof("v", "(x-oldx)/dt")
def getAlpha(self):
"""Get the value of alpha for the integrator."""
return self.getGlobalVariable(0)*kilojoules_per_mole
def setAlpha(self, alpha):
"""Set the value of alpha for the integrator."""
self.setGlobalVariable(0, alpha)
def getE(self):
"""Get the energy threshold E for the integrator."""
return self.getGlobalVariable(1)*kilojoules_per_mole
def setE(self, E):
"""Set the energy threshold E for the integrator."""
self.setGlobalVariable(1, E)
def getEffectiveEnergy(self, energy):
"""Given the actual potential energy of the system, return the value of the effective potential."""
alpha = self.getAlpha()
......@@ -94,21 +98,26 @@ class AMDIntegrator(CustomIntegrator):
class AMDForceGroupIntegrator(CustomIntegrator):
"""AMDForceGroupIntegrator implements a single boost aMD integration algorithm.
This is similar to AMDIntegrator, but is applied based on the energy of a single force group
(typically representing torsions).
For details, see Hamelberg et al., J. Chem. Phys. 127, 155102 (2007).
"""
def __init__(self, dt, group, alphaGroup, EGroup):
"""Create a AMDForceGroupIntegrator.
Parameters:
- dt (time) The integration time step to use
- group (int) The force group to apply the boost to
- alphaGroup (energy) The alpha parameter to use for the boosted force group
- EGroup (energy) The energy cutoff to use for the boosted force group
Parameters
----------
dt : time
The integration time step to use
group : int
The force group to apply the boost to
alphaGroup : energy
The alpha parameter to use for the boosted force group
EGroup : energy
The energy cutoff to use for the boosted force group
"""
CustomIntegrator.__init__(self, dt)
self.addGlobalVariable("alphaGroup", alphaGroup)
......@@ -124,29 +133,35 @@ class AMDForceGroupIntegrator(CustomIntegrator):
self.addComputePerDof("x", "x+dt*v")
self.addConstrainPositions()
self.addComputePerDof("v", "(x-oldx)/dt")
def getAlphaGroup(self):
"""Get the value of alpha for the boosted force group."""
return self.getGlobalVariable(0)*kilojoules_per_mole
def setAlphaGroup(self, alpha):
"""Set the value of alpha for the boosted force group."""
self.setGlobalVariable(0, alpha)
def getEGroup(self):
"""Get the energy threshold E for the boosted force group."""
return self.getGlobalVariable(1)*kilojoules_per_mole
def setEGroup(self, E):
"""Set the energy threshold E for the boosted force group."""
self.setGlobalVariable(1, E)
def getEffectiveEnergy(self, groupEnergy):
"""Given the actual group energy of the system, return the value of the effective potential.
Parameters:
- groupEnergy (energy): the actual potential energy of the boosted force group
Returns: the value of the effective potential
Parameters
----------
groupEnergy : energy
the actual potential energy of the boosted force group
Returns
-------
energy
the value of the effective potential
"""
alphaGroup = self.getAlphaGroup()
EGroup = self.getEGroup()
......@@ -161,24 +176,31 @@ class AMDForceGroupIntegrator(CustomIntegrator):
class DualAMDIntegrator(CustomIntegrator):
"""DualAMDIntegrator implements a dual boost aMD integration algorithm.
This is similar to AMDIntegrator, but two different boosts are applied to the potential:
one based on the total energy, and one based on the energy of a single force group
(typically representing torsions).
For details, see Hamelberg et al., J. Chem. Phys. 127, 155102 (2007).
"""
def __init__(self, dt, group, alphaTotal, ETotal, alphaGroup, EGroup):
"""Create a DualAMDIntegrator.
Parameters:
- dt (time) The integration time step to use
- group (int) The force group to apply the second boost to
- alphaTotal (energy) The alpha parameter to use for the total energy
- ETotal (energy) The energy cutoff to use for the total energy
- alphaGroup (energy) The alpha parameter to use for the boosted force group
- EGroup (energy) The energy cutoff to use for the boosted force group
Parameters
----------
dt : time
The integration time step to use
group : int
The force group to apply the second boost to
alphaTotal : energy
The alpha parameter to use for the total energy
ETotal : energy
The energy cutoff to use for the total energy
alphaGroup : energy
The alpha parameter to use for the boosted force group
EGroup : energy
The energy cutoff to use for the boosted force group
"""
CustomIntegrator.__init__(self, dt)
self.addGlobalVariable("alphaTotal", alphaTotal)
......@@ -201,46 +223,53 @@ class DualAMDIntegrator(CustomIntegrator):
self.addComputePerDof("x", "x+dt*v")
self.addConstrainPositions()
self.addComputePerDof("v", "(x-oldx)/dt")
def getAlphaTotal(self):
"""Get the value of alpha for the total energy."""
return self.getGlobalVariable(0)*kilojoules_per_mole
def setAlphaTotal(self, alpha):
"""Set the value of alpha for the total energy."""
self.setGlobalVariable(0, alpha)
def getETotal(self):
"""Get the energy threshold E for the total energy."""
return self.getGlobalVariable(1)*kilojoules_per_mole
def setETotal(self, E):
"""Set the energy threshold E for the total energy."""
self.setGlobalVariable(1, E)
def getAlphaGroup(self):
"""Get the value of alpha for the boosted force group."""
return self.getGlobalVariable(2)*kilojoules_per_mole
def setAlphaGroup(self, alpha):
"""Set the value of alpha for the boosted force group."""
self.setGlobalVariable(2, alpha)
def getEGroup(self):
"""Get the energy threshold E for the boosted force group."""
return self.getGlobalVariable(3)*kilojoules_per_mole
def setEGroup(self, E):
"""Set the energy threshold E for the boosted force group."""
self.setGlobalVariable(3, E)
def getEffectiveEnergy(self, totalEnergy, groupEnergy):
"""Given the actual potential energy of the system, return the value of the effective potential.
Parameters:
- totalEnergy (energy): the actual potential energy of the whole system
- groupEnergy (energy): the actual potential energy of the boosted force group
Returns: the value of the effective potential
Parameters
----------
totalEnergy : energy
the actual potential energy of the whole system
groupEnergy : energy
the actual potential energy of the boosted force group
Returns
-------
energy
the value of the effective potential
"""
alphaTotal = self.getAlphaTotal()
ETotal = self.getETotal()
......
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