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 { ...@@ -43,7 +43,7 @@ namespace OpenMM {
/** /**
* A State object records a snapshot of the current state of a simulation at a point in time. * 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. * 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 * 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 * 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 * important for forces and energies, since they may need to be calculated. If you query a
...@@ -81,7 +81,7 @@ public: ...@@ -81,7 +81,7 @@ public:
const std::vector<Vec3>& getForces() const; 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. * 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 * 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. * 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 * This routine returns the kinetic energy at the current time, computed in a way that is appropriate for whatever
...@@ -95,9 +95,9 @@ public: ...@@ -95,9 +95,9 @@ public:
/** /**
* Get the vectors defining the axes of the periodic box (measured in nm). * 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[out] a 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[out] b 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] c the vector defining the third edge of the periodic box
*/ */
void getPeriodicBoxVectors(Vec3& a, Vec3& b, Vec3& c) const; void getPeriodicBoxVectors(Vec3& a, Vec3& b, Vec3& c) const;
/** /**
......
...@@ -44,19 +44,19 @@ class OPENMM_EXPORT VirtualSite; ...@@ -44,19 +44,19 @@ class OPENMM_EXPORT VirtualSite;
/** /**
* This class represents a molecular system. The definition of a System involves * This class represents a molecular system. The definition of a System involves
* four elements: * four elements:
* *
* <ol> * <ol>
* <li>The set of particles in the system</li> * <li>The set of particles in the system</li>
* <li>The forces acting on them</li> * <li>The forces acting on them</li>
* <li>Pairs of particles whose separation should be constrained to a fixed value</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> * <li>For periodic systems, the dimensions of the periodic box</li>
* </ol> * </ol>
* *
* The particles and constraints are defined directly by the System object, while * 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 * forces are defined by objects that extend the Force class. After creating a
* System, call addParticle() once for each particle, addConstraint() for each constraint, * System, call addParticle() once for each particle, addConstraint() for each constraint,
* and addForce() for each Force. * and addForce() for each Force.
* *
* In addition, particles may be designated as "virtual sites". These are particles * In addition, particles may be designated as "virtual sites". These are particles
* whose positions are computed automatically based on the positions of other 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 * To define a virtual site, call setVirtualSite(), passing in a VirtualSite object
...@@ -94,7 +94,7 @@ public: ...@@ -94,7 +94,7 @@ public:
* the particle and not modify its position or velocity. This is most often * 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 * used for virtual sites, but can also be used as a way to prevent a particle
* from moving. * from moving.
* *
* @param index the index of the particle for which to get the mass * @param index the index of the particle for which to get the mass
*/ */
double getParticleMass(int index) const; double getParticleMass(int index) const;
...@@ -103,7 +103,7 @@ public: ...@@ -103,7 +103,7 @@ public:
* the particle and not modify its position or velocity. This is most often * 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 * used for virtual sites, but can also be used as a way to prevent a particle
* from moving. * from moving.
* *
* @param index the index of the particle for which to set the mass * @param index the index of the particle for which to set the mass
* @param mass the mass of the particle * @param mass the mass of the particle
*/ */
...@@ -120,7 +120,7 @@ public: ...@@ -120,7 +120,7 @@ public:
void setVirtualSite(int index, VirtualSite* virtualSite); void setVirtualSite(int index, VirtualSite* virtualSite);
/** /**
* Get whether a particle is a VirtualSite. * Get whether a particle is a VirtualSite.
* *
* @param index the index of the particle to check * @param index the index of the particle to check
*/ */
bool isVirtualSite(int index) const { bool isVirtualSite(int index) const {
...@@ -129,7 +129,7 @@ public: ...@@ -129,7 +129,7 @@ public:
/** /**
* Get VirtualSite object for a particle. If the particle is not a virtual * Get VirtualSite object for a particle. If the particle is not a virtual
* site, this throws an exception. * site, this throws an exception.
* *
* @param index the index of the particle to get * @param index the index of the particle to get
*/ */
const VirtualSite& getVirtualSite(int index) const; const VirtualSite& getVirtualSite(int index) const;
...@@ -151,17 +151,17 @@ public: ...@@ -151,17 +151,17 @@ public:
int addConstraint(int particle1, int particle2, double distance); int addConstraint(int particle1, int particle2, double distance);
/** /**
* Get the parameters defining a distance constraint. * Get the parameters defining a distance constraint.
* *
* @param index the index of the constraint for which to get parameters * @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[out] particle1 the index of the first particle involved in the constraint
* @param particle2 the index of the second particle involved in the constraint * @param[out] 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] distance the required distance between the two particles, measured in nm
*/ */
void getConstraintParameters(int index, int& particle1, int& particle2, double& distance) const; 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 * Set the parameters defining a distance constraint. Particles whose mass is 0 cannot participate
* in constraints. * in constraints.
* *
* @param index the index of the constraint for which to set parameters * @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 particle1 the index of the first particle involved in the constraint
* @param particle2 the index of the second particle involved in the constraint * @param particle2 the index of the second particle involved in the constraint
...@@ -170,7 +170,7 @@ public: ...@@ -170,7 +170,7 @@ public:
void setConstraintParameters(int index, int particle1, int particle2, double distance); void setConstraintParameters(int index, int particle1, int particle2, double distance);
/** /**
* Remove a constraint from the System. * Remove a constraint from the System.
* *
* @param index the index of the constraint to remove * @param index the index of the constraint to remove
*/ */
void removeConstraint(int index); void removeConstraint(int index);
...@@ -194,7 +194,7 @@ public: ...@@ -194,7 +194,7 @@ public:
} }
/** /**
* Get a const reference to one of the Forces in this System. * Get a const reference to one of the Forces in this System.
* *
* @param index the index of the Force to get * @param index the index of the Force to get
*/ */
const Force& getForce(int index) const; const Force& getForce(int index) const;
...@@ -216,9 +216,9 @@ public: ...@@ -216,9 +216,9 @@ public:
* created Context will have its box vectors set to these. They will affect * created Context will have its box vectors set to these. They will affect
* any Force added to the System that uses periodic boundary conditions. * 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[out] a 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[out] b 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] c the vector defining the third edge of the periodic box
*/ */
void getDefaultPeriodicBoxVectors(Vec3& a, Vec3& b, Vec3& c) const; void getDefaultPeriodicBoxVectors(Vec3& a, Vec3& b, Vec3& c) const;
/** /**
......
...@@ -40,6 +40,10 @@ typedef int int32_t; ...@@ -40,6 +40,10 @@ typedef int int32_t;
// This file defines classes and functions to simplify vectorizing code with NEON. // 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. * Determine whether ivec4 and fvec4 are supported on this processor.
*/ */
...@@ -262,6 +266,14 @@ static inline fvec4 sqrt(const fvec4& v) { ...@@ -262,6 +266,14 @@ static inline fvec4 sqrt(const fvec4& v) {
return rsqrt(v)*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) { static inline float dot3(const fvec4& v1, const fvec4& v2) {
fvec4 result = v1*v2; fvec4 result = v1*v2;
return vgetq_lane_f32(result, 0) + vgetq_lane_f32(result, 1) + vgetq_lane_f32(result, 2); 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) { ...@@ -233,6 +233,14 @@ static inline fvec4 abs(const fvec4& v) {
return v&(__m128) ivec4(0x7FFFFFFF); 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) { static inline float dot3(const fvec4& v1, const fvec4& v2) {
fvec4 r = v1*v2; fvec4 r = v1*v2;
return r[0]+r[1]+r[2]; return r[0]+r[1]+r[2];
......
...@@ -37,6 +37,10 @@ ...@@ -37,6 +37,10 @@
// This file defines classes and functions to simplify vectorizing code with SSE. // 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. * Determine whether ivec4 and fvec4 are supported on this processor.
*/ */
...@@ -253,6 +257,14 @@ static inline fvec4 rsqrt(const fvec4& v) { ...@@ -253,6 +257,14 @@ static inline fvec4 rsqrt(const fvec4& v) {
return y; 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) { static inline float dot3(const fvec4& v1, const fvec4& v2) {
return _mm_cvtss_f32(_mm_dp_ps(v1, v2, 0x71)); return _mm_cvtss_f32(_mm_dp_ps(v1, v2, 0x71));
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * 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 * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -29,101 +29,97 @@ ...@@ -29,101 +29,97 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * 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/OpenMMException.h"
#include "openmm/GBVIForce.h" #include "openmm/internal/ContextImpl.h"
#include "openmm/internal/AssertionUtilities.h" #include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/GBVIForceImpl.h" #include "openmm/kernels.h"
#include <sstream> #include <string>
using namespace OpenMM; using namespace OpenMM;
using namespace std;
GBVIForce::GBVIForce() : nonbondedMethod(NoCutoff), cutoffDistance(1.0), solventDielectric(78.3), soluteDielectric(1.0), CompoundIntegrator::CompoundIntegrator() : currentIntegrator(0) {
scalingMethod(QuinticSpline), quinticLowerLimitFactor(0.8), quinticUpperBornRadiusLimit(5.0) {
} }
int GBVIForce::addParticle(double charge, double radius, double gamma) { CompoundIntegrator::~CompoundIntegrator() {
particles.push_back(ParticleInfo(charge, radius, gamma)); for (int i = 0; i < integrators.size(); i++)
return particles.size()-1; delete integrators[i];
} }
void GBVIForce::getParticleParameters(int index, double& charge, double& radius, double& gamma) const { int CompoundIntegrator::getNumIntegrators() const {
ASSERT_VALID_INDEX(index, particles); return integrators.size();
charge = particles[index].charge;
radius = particles[index].radius;
gamma = particles[index].gamma;
} }
void GBVIForce::setParticleParameters(int index, double charge, double radius, double gamma) { int CompoundIntegrator::addIntegrator(Integrator* integrator) {
ASSERT_VALID_INDEX(index, particles); if (owner != NULL)
particles[index].charge = charge; throw OpenMMException("addIntegrator() cannot be called after a CustomIntegrator is already bound to a context");
particles[index].radius = radius; integrators.push_back(integrator);
particles[index].gamma = gamma; return integrators.size()-1;
} }
GBVIForce::NonbondedMethod GBVIForce::getNonbondedMethod() const { Integrator& CompoundIntegrator::getIntegrator(int index) {
return nonbondedMethod; ASSERT_VALID_INDEX(index, integrators);
return *integrators[index];
} }
void GBVIForce::setNonbondedMethod(NonbondedMethod method) { const Integrator& CompoundIntegrator::getIntegrator(int index) const {
nonbondedMethod = method; ASSERT_VALID_INDEX(index, integrators);
return *integrators[index];
} }
double GBVIForce::getCutoffDistance() const { int CompoundIntegrator::getCurrentIntegrator() const {
return cutoffDistance; return currentIntegrator;
} }
void GBVIForce::setCutoffDistance(double distance) { void CompoundIntegrator::setCurrentIntegrator(int index) {
cutoffDistance = distance; if (index < 0 || index >= integrators.size())
throw OpenMMException("Illegal index for setCurrentIntegrator()");
currentIntegrator = index;
} }
GBVIForce::BornRadiusScalingMethod GBVIForce::getBornRadiusScalingMethod() const { double CompoundIntegrator::getStepSize() const {
return scalingMethod; return integrators[currentIntegrator]->getStepSize();
} }
void GBVIForce::setBornRadiusScalingMethod(BornRadiusScalingMethod method) { void CompoundIntegrator::setStepSize(double size) {
scalingMethod = method; integrators[currentIntegrator]->setStepSize(size);
} }
double GBVIForce::getQuinticLowerLimitFactor() const { double CompoundIntegrator::getConstraintTolerance() const {
return quinticLowerLimitFactor; return integrators[currentIntegrator]->getConstraintTolerance();
} }
void GBVIForce::setQuinticLowerLimitFactor(double inputQuinticLowerLimitFactor ){ void CompoundIntegrator::setConstraintTolerance(double tol) {
quinticLowerLimitFactor = inputQuinticLowerLimitFactor; integrators[currentIntegrator]->setConstraintTolerance(tol);
} }
double GBVIForce::getQuinticUpperBornRadiusLimit() const { void CompoundIntegrator::step(int steps) {
return quinticUpperBornRadiusLimit; integrators[currentIntegrator]->step(steps);
} }
void GBVIForce::setQuinticUpperBornRadiusLimit(double inputQuinticUpperBornRadiusLimit){ void CompoundIntegrator::initialize(ContextImpl& context) {
quinticUpperBornRadiusLimit = inputQuinticUpperBornRadiusLimit; 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) { void CompoundIntegrator::cleanup() {
bonds.push_back(BondInfo(particle1, particle2, bondLength)); for (int i = 0; i < integrators.size(); i++)
return bonds.size()-1; integrators[i]->cleanup();
} }
void GBVIForce::setBondParameters( int index, int particle1, int particle2, double bondLength) { vector<string> CompoundIntegrator::getKernelNames() {
ASSERT_VALID_INDEX(index, bonds); vector<string> kernels;
bonds[index].particle1 = particle1; for (int i = 0; i < integrators.size(); i++) {
bonds[index].particle2 = particle2; vector<string> integratorKernels = integrators[i]->getKernelNames();
bonds[index].bondLength = bondLength; kernels.insert(kernels.end(), integratorKernels.begin(), integratorKernels.end());
}
return kernels;
} }
int GBVIForce::getNumBonds() const { double CompoundIntegrator::computeKineticEnergy() {
return (int) bonds.size(); return integrators[currentIntegrator]->computeKineticEnergy();
}
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);
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * 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 * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -114,21 +114,15 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const { ...@@ -114,21 +114,15 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
center *= 1.0/molecules[i].size(); center *= 1.0/molecules[i].size();
// Find the displacement to move it into the first periodic box. // Find the displacement to move it into the first periodic box.
Vec3 diff;
int xcell = (int) floor(center[0]/periodicBoxSize[0][0]); diff += periodicBoxSize[2]*floor(center[2]/periodicBoxSize[2][2]);
int ycell = (int) floor(center[1]/periodicBoxSize[1][1]); diff += periodicBoxSize[1]*floor((center[1]-diff[1])/periodicBoxSize[1][1]);
int zcell = (int) floor(center[2]/periodicBoxSize[2][2]); diff += periodicBoxSize[0]*floor((center[0]-diff[0])/periodicBoxSize[0][0]);
double dx = xcell*periodicBoxSize[0][0];
double dy = ycell*periodicBoxSize[1][1];
double dz = zcell*periodicBoxSize[2][2];
// Translate all the particles in the molecule. // Translate all the particles in the molecule.
for (int j = 0; j < (int) molecules[i].size(); j++) { for (int j = 0; j < (int) molecules[i].size(); j++) {
Vec3& pos = positions[molecules[i][j]]; Vec3& pos = positions[molecules[i][j]];
pos[0] -= dx; pos -= diff;
pos[1] -= dy;
pos[2] -= dz;
} }
} }
} }
...@@ -207,6 +201,10 @@ void Context::setVelocitiesToTemperature(double temperature, int randomSeed) { ...@@ -207,6 +201,10 @@ void Context::setVelocitiesToTemperature(double temperature, int randomSeed) {
impl->applyVelocityConstraints(1e-5); impl->applyVelocityConstraints(1e-5);
} }
const map<string, double>& Context::getParameters() const {
return impl->getParameters();
}
double Context::getParameter(const string& name) const { double Context::getParameter(const string& name) const {
return impl->getParameter(name); return impl->getParameter(name);
} }
......
...@@ -262,6 +262,10 @@ void CustomNonbondedForce::setFunctionParameters(int index, const std::string& n ...@@ -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) { 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)); interactionGroups.push_back(InteractionGroupInfo(set1, set2));
return interactionGroups.size()-1; return interactionGroups.size()-1;
} }
...@@ -274,6 +278,10 @@ void CustomNonbondedForce::getInteractionGroupParameters(int index, std::set<int ...@@ -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) { void CustomNonbondedForce::setInteractionGroupParameters(int index, const std::set<int>& set1, const std::set<int>& set2) {
ASSERT_VALID_INDEX(index, interactionGroups); 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].set1 = set1;
interactionGroups[index].set2 = set2; interactionGroups[index].set2 = set2;
} }
......
...@@ -111,6 +111,26 @@ void CustomNonbondedForceImpl::initialize(ContextImpl& context) { ...@@ -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]) 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."); 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); 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 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * 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 * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -47,3 +47,19 @@ Integrator::~Integrator() { ...@@ -47,3 +47,19 @@ Integrator::~Integrator() {
context->integratorDeleted(); 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 @@ ...@@ -12,9 +12,11 @@
# libOpenMMCPU_static.a # 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) 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 # The source is organized into subdirectories, but we handle them all from
# this CMakeLists file rather than letting CMake visit them as SUBDIRS. # this CMakeLists file rather than letting CMake visit them as SUBDIRS.
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "AlignedArray.h" #include "AlignedArray.h"
#include "RealVec.h" #include "RealVec.h"
#include "windowsExportCpu.h" #include "windowsExportCpu.h"
#include "openmm/internal/gmx_atomic.h"
#include "openmm/internal/ThreadPool.h" #include "openmm/internal/ThreadPool.h"
#include <set> #include <set>
#include <utility> #include <utility>
...@@ -74,6 +75,7 @@ private: ...@@ -74,6 +75,7 @@ private:
int numAtoms; int numAtoms;
bool usePeriodic; bool usePeriodic;
float maxDistance; float maxDistance;
gmx_atomic_t atomicCounter;
}; };
} // namespace OpenMM } // namespace OpenMM
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "SimTKOpenMMUtilities.h" #include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h" #include "ReferenceForce.h"
#include "CpuCustomGBForce.h" #include "CpuCustomGBForce.h"
#include "gmx_atomic.h" #include "openmm/internal/gmx_atomic.h"
using namespace OpenMM; using namespace OpenMM;
using namespace std; using namespace std;
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include "ReferenceTabulatedFunction.h" #include "ReferenceTabulatedFunction.h"
#include "openmm/internal/CustomManyParticleForceImpl.h" #include "openmm/internal/CustomManyParticleForceImpl.h"
#include "lepton/CustomFunction.h" #include "lepton/CustomFunction.h"
#include "gmx_atomic.h" #include "openmm/internal/gmx_atomic.h"
using namespace OpenMM; using namespace OpenMM;
using namespace std; using namespace std;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "SimTKOpenMMUtilities.h" #include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h" #include "ReferenceForce.h"
#include "CpuCustomNonbondedForce.h" #include "CpuCustomNonbondedForce.h"
#include "gmx_atomic.h" #include "openmm/internal/gmx_atomic.h"
using namespace OpenMM; using namespace OpenMM;
using namespace std; using namespace std;
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "CpuGBSAOBCForce.h" #include "CpuGBSAOBCForce.h"
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "openmm/internal/vectorize.h" #include "openmm/internal/vectorize.h"
#include "gmx_atomic.h" #include "openmm/internal/gmx_atomic.h"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
...@@ -279,7 +279,7 @@ void CpuGBSAOBCForce::threadComputeForce(ThreadPool& threads, int threadIndex) { ...@@ -279,7 +279,7 @@ void CpuGBSAOBCForce::threadComputeForce(ThreadPool& threads, int threadIndex) {
fvec4 r = sqrt(r2); fvec4 r = sqrt(r2);
fvec4 alpha2_ij = radii*bornRadii[atomJ]; fvec4 alpha2_ij = radii*bornRadii[atomJ];
fvec4 D_ij = r2/(4.0f*alpha2_ij); 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 denominator2 = r2 + alpha2_ij*expTerm;
fvec4 denominator = sqrt(denominator2); fvec4 denominator = sqrt(denominator2);
fvec4 Gpol = (partialChargeI*posJ[3])/denominator; fvec4 Gpol = (partialChargeI*posJ[3])/denominator;
......
...@@ -599,7 +599,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo ...@@ -599,7 +599,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
if (nonbondedMethod != NoCutoff) { if (nonbondedMethod != NoCutoff) {
// Determine whether we need to recompute the neighbor list. // Determine whether we need to recompute the neighbor list.
double padding = 0.15*nonbondedCutoff; double padding = 0.25*nonbondedCutoff;
bool needRecompute = false; bool needRecompute = false;
double closeCutoff2 = 0.25*padding*padding; double closeCutoff2 = 0.25*padding*padding;
double farCutoff2 = 0.5*padding*padding; double farCutoff2 = 0.5*padding*padding;
......
...@@ -59,22 +59,25 @@ public: ...@@ -59,22 +59,25 @@ public:
*/ */
class CpuNeighborList::Voxels { class CpuNeighborList::Voxels {
public: public:
Voxels(int blockSize, float vsy, float vsz, float miny, float maxy, float minz, float maxz, const RealVec* periodicBoxVectors, bool usePeriodic) : 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), periodicBoxVectors(periodicBoxVectors), usePeriodic(usePeriodic) { blockSize(blockSize), voxelSizeY(vsy), voxelSizeZ(vsz), miny(miny), maxy(maxy), minz(minz), maxz(maxz), usePeriodic(usePeriodic) {
periodicBoxSize[0] = (float) periodicBoxVectors[0][0]; for (int i = 0; i < 3; i++)
periodicBoxSize[1] = (float) periodicBoxVectors[1][1]; for (int j = 0; j < 3; j++)
periodicBoxSize[2] = (float) periodicBoxVectors[2][2]; periodicBoxVectors[i][j] = (float) boxVectors[i][j];
recipBoxSize[0] = (float) (1/periodicBoxVectors[0][0]); periodicBoxSize[0] = (float) boxVectors[0][0];
recipBoxSize[1] = (float) (1/periodicBoxVectors[1][1]); periodicBoxSize[1] = (float) boxVectors[1][1];
recipBoxSize[2] = (float) (1/periodicBoxVectors[2][2]); periodicBoxSize[2] = (float) boxVectors[2][2];
triclinic = (periodicBoxVectors[0][1] != 0.0 || periodicBoxVectors[0][2] != 0.0 || recipBoxSize[0] = (float) (1/boxVectors[0][0]);
periodicBoxVectors[1][0] != 0.0 || periodicBoxVectors[1][2] != 0.0 || recipBoxSize[1] = (float) (1/boxVectors[1][1]);
periodicBoxVectors[2][0] != 0.0 || periodicBoxVectors[2][1] != 0.0); 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) { if (usePeriodic) {
ny = (int) floorf(periodicBoxVectors[1][1]/voxelSizeY+0.5f); ny = (int) floorf(boxVectors[1][1]/voxelSizeY+0.5f);
nz = (int) floorf(periodicBoxVectors[2][2]/voxelSizeZ+0.5f); nz = (int) floorf(boxVectors[2][2]/voxelSizeZ+0.5f);
voxelSizeY = periodicBoxVectors[1][1]/ny; voxelSizeY = boxVectors[1][1]/ny;
voxelSizeZ = periodicBoxVectors[2][2]/nz; voxelSizeZ = boxVectors[2][2]/nz;
} }
else { else {
ny = max(1, (int) floorf((maxy-miny)/voxelSizeY+0.5f)); ny = max(1, (int) floorf((maxy-miny)/voxelSizeY+0.5f));
...@@ -110,12 +113,10 @@ public: ...@@ -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]; const vector<pair<float, int> >& bin = bins[y][z];
int lower = 0;
int upper = bin.size();
while (lower < upper) { while (lower < upper) {
int middle = (lower+upper)/2; int middle = (lower+upper)/2;
if (bin[middle].first < x) if (bin[middle].first < x)
...@@ -127,12 +128,10 @@ public: ...@@ -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]; const vector<pair<float, int> >& bin = bins[y][z];
int lower = 0;
int upper = bin.size();
while (lower < upper) { while (lower < upper) {
int middle = (lower+upper)/2; int middle = (lower+upper)/2;
if (bin[middle].first > x) if (bin[middle].first > x)
...@@ -208,7 +207,7 @@ public: ...@@ -208,7 +207,7 @@ public:
// Loop over voxels along the y axis. // 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 starty = centerVoxelIndex.y-dIndexY;
int endy = centerVoxelIndex.y+dIndexY; int endy = centerVoxelIndex.y+dIndexY;
float yoffset = (float) (usePeriodic ? boxz*periodicBoxVectors[2][1] : 0); float yoffset = (float) (usePeriodic ? boxz*periodicBoxVectors[2][1] : 0);
...@@ -225,7 +224,7 @@ public: ...@@ -225,7 +224,7 @@ public:
voxelIndex.y = y; voxelIndex.y = y;
if (usePeriodic) if (usePeriodic)
voxelIndex.y = (y < 0 ? y+ny : (y >= ny ? y-ny : y)); 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); 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 // Identify the range of atoms within this bin we need to search. When using periodic boundary
...@@ -261,30 +260,34 @@ public: ...@@ -261,30 +260,34 @@ public:
int numRanges; int numRanges;
int rangeStart[2]; int rangeStart[2];
int rangeEnd[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) { if (needPeriodic) {
numRanges = 2; numRanges = 2;
rangeEnd[0] = findUpperBound(voxelIndex.y, voxelIndex.z, maxx); rangeEnd[0] = findUpperBound(voxelIndex.y, voxelIndex.z, maxx, rangeStart[0], binSize);
if (rangeStart[0] > 0) { if (rangeStart[0] > 0 && rangeEnd[0] < binSize)
numRanges = 1;
else if (rangeStart[0] > 0) {
rangeStart[1] = 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 { 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(); rangeEnd[1] = bins[voxelIndex.y][voxelIndex.z].size();
} }
} }
else { else {
numRanges = 1; 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); bool periodicRectangular = (needPeriodic && !triclinic);
// Loop over atoms and check to see if they are neighbors of this block. // 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 range = 0; range < numRanges; range++) {
for (int item = rangeStart[range]; item < rangeEnd[range]; item++) { 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. // Avoid duplicate entries.
if (sortedIndex >= lastSortedIndex) if (sortedIndex >= lastSortedIndex)
...@@ -361,7 +364,7 @@ private: ...@@ -361,7 +364,7 @@ private:
int ny, nz; int ny, nz;
float periodicBoxSize[3], recipBoxSize[3]; float periodicBoxSize[3], recipBoxSize[3];
bool triclinic; bool triclinic;
const RealVec* periodicBoxVectors; float periodicBoxVectors[3][3];
const bool usePeriodic; const bool usePeriodic;
vector<vector<vector<pair<float, int> > > > bins; vector<vector<vector<pair<float, int> > > > bins;
}; };
...@@ -444,6 +447,7 @@ void CpuNeighborList::computeNeighborList(int numAtoms, const AlignedArray<float ...@@ -444,6 +447,7 @@ void CpuNeighborList::computeNeighborList(int numAtoms, const AlignedArray<float
// Signal the threads to start running and wait for them to finish. // Signal the threads to start running and wait for them to finish.
gmx_atomic_set(&atomicCounter, 0);
threads.resumeThreads(); threads.resumeThreads();
threads.waitForThreads(); threads.waitForThreads();
...@@ -500,7 +504,11 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI ...@@ -500,7 +504,11 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
vector<int> blockAtoms; vector<int> blockAtoms;
vector<float> blockAtomX(blockSize), blockAtomY(blockSize), blockAtomZ(blockSize); vector<float> blockAtomX(blockSize), blockAtomY(blockSize), blockAtomZ(blockSize);
vector<VoxelIndex> atomVoxelIndex; 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. // Find the atoms in this block and compute their bounding box.
int firstIndex = blockSize*i; int firstIndex = blockSize*i;
...@@ -532,15 +540,25 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI ...@@ -532,15 +540,25 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
// Record the exclusions for this block. // Record the exclusions for this block.
map<int, char> atomFlags;
for (int j = 0; j < atomsInBlock; j++) { for (int j = 0; j < atomsInBlock; j++) {
const set<int>& atomExclusions = (*exclusions)[sortedAtoms[firstIndex+j]]; const set<int>& atomExclusions = (*exclusions)[sortedAtoms[firstIndex+j]];
char mask = 1<<j; char mask = 1<<j;
for (int k = 0; k < (int) blockNeighbors[i].size(); k++) { for (set<int>::const_iterator iter = atomExclusions.begin(); iter != atomExclusions.end(); ++iter) {
int atomIndex = blockNeighbors[i][k]; map<int, char>::iterator thisAtomFlags = atomFlags.find(*iter);
if (atomExclusions.find(atomIndex) != atomExclusions.end()) if (thisAtomFlags == atomFlags.end())
blockExclusions[i][k] |= mask; 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