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
......@@ -43,7 +43,7 @@ namespace OpenMM {
/**
* A State object records a snapshot of the current state of a simulation at a point in time.
* You create it by calling getState() on a Context.
*
*
* When a State is created, you specify what information should be stored in it. This saves
* time and memory by only copying in the information that you actually want. This is especially
* important for forces and energies, since they may need to be calculated. If you query a
......@@ -81,7 +81,7 @@ public:
const std::vector<Vec3>& getForces() const;
/**
* Get the total kinetic energy of the system. If this State does not contain energies, this will throw an exception.
*
*
* Note that this may be different from simply mv<sup>2</sup>/2 summed over all particles. For example, a leapfrog
* integrator will store velocities offset by half a step, so they must be adjusted before computing the kinetic energy.
* This routine returns the kinetic energy at the current time, computed in a way that is appropriate for whatever
......@@ -95,9 +95,9 @@ public:
/**
* Get the vectors defining the axes of the periodic box (measured in nm).
*
* @param a on exit, this contains the vector defining the first edge of the periodic box
* @param b on exit, this contains the vector defining the second edge of the periodic box
* @param c on exit, this contains the vector defining the third edge of the periodic box
* @param[out] a the vector defining the first edge of the periodic box
* @param[out] b the vector defining the second edge of the periodic box
* @param[out] c the vector defining the third edge of the periodic box
*/
void getPeriodicBoxVectors(Vec3& a, Vec3& b, Vec3& c) const;
/**
......
......@@ -44,19 +44,19 @@ class OPENMM_EXPORT VirtualSite;
/**
* This class represents a molecular system. The definition of a System involves
* four elements:
*
*
* <ol>
* <li>The set of particles in the system</li>
* <li>The forces acting on them</li>
* <li>Pairs of particles whose separation should be constrained to a fixed value</li>
* <li>For periodic systems, the dimensions of the periodic box</li>
* </ol>
*
*
* The particles and constraints are defined directly by the System object, while
* forces are defined by objects that extend the Force class. After creating a
* System, call addParticle() once for each particle, addConstraint() for each constraint,
* and addForce() for each Force.
*
*
* In addition, particles may be designated as "virtual sites". These are particles
* whose positions are computed automatically based on the positions of other particles.
* To define a virtual site, call setVirtualSite(), passing in a VirtualSite object
......@@ -94,7 +94,7 @@ public:
* the particle and not modify its position or velocity. This is most often
* used for virtual sites, but can also be used as a way to prevent a particle
* from moving.
*
*
* @param index the index of the particle for which to get the mass
*/
double getParticleMass(int index) const;
......@@ -103,7 +103,7 @@ public:
* the particle and not modify its position or velocity. This is most often
* used for virtual sites, but can also be used as a way to prevent a particle
* from moving.
*
*
* @param index the index of the particle for which to set the mass
* @param mass the mass of the particle
*/
......@@ -120,7 +120,7 @@ public:
void setVirtualSite(int index, VirtualSite* virtualSite);
/**
* Get whether a particle is a VirtualSite.
*
*
* @param index the index of the particle to check
*/
bool isVirtualSite(int index) const {
......@@ -129,7 +129,7 @@ public:
/**
* Get VirtualSite object for a particle. If the particle is not a virtual
* site, this throws an exception.
*
*
* @param index the index of the particle to get
*/
const VirtualSite& getVirtualSite(int index) const;
......@@ -151,17 +151,17 @@ public:
int addConstraint(int particle1, int particle2, double distance);
/**
* Get the parameters defining a distance constraint.
*
*
* @param index the index of the constraint for which to get parameters
* @param particle1 the index of the first particle involved in the constraint
* @param particle2 the index of the second particle involved in the constraint
* @param distance the required distance between the two particles, measured in nm
* @param[out] particle1 the index of the first particle involved in the constraint
* @param[out] particle2 the index of the second particle involved in the constraint
* @param[out] distance the required distance between the two particles, measured in nm
*/
void getConstraintParameters(int index, int& particle1, int& particle2, double& distance) const;
/**
* Set the parameters defining a distance constraint. Particles whose mass is 0 cannot participate
* in constraints.
*
*
* @param index the index of the constraint for which to set parameters
* @param particle1 the index of the first particle involved in the constraint
* @param particle2 the index of the second particle involved in the constraint
......@@ -170,7 +170,7 @@ public:
void setConstraintParameters(int index, int particle1, int particle2, double distance);
/**
* Remove a constraint from the System.
*
*
* @param index the index of the constraint to remove
*/
void removeConstraint(int index);
......@@ -194,7 +194,7 @@ public:
}
/**
* Get a const reference to one of the Forces in this System.
*
*
* @param index the index of the Force to get
*/
const Force& getForce(int index) const;
......@@ -216,9 +216,9 @@ public:
* created Context will have its box vectors set to these. They will affect
* any Force added to the System that uses periodic boundary conditions.
*
* @param a on exit, this contains the vector defining the first edge of the periodic box
* @param b on exit, this contains the vector defining the second edge of the periodic box
* @param c on exit, this contains the vector defining the third edge of the periodic box
* @param[out] a the vector defining the first edge of the periodic box
* @param[out] b the vector defining the second edge of the periodic box
* @param[out] c the vector defining the third edge of the periodic box
*/
void getDefaultPeriodicBoxVectors(Vec3& a, Vec3& b, Vec3& c) const;
/**
......
......@@ -40,6 +40,10 @@ typedef int int32_t;
// This file defines classes and functions to simplify vectorizing code with NEON.
// These two functions are defined in the vecmath library, which is linked into OpenMM.
float32x4_t exp_ps(float32x4_t);
float32x4_t log_ps(float32x4_t);
/**
* Determine whether ivec4 and fvec4 are supported on this processor.
*/
......@@ -262,6 +266,14 @@ static inline fvec4 sqrt(const fvec4& v) {
return rsqrt(v)*v;
}
static inline fvec4 exp(const fvec4& v) {
return fvec4(exp_ps(v.val));
}
static inline fvec4 log(const fvec4& v) {
return fvec4(log_ps(v.val));
}
static inline float dot3(const fvec4& v1, const fvec4& v2) {
fvec4 result = v1*v2;
return vgetq_lane_f32(result, 0) + vgetq_lane_f32(result, 1) + vgetq_lane_f32(result, 2);
......
......@@ -233,6 +233,14 @@ static inline fvec4 abs(const fvec4& v) {
return v&(__m128) ivec4(0x7FFFFFFF);
}
static inline fvec4 exp(const fvec4& v) {
return fvec4(expf(v[0]), expf(v[1]), expf(v[2]), expf(v[3]));
}
static inline fvec4 log(const fvec4& v) {
return fvec4(logf(v[0]), logf(v[1]), logf(v[2]), logf(v[3]));
}
static inline float dot3(const fvec4& v1, const fvec4& v2) {
fvec4 r = v1*v2;
return r[0]+r[1]+r[2];
......
......@@ -37,6 +37,10 @@
// This file defines classes and functions to simplify vectorizing code with SSE.
// These two functions are defined in the vecmath library, which is linked into OpenMM.
__m128 exp_ps(__m128);
__m128 log_ps(__m128);
/**
* Determine whether ivec4 and fvec4 are supported on this processor.
*/
......@@ -253,6 +257,14 @@ static inline fvec4 rsqrt(const fvec4& v) {
return y;
}
static inline fvec4 exp(const fvec4& v) {
return fvec4(exp_ps(v.val));
}
static inline fvec4 log(const fvec4& v) {
return fvec4(log_ps(v.val));
}
static inline float dot3(const fvec4& v1, const fvec4& v2) {
return _mm_cvtss_f32(_mm_dp_ps(v1, v2, 0x71));
}
......
......@@ -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,101 +29,97 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/Force.h"
#include "openmm/CompoundIntegrator.h"
#include "openmm/Context.h"
#include "openmm/OpenMMException.h"
#include "openmm/GBVIForce.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/GBVIForceImpl.h"
#include <sstream>
#include "openmm/kernels.h"
#include <string>
using namespace OpenMM;
using namespace std;
GBVIForce::GBVIForce() : nonbondedMethod(NoCutoff), cutoffDistance(1.0), solventDielectric(78.3), soluteDielectric(1.0),
scalingMethod(QuinticSpline), quinticLowerLimitFactor(0.8), quinticUpperBornRadiusLimit(5.0) {
CompoundIntegrator::CompoundIntegrator() : currentIntegrator(0) {
}
int GBVIForce::addParticle(double charge, double radius, double gamma) {
particles.push_back(ParticleInfo(charge, radius, gamma));
return particles.size()-1;
CompoundIntegrator::~CompoundIntegrator() {
for (int i = 0; i < integrators.size(); i++)
delete integrators[i];
}
void GBVIForce::getParticleParameters(int index, double& charge, double& radius, double& gamma) const {
ASSERT_VALID_INDEX(index, particles);
charge = particles[index].charge;
radius = particles[index].radius;
gamma = particles[index].gamma;
int CompoundIntegrator::getNumIntegrators() const {
return integrators.size();
}
void GBVIForce::setParticleParameters(int index, double charge, double radius, double gamma) {
ASSERT_VALID_INDEX(index, particles);
particles[index].charge = charge;
particles[index].radius = radius;
particles[index].gamma = gamma;
int CompoundIntegrator::addIntegrator(Integrator* integrator) {
if (owner != NULL)
throw OpenMMException("addIntegrator() cannot be called after a CustomIntegrator is already bound to a context");
integrators.push_back(integrator);
return integrators.size()-1;
}
GBVIForce::NonbondedMethod GBVIForce::getNonbondedMethod() const {
return nonbondedMethod;
Integrator& CompoundIntegrator::getIntegrator(int index) {
ASSERT_VALID_INDEX(index, integrators);
return *integrators[index];
}
void GBVIForce::setNonbondedMethod(NonbondedMethod method) {
nonbondedMethod = method;
const Integrator& CompoundIntegrator::getIntegrator(int index) const {
ASSERT_VALID_INDEX(index, integrators);
return *integrators[index];
}
double GBVIForce::getCutoffDistance() const {
return cutoffDistance;
int CompoundIntegrator::getCurrentIntegrator() const {
return currentIntegrator;
}
void GBVIForce::setCutoffDistance(double distance) {
cutoffDistance = distance;
void CompoundIntegrator::setCurrentIntegrator(int index) {
if (index < 0 || index >= integrators.size())
throw OpenMMException("Illegal index for setCurrentIntegrator()");
currentIntegrator = index;
}
GBVIForce::BornRadiusScalingMethod GBVIForce::getBornRadiusScalingMethod() const {
return scalingMethod;
double CompoundIntegrator::getStepSize() const {
return integrators[currentIntegrator]->getStepSize();
}
void GBVIForce::setBornRadiusScalingMethod(BornRadiusScalingMethod method) {
scalingMethod = method;
void CompoundIntegrator::setStepSize(double size) {
integrators[currentIntegrator]->setStepSize(size);
}
double GBVIForce::getQuinticLowerLimitFactor() const {
return quinticLowerLimitFactor;
double CompoundIntegrator::getConstraintTolerance() const {
return integrators[currentIntegrator]->getConstraintTolerance();
}
void GBVIForce::setQuinticLowerLimitFactor(double inputQuinticLowerLimitFactor ){
quinticLowerLimitFactor = inputQuinticLowerLimitFactor;
void CompoundIntegrator::setConstraintTolerance(double tol) {
integrators[currentIntegrator]->setConstraintTolerance(tol);
}
double GBVIForce::getQuinticUpperBornRadiusLimit() const {
return quinticUpperBornRadiusLimit;
void CompoundIntegrator::step(int steps) {
integrators[currentIntegrator]->step(steps);
}
void GBVIForce::setQuinticUpperBornRadiusLimit(double inputQuinticUpperBornRadiusLimit){
quinticUpperBornRadiusLimit = inputQuinticUpperBornRadiusLimit;
void CompoundIntegrator::initialize(ContextImpl& context) {
if (integrators.size() == 0)
throw OpenMMException("CompoundIntegrator must contain at least one Integrator");
for (int i = 0; i < integrators.size(); i++)
integrators[i]->initialize(context);
}
int GBVIForce::addBond(int particle1, int particle2, double bondLength) {
bonds.push_back(BondInfo(particle1, particle2, bondLength));
return bonds.size()-1;
void CompoundIntegrator::cleanup() {
for (int i = 0; i < integrators.size(); i++)
integrators[i]->cleanup();
}
void GBVIForce::setBondParameters( int index, int particle1, int particle2, double bondLength) {
ASSERT_VALID_INDEX(index, bonds);
bonds[index].particle1 = particle1;
bonds[index].particle2 = particle2;
bonds[index].bondLength = bondLength;
vector<string> CompoundIntegrator::getKernelNames() {
vector<string> kernels;
for (int i = 0; i < integrators.size(); i++) {
vector<string> integratorKernels = integrators[i]->getKernelNames();
kernels.insert(kernels.end(), integratorKernels.begin(), integratorKernels.end());
}
return kernels;
}
int GBVIForce::getNumBonds() const {
return (int) bonds.size();
}
void GBVIForce::getBondParameters(int index, int& bondIndex1, int& bondIndex2, double& bondLength) const {
ASSERT_VALID_INDEX(index, bonds);
bondIndex1 = bonds[index].particle1;
bondIndex2 = bonds[index].particle2;
bondLength = bonds[index].bondLength;
}
ForceImpl* GBVIForce::createImpl() const {
return new GBVIForceImpl(*this);
double CompoundIntegrator::computeKineticEnergy() {
return integrators[currentIntegrator]->computeKineticEnergy();
}
......@@ -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-2013 Stanford University and the Authors. *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -114,21 +114,15 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
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;
}
}
}
......@@ -207,6 +201,10 @@ void Context::setVelocitiesToTemperature(double temperature, int randomSeed) {
impl->applyVelocityConstraints(1e-5);
}
const map<string, double>& Context::getParameters() const {
return impl->getParameters();
}
double Context::getParameter(const string& name) const {
return impl->getParameter(name);
}
......
......@@ -262,6 +262,10 @@ void CustomNonbondedForce::setFunctionParameters(int index, const std::string& n
}
int CustomNonbondedForce::addInteractionGroup(const std::set<int>& set1, const std::set<int>& set2) {
for (set<int>::iterator it = set1.begin(); it != set1.end(); ++it)
ASSERT(*it >= 0);
for (set<int>::iterator it = set2.begin(); it != set2.end(); ++it)
ASSERT(*it >= 0);
interactionGroups.push_back(InteractionGroupInfo(set1, set2));
return interactionGroups.size()-1;
}
......@@ -274,6 +278,10 @@ void CustomNonbondedForce::getInteractionGroupParameters(int index, std::set<int
void CustomNonbondedForce::setInteractionGroupParameters(int index, const std::set<int>& set1, const std::set<int>& set2) {
ASSERT_VALID_INDEX(index, interactionGroups);
for (set<int>::iterator it = set1.begin(); it != set1.end(); ++it)
ASSERT_VALID_INDEX(*it, particles);
for (set<int>::iterator it = set2.begin(); it != set2.end(); ++it)
ASSERT_VALID_INDEX(*it, particles);
interactionGroups[index].set1 = set1;
interactionGroups[index].set2 = set2;
}
......
......@@ -111,6 +111,26 @@ void CustomNonbondedForceImpl::initialize(ContextImpl& context) {
if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2])
throw OpenMMException("CustomNonbondedForce: The cutoff distance cannot be greater than half the periodic box size.");
}
// Check that all interaction groups only specify particles that have been defined.
for (int group = 0; group < owner.getNumInteractionGroups(); group++) {
set<int> set1, set2;
owner.getInteractionGroupParameters(group, set1, set2);
for (set<int>::iterator it = set1.begin(); it != set1.end(); ++it)
if ((*it < 0) || (*it >= owner.getNumParticles())) {
stringstream msg;
msg << "CustomNonbondedForce: Interaction group " << group << " set1 contains a particle index (" << *it << ") "
<< "not present in system (" << owner.getNumParticles() << " particles).";
throw OpenMMException(msg.str());
}
for (set<int>::iterator it = set2.begin(); it != set2.end(); ++it)
if ((*it < 0) || (*it >= owner.getNumParticles())) {
stringstream msg;
msg << "CustomNonbondedForce: Interaction group " << group << " set2 contains a particle index (" << *it << ") "
<< "not present in system (" << owner.getNumParticles() << " particles).";
throw OpenMMException(msg.str());
}
}
kernel.getAs<CalcCustomNonbondedForceKernel>().initialize(context.getSystem(), owner);
}
......
/* -------------------------------------------------------------------------- *
* 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 "openmm/internal/GBVIForceImpl.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/OpenMMException.h"
#include "openmm/kernels.h"
#include <vector>
#include <cmath>
#include <cstdio>
#include <sstream>
using namespace OpenMM;
using std::vector;
GBVIForceImpl::GBVIForceImpl(const GBVIForce& owner) : owner(owner) {
}
void GBVIForceImpl::initialize(ContextImpl& context) {
kernel = context.getPlatform().createKernel(CalcGBVIForceKernel::Name(), context);
if (owner.getNumParticles() != context.getSystem().getNumParticles())
throw OpenMMException("GBVIForce must have exactly as many particles as the System it belongs to.");
const System& system = context.getSystem();
int numberOfParticles = owner.getNumParticles();
int numberOfBonds = owner.getNumBonds();
// load 1-2 atom pairs along w/ bond distance using HarmonicBondForce & constraints
// numberOfBonds < 1, indicating they were not set by the user
if( numberOfBonds < 1 && numberOfParticles > 1 ){
(void) fprintf( stderr, "Warning: no covalent bonds set for GB/VI force!\n" );
// getBondsFromForces( context );
// numberOfBonds = owner.getNumBonds();
}
std::vector< std::vector<int> > bondIndices;
bondIndices.resize( numberOfBonds );
std::vector<double> bondLengths;
bondLengths.resize( numberOfBonds );
for (int i = 0; i < numberOfBonds; i++) {
int particle1, particle2;
double bondLength;
owner.getBondParameters(i, particle1, particle2, bondLength);
if (particle1 < 0 || particle1 >= owner.getNumParticles()) {
std::stringstream msg;
msg << "GBVISoftcoreForce: Illegal particle index: ";
msg << particle1;
throw OpenMMException(msg.str());
}
if (particle2 < 0 || particle2 >= owner.getNumParticles()) {
std::stringstream msg;
msg << "GBVISoftcoreForce: Illegal particle index: ";
msg << particle2;
throw OpenMMException(msg.str());
}
if (bondLength < 0 ) {
std::stringstream msg;
msg << "GBVISoftcoreForce: negative bondlength: ";
msg << bondLength;
throw OpenMMException(msg.str());
}
bondIndices[i].push_back( particle1 );
bondIndices[i].push_back( particle2 );
bondLengths[i] = bondLength;
}
if (owner.getNonbondedMethod() == GBVIForce::CutoffPeriodic) {
Vec3 boxVectors[3];
system.getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]);
double cutoff = owner.getCutoffDistance();
if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2])
throw OpenMMException("GBVIForce: The cutoff distance cannot be greater than half the periodic box size.");
}
vector<double> scaledRadii;
scaledRadii.resize(numberOfParticles);
findScaledRadii( numberOfParticles, bondIndices, bondLengths, scaledRadii);
kernel.getAs<CalcGBVIForceKernel>().initialize(context.getSystem(), owner, scaledRadii);
}
/*
int GBVIForceImpl::getBondsFromForces(ContextImpl& context) {
// load 1-2 atom pairs along w/ bond distance using HarmonicBondForce & constraints
const System& system = context.getSystem();
for (int i = 0; i < system.getNumForces(); i++) {
if (dynamic_cast<const HarmonicBondForce*>(&system.getForce(i)) != NULL) {
const HarmonicBondForce& force = dynamic_cast<const HarmonicBondForce&>(system.getForce(i));
for (int j = 0; j < force.getNumBonds(); ++j) {
int particle1, particle2;
double length, k;
force.getBondParameters(j, particle1, particle2, length, k);
owner.addBond( particle1, particle2, length );
}
break;
}
}
// Also treat constrained distances as bonds if mass of one particle is < (2 + epsilon) (~2=deuterium)
for (int j = 0; j < system.getNumConstraints(); j++) {
int particle1, particle2;
double distance;
system.getConstraintParameters(j, particle1, particle2, distance);
double mass1 = system.getParticleMass( particle1 );
double mass2 = system.getParticleMass( particle2 );
if( mass1 < 2.1 || mass2 < 2.1 ){
owner.addBond( particle1, particle2, distance );
}
}
return 0;
}
*/
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 && numberOfParticles > 1 ){
(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");
}
}
double GBVIForceImpl::calcForcesAndEnergy(ContextImpl& context, bool includeForces, bool includeEnergy, int groups) {
if ((groups&(1<<owner.getForceGroup())) != 0)
return kernel.getAs<CalcGBVIForceKernel>().execute(context, includeForces, includeEnergy);
return 0.0;
}
std::vector<std::string> GBVIForceImpl::getKernelNames() {
std::vector<std::string> names;
names.push_back(CalcGBVIForceKernel::Name());
return names;
}
......@@ -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) 2013 Stanford University and the Authors. *
* Portions copyright (c) 2013-2015 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -47,3 +47,19 @@ Integrator::~Integrator() {
context->integratorDeleted();
}
}
double Integrator::getStepSize() const {
return stepSize;
}
void Integrator::setStepSize(double size) {
stepSize = size;
}
double Integrator::getConstraintTolerance() const {
return constraintTol;
}
void Integrator::setConstraintTolerance(double tol) {
constraintTol = tol;
}
......@@ -12,9 +12,11 @@
# libOpenMMCPU_static.a
#----------------------------------------------------
IF(BUILD_TESTING)
SET(OPENMM_BUILD_CPU_TESTS TRUE CACHE BOOL "Whether to build CPU platform test cases")
MARK_AS_ADVANCED(OPENMM_BUILD_CPU_TESTS)
IF(BUILD_TESTING AND OPENMM_BUILD_CPU_TESTS)
SUBDIRS(tests)
ENDIF(BUILD_TESTING)
ENDIF(BUILD_TESTING AND OPENMM_BUILD_CPU_TESTS)
# The source is organized into subdirectories, but we handle them all from
# this CMakeLists file rather than letting CMake visit them as SUBDIRS.
......
......@@ -35,6 +35,7 @@
#include "AlignedArray.h"
#include "RealVec.h"
#include "windowsExportCpu.h"
#include "openmm/internal/gmx_atomic.h"
#include "openmm/internal/ThreadPool.h"
#include <set>
#include <utility>
......@@ -74,6 +75,7 @@ private:
int numAtoms;
bool usePeriodic;
float maxDistance;
gmx_atomic_t atomicCounter;
};
} // namespace OpenMM
......
......@@ -28,7 +28,7 @@
#include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h"
#include "CpuCustomGBForce.h"
#include "gmx_atomic.h"
#include "openmm/internal/gmx_atomic.h"
using namespace OpenMM;
using namespace std;
......
......@@ -32,7 +32,7 @@
#include "ReferenceTabulatedFunction.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include "lepton/CustomFunction.h"
#include "gmx_atomic.h"
#include "openmm/internal/gmx_atomic.h"
using namespace OpenMM;
using namespace std;
......
......@@ -28,7 +28,7 @@
#include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h"
#include "CpuCustomNonbondedForce.h"
#include "gmx_atomic.h"
#include "openmm/internal/gmx_atomic.h"
using namespace OpenMM;
using namespace std;
......
......@@ -25,7 +25,7 @@
#include "CpuGBSAOBCForce.h"
#include "SimTKOpenMMRealType.h"
#include "openmm/internal/vectorize.h"
#include "gmx_atomic.h"
#include "openmm/internal/gmx_atomic.h"
#include <algorithm>
#include <cmath>
#include <cstdlib>
......@@ -279,7 +279,7 @@ void CpuGBSAOBCForce::threadComputeForce(ThreadPool& threads, int threadIndex) {
fvec4 r = sqrt(r2);
fvec4 alpha2_ij = radii*bornRadii[atomJ];
fvec4 D_ij = r2/(4.0f*alpha2_ij);
fvec4 expTerm(expf(-D_ij[0]), expf(-D_ij[1]), expf(-D_ij[2]), expf(-D_ij[3]));
fvec4 expTerm = exp(-D_ij);
fvec4 denominator2 = r2 + alpha2_ij*expTerm;
fvec4 denominator = sqrt(denominator2);
fvec4 Gpol = (partialChargeI*posJ[3])/denominator;
......
......@@ -599,7 +599,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
if (nonbondedMethod != NoCutoff) {
// Determine whether we need to recompute the neighbor list.
double padding = 0.15*nonbondedCutoff;
double padding = 0.25*nonbondedCutoff;
bool needRecompute = false;
double closeCutoff2 = 0.25*padding*padding;
double farCutoff2 = 0.5*padding*padding;
......
......@@ -59,22 +59,25 @@ public:
*/
class CpuNeighborList::Voxels {
public:
Voxels(int blockSize, float vsy, float vsz, float miny, float maxy, float minz, float maxz, const RealVec* periodicBoxVectors, bool usePeriodic) :
blockSize(blockSize), voxelSizeY(vsy), voxelSizeZ(vsz), miny(miny), maxy(maxy), minz(minz), maxz(maxz), periodicBoxVectors(periodicBoxVectors), usePeriodic(usePeriodic) {
periodicBoxSize[0] = (float) periodicBoxVectors[0][0];
periodicBoxSize[1] = (float) periodicBoxVectors[1][1];
periodicBoxSize[2] = (float) periodicBoxVectors[2][2];
recipBoxSize[0] = (float) (1/periodicBoxVectors[0][0]);
recipBoxSize[1] = (float) (1/periodicBoxVectors[1][1]);
recipBoxSize[2] = (float) (1/periodicBoxVectors[2][2]);
triclinic = (periodicBoxVectors[0][1] != 0.0 || periodicBoxVectors[0][2] != 0.0 ||
periodicBoxVectors[1][0] != 0.0 || periodicBoxVectors[1][2] != 0.0 ||
periodicBoxVectors[2][0] != 0.0 || periodicBoxVectors[2][1] != 0.0);
Voxels(int blockSize, float vsy, float vsz, float miny, float maxy, float minz, float maxz, const RealVec* boxVectors, bool usePeriodic) :
blockSize(blockSize), voxelSizeY(vsy), voxelSizeZ(vsz), miny(miny), maxy(maxy), minz(minz), maxz(maxz), usePeriodic(usePeriodic) {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
periodicBoxVectors[i][j] = (float) boxVectors[i][j];
periodicBoxSize[0] = (float) boxVectors[0][0];
periodicBoxSize[1] = (float) boxVectors[1][1];
periodicBoxSize[2] = (float) boxVectors[2][2];
recipBoxSize[0] = (float) (1/boxVectors[0][0]);
recipBoxSize[1] = (float) (1/boxVectors[1][1]);
recipBoxSize[2] = (float) (1/boxVectors[2][2]);
triclinic = (boxVectors[0][1] != 0.0 || boxVectors[0][2] != 0.0 ||
boxVectors[1][0] != 0.0 || boxVectors[1][2] != 0.0 ||
boxVectors[2][0] != 0.0 || boxVectors[2][1] != 0.0);
if (usePeriodic) {
ny = (int) floorf(periodicBoxVectors[1][1]/voxelSizeY+0.5f);
nz = (int) floorf(periodicBoxVectors[2][2]/voxelSizeZ+0.5f);
voxelSizeY = periodicBoxVectors[1][1]/ny;
voxelSizeZ = periodicBoxVectors[2][2]/nz;
ny = (int) floorf(boxVectors[1][1]/voxelSizeY+0.5f);
nz = (int) floorf(boxVectors[2][2]/voxelSizeZ+0.5f);
voxelSizeY = boxVectors[1][1]/ny;
voxelSizeZ = boxVectors[2][2]/nz;
}
else {
ny = max(1, (int) floorf((maxy-miny)/voxelSizeY+0.5f));
......@@ -110,12 +113,10 @@ public:
}
/**
* Find the index of the first particle in voxel (y,z) whose x coordinate in >= the specified value.
* Find the index of the first particle in voxel (y,z) whose x coordinate is >= the specified value.
*/
int findLowerBound(int y, int z, double x) const {
int findLowerBound(int y, int z, double x, int lower, int upper) const {
const vector<pair<float, int> >& bin = bins[y][z];
int lower = 0;
int upper = bin.size();
while (lower < upper) {
int middle = (lower+upper)/2;
if (bin[middle].first < x)
......@@ -127,12 +128,10 @@ public:
}
/**
* Find the index of the first particle in voxel (y,z) whose x coordinate in greater than the specified value.
* Find the index of the first particle in voxel (y,z) whose x coordinate is greater than the specified value.
*/
int findUpperBound(int y, int z, double x) const {
int findUpperBound(int y, int z, double x, int lower, int upper) const {
const vector<pair<float, int> >& bin = bins[y][z];
int lower = 0;
int upper = bin.size();
while (lower < upper) {
int middle = (lower+upper)/2;
if (bin[middle].first > x)
......@@ -208,7 +207,7 @@ public:
// Loop over voxels along the y axis.
int boxz = (int) floor((float) z/nz);
float boxz = floor((float) z/nz);
int starty = centerVoxelIndex.y-dIndexY;
int endy = centerVoxelIndex.y+dIndexY;
float yoffset = (float) (usePeriodic ? boxz*periodicBoxVectors[2][1] : 0);
......@@ -225,7 +224,7 @@ public:
voxelIndex.y = y;
if (usePeriodic)
voxelIndex.y = (y < 0 ? y+ny : (y >= ny ? y-ny : y));
int boxy = (int) floor((float) y/ny);
float boxy = floor((float) y/ny);
float xoffset = (float) (usePeriodic ? boxy*periodicBoxVectors[1][0]+boxz*periodicBoxVectors[2][0] : 0);
// Identify the range of atoms within this bin we need to search. When using periodic boundary
......@@ -261,30 +260,34 @@ public:
int numRanges;
int rangeStart[2];
int rangeEnd[2];
rangeStart[0] = findLowerBound(voxelIndex.y, voxelIndex.z, minx);
int binSize = bins[voxelIndex.y][voxelIndex.z].size();
rangeStart[0] = findLowerBound(voxelIndex.y, voxelIndex.z, minx, 0, binSize);
if (needPeriodic) {
numRanges = 2;
rangeEnd[0] = findUpperBound(voxelIndex.y, voxelIndex.z, maxx);
if (rangeStart[0] > 0) {
rangeEnd[0] = findUpperBound(voxelIndex.y, voxelIndex.z, maxx, rangeStart[0], binSize);
if (rangeStart[0] > 0 && rangeEnd[0] < binSize)
numRanges = 1;
else if (rangeStart[0] > 0) {
rangeStart[1] = 0;
rangeEnd[1] = min(findUpperBound(voxelIndex.y, voxelIndex.z, maxx-periodicBoxSize[0]), rangeStart[0]);
rangeEnd[1] = min(findUpperBound(voxelIndex.y, voxelIndex.z, maxx-periodicBoxSize[0], 0, rangeStart[0]), rangeStart[0]);
}
else {
rangeStart[1] = max(findLowerBound(voxelIndex.y, voxelIndex.z, minx+periodicBoxSize[0]), rangeEnd[0]);
rangeStart[1] = max(findLowerBound(voxelIndex.y, voxelIndex.z, minx+periodicBoxSize[0], rangeEnd[0], binSize), rangeEnd[0]);
rangeEnd[1] = bins[voxelIndex.y][voxelIndex.z].size();
}
}
else {
numRanges = 1;
rangeEnd[0] = findUpperBound(voxelIndex.y, voxelIndex.z, maxx);
rangeEnd[0] = findUpperBound(voxelIndex.y, voxelIndex.z, maxx, rangeStart[0], binSize);
}
bool periodicRectangular = (needPeriodic && !triclinic);
// Loop over atoms and check to see if they are neighbors of this block.
const vector<pair<float, int> >& voxelBins = bins[voxelIndex.y][voxelIndex.z];
for (int range = 0; range < numRanges; range++) {
for (int item = rangeStart[range]; item < rangeEnd[range]; item++) {
const int sortedIndex = bins[voxelIndex.y][voxelIndex.z][item].second;
const int sortedIndex = voxelBins[item].second;
// Avoid duplicate entries.
if (sortedIndex >= lastSortedIndex)
......@@ -361,7 +364,7 @@ private:
int ny, nz;
float periodicBoxSize[3], recipBoxSize[3];
bool triclinic;
const RealVec* periodicBoxVectors;
float periodicBoxVectors[3][3];
const bool usePeriodic;
vector<vector<vector<pair<float, int> > > > bins;
};
......@@ -444,6 +447,7 @@ void CpuNeighborList::computeNeighborList(int numAtoms, const AlignedArray<float
// Signal the threads to start running and wait for them to finish.
gmx_atomic_set(&atomicCounter, 0);
threads.resumeThreads();
threads.waitForThreads();
......@@ -500,7 +504,11 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
vector<int> blockAtoms;
vector<float> blockAtomX(blockSize), blockAtomY(blockSize), blockAtomZ(blockSize);
vector<VoxelIndex> atomVoxelIndex;
for (int i = threadIndex; i < numBlocks; i += numThreads) {
while (true) {
int i = gmx_atomic_fetch_add(&atomicCounter, 1);
if (i >= numBlocks)
break;
// Find the atoms in this block and compute their bounding box.
int firstIndex = blockSize*i;
......@@ -532,15 +540,25 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
// Record the exclusions for this block.
map<int, char> atomFlags;
for (int j = 0; j < atomsInBlock; j++) {
const set<int>& atomExclusions = (*exclusions)[sortedAtoms[firstIndex+j]];
char mask = 1<<j;
for (int k = 0; k < (int) blockNeighbors[i].size(); k++) {
int atomIndex = blockNeighbors[i][k];
if (atomExclusions.find(atomIndex) != atomExclusions.end())
blockExclusions[i][k] |= mask;
for (set<int>::const_iterator iter = atomExclusions.begin(); iter != atomExclusions.end(); ++iter) {
map<int, char>::iterator thisAtomFlags = atomFlags.find(*iter);
if (thisAtomFlags == atomFlags.end())
atomFlags[*iter] = mask;
else
thisAtomFlags->second |= mask;
}
}
int numNeighbors = blockNeighbors[i].size();
for (int k = 0; k < numNeighbors; k++) {
int atomIndex = blockNeighbors[i][k];
map<int, char>::iterator thisAtomFlags = atomFlags.find(atomIndex);
if (thisAtomFlags != atomFlags.end())
blockExclusions[i][k] |= thisAtomFlags->second;
}
}
}
......
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