"docs/UsersGuide/vscode:/vscode.git/clone" did not exist on "45d017ab54910a265c21b4362ed2689ece14409b"
Commit fd473eea authored by Peter Eastman's avatar Peter Eastman
Browse files

Merge branch 'master' into nucleic

parents 0a751b5b 6a985cfd
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,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-2010 Stanford University and the Authors. * * Portions copyright (c) 2008-2015 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "lepton/ParsedExpression.h" #include "lepton/ParsedExpression.h"
#include <utility> #include <utility>
#include <map> #include <map>
#include <set>
#include <string> #include <string>
namespace OpenMM { namespace OpenMM {
...@@ -84,7 +85,7 @@ private: ...@@ -84,7 +85,7 @@ private:
class FunctionPlaceholder; class FunctionPlaceholder;
static Lepton::ExpressionTreeNode replaceFunctions(const Lepton::ExpressionTreeNode& node, std::map<std::string, int> atoms, static Lepton::ExpressionTreeNode replaceFunctions(const Lepton::ExpressionTreeNode& node, std::map<std::string, int> atoms,
std::map<std::string, std::vector<int> >& distances, std::map<std::string, std::vector<int> >& angles, std::map<std::string, std::vector<int> >& distances, std::map<std::string, std::vector<int> >& angles,
std::map<std::string, std::vector<int> >& dihedrals); std::map<std::string, std::vector<int> >& dihedrals, std::set<std::string>& variables);
const CustomHbondForce& owner; const CustomHbondForce& owner;
Kernel kernel; Kernel kernel;
}; };
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "lepton/ParsedExpression.h" #include "lepton/ParsedExpression.h"
#include <utility> #include <utility>
#include <map> #include <map>
#include <set>
#include <string> #include <string>
namespace OpenMM { namespace OpenMM {
...@@ -98,7 +99,7 @@ private: ...@@ -98,7 +99,7 @@ private:
class FunctionPlaceholder; class FunctionPlaceholder;
static Lepton::ExpressionTreeNode replaceFunctions(const Lepton::ExpressionTreeNode& node, std::map<std::string, int> atoms, static Lepton::ExpressionTreeNode replaceFunctions(const Lepton::ExpressionTreeNode& node, std::map<std::string, int> atoms,
std::map<std::string, std::vector<int> >& distances, std::map<std::string, std::vector<int> >& angles, std::map<std::string, std::vector<int> >& distances, std::map<std::string, std::vector<int> >& angles,
std::map<std::string, std::vector<int> >& dihedrals); std::map<std::string, std::vector<int> >& dihedrals, std::set<std::string>& variables);
static void generatePermutations(std::vector<int>& values, int numFixed, std::vector<std::vector<int> >& result); static void generatePermutations(std::vector<int>& values, int numFixed, std::vector<std::vector<int> >& result);
const CustomManyParticleForce& owner; const CustomManyParticleForce& owner;
Kernel kernel; Kernel kernel;
......
...@@ -64,6 +64,7 @@ public: ...@@ -64,6 +64,7 @@ public:
} }
std::vector<std::string> getKernelNames(); std::vector<std::string> getKernelNames();
void updateParametersInContext(ContextImpl& context); void updateParametersInContext(ContextImpl& context);
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
/** /**
* This is a utility routine that calculates the values to use for alpha and kmax when using * This is a utility routine that calculates the values to use for alpha and kmax when using
* Ewald summation. * Ewald summation.
......
...@@ -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));
} }
......
...@@ -252,6 +252,10 @@ ContextImpl& Context::getImpl() { ...@@ -252,6 +252,10 @@ ContextImpl& Context::getImpl() {
return *impl; return *impl;
} }
const ContextImpl& Context::getImpl() const {
return *impl;
}
const vector<vector<int> >& Context::getMolecules() const { const vector<vector<int> >& Context::getMolecules() const {
return impl->getMolecules(); return impl->getMolecules();
} }
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "openmm/Context.h" #include "openmm/Context.h"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <cstdlib>
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <utility> #include <utility>
...@@ -115,6 +116,11 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ ...@@ -115,6 +116,11 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
// Select a platform to use. // Select a platform to use.
vector<pair<double, Platform*> > candidatePlatforms; vector<pair<double, Platform*> > candidatePlatforms;
if (platform == NULL) {
char* defaultPlatform = getenv("OPENMM_DEFAULT_PLATFORM");
if (defaultPlatform != NULL)
platform = &Platform::getPlatformByName(string(defaultPlatform));
}
if (platform == NULL) { if (platform == NULL) {
for (int i = 0; i < Platform::getNumPlatforms(); i++) { for (int i = 0; i < Platform::getNumPlatforms(); i++) {
Platform& p = Platform::getPlatform(i); Platform& p = Platform::getPlatform(i);
......
/* -------------------------------------------------------------------------- *
* 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) 2015 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/Force.h"
#include "openmm/OpenMMException.h"
#include "openmm/CustomCentroidBondForce.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/CustomCentroidBondForceImpl.h"
#include <cmath>
#include <map>
#include <set>
#include <sstream>
#include <utility>
using namespace OpenMM;
using std::map;
using std::pair;
using std::set;
using std::string;
using std::stringstream;
using std::vector;
CustomCentroidBondForce::CustomCentroidBondForce(int numGroups, const string& energy) : groupsPerBond(numGroups), energyExpression(energy) {
}
CustomCentroidBondForce::~CustomCentroidBondForce() {
for (int i = 0; i < (int) functions.size(); i++)
delete functions[i].function;
}
const string& CustomCentroidBondForce::getEnergyFunction() const {
return energyExpression;
}
void CustomCentroidBondForce::setEnergyFunction(const std::string& energy) {
energyExpression = energy;
}
int CustomCentroidBondForce::addPerBondParameter(const string& name) {
bondParameters.push_back(BondParameterInfo(name));
return bondParameters.size()-1;
}
const string& CustomCentroidBondForce::getPerBondParameterName(int index) const {
ASSERT_VALID_INDEX(index, bondParameters);
return bondParameters[index].name;
}
void CustomCentroidBondForce::setPerBondParameterName(int index, const string& name) {
ASSERT_VALID_INDEX(index, bondParameters);
bondParameters[index].name = name;
}
int CustomCentroidBondForce::addGlobalParameter(const string& name, double defaultValue) {
globalParameters.push_back(GlobalParameterInfo(name, defaultValue));
return globalParameters.size()-1;
}
const string& CustomCentroidBondForce::getGlobalParameterName(int index) const {
ASSERT_VALID_INDEX(index, globalParameters);
return globalParameters[index].name;
}
void CustomCentroidBondForce::setGlobalParameterName(int index, const string& name) {
ASSERT_VALID_INDEX(index, globalParameters);
globalParameters[index].name = name;
}
double CustomCentroidBondForce::getGlobalParameterDefaultValue(int index) const {
ASSERT_VALID_INDEX(index, globalParameters);
return globalParameters[index].defaultValue;
}
void CustomCentroidBondForce::setGlobalParameterDefaultValue(int index, double defaultValue) {
ASSERT_VALID_INDEX(index, globalParameters);
globalParameters[index].defaultValue = defaultValue;
}
int CustomCentroidBondForce::addGroup(const vector<int>& particles, const vector<double>& weights) {
if (particles.size() != weights.size() && weights.size() > 0)
throw OpenMMException("CustomCentroidBondForce: wrong number of weights specified for a group.");
groups.push_back(GroupInfo(particles, weights));
return groups.size()-1;
}
void CustomCentroidBondForce::getGroupParameters(int index, vector<int>& particles, std::vector<double>& weights) const {
ASSERT_VALID_INDEX(index, groups);
particles = groups[index].particles;
weights = groups[index].weights;
}
void CustomCentroidBondForce::setGroupParameters(int index, const vector<int>& particles, const vector<double>& weights) {
ASSERT_VALID_INDEX(index, groups);
if (particles.size() != weights.size() && weights.size() > 0)
throw OpenMMException("CustomCentroidBondForce: wrong number of weights specified for a group.");
groups[index].particles = particles;
groups[index].weights = weights;
}
int CustomCentroidBondForce::addBond(const vector<int>& groups, const vector<double>& parameters) {
if (groups.size() != groupsPerBond)
throw OpenMMException("CustomCentroidBondForce: wrong number of groups specified for a bond.");
bonds.push_back(BondInfo(groups, parameters));
return bonds.size()-1;
}
void CustomCentroidBondForce::getBondParameters(int index, vector<int>& groups, std::vector<double>& parameters) const {
ASSERT_VALID_INDEX(index, bonds);
groups = bonds[index].groups;
parameters = bonds[index].parameters;
}
void CustomCentroidBondForce::setBondParameters(int index, const vector<int>& groups, const vector<double>& parameters) {
ASSERT_VALID_INDEX(index, bonds);
if (groups.size() != groupsPerBond)
throw OpenMMException("CustomCentroidBondForce: wrong number of groups specified for a bond.");
bonds[index].groups = groups;
bonds[index].parameters = parameters;
}
int CustomCentroidBondForce::addTabulatedFunction(const std::string& name, TabulatedFunction* function) {
functions.push_back(FunctionInfo(name, function));
return functions.size()-1;
}
const TabulatedFunction& CustomCentroidBondForce::getTabulatedFunction(int index) const {
ASSERT_VALID_INDEX(index, functions);
return *functions[index].function;
}
TabulatedFunction& CustomCentroidBondForce::getTabulatedFunction(int index) {
ASSERT_VALID_INDEX(index, functions);
return *functions[index].function;
}
const string& CustomCentroidBondForce::getTabulatedFunctionName(int index) const {
ASSERT_VALID_INDEX(index, functions);
return functions[index].name;
}
ForceImpl* CustomCentroidBondForce::createImpl() const {
return new CustomCentroidBondForceImpl(*this);
}
void CustomCentroidBondForce::updateParametersInContext(Context& context) {
dynamic_cast<CustomCentroidBondForceImpl&>(getImplInContext(context)).updateParametersInContext(getContextImpl(context));
}
/* -------------------------------------------------------------------------- *
* 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-2015 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/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/CustomCentroidBondForceImpl.h"
#include "openmm/kernels.h"
#include "lepton/Operation.h"
#include "lepton/Parser.h"
#include <sstream>
#include <utility>
using namespace OpenMM;
using namespace std;
using Lepton::CustomFunction;
using Lepton::ExpressionTreeNode;
using Lepton::Operation;
using Lepton::ParsedExpression;
/**
* This class serves as a placeholder for angles and dihedrals in expressions.
*/
class CustomCentroidBondForceImpl::FunctionPlaceholder : public CustomFunction {
public:
int numArguments;
FunctionPlaceholder(int numArguments) : numArguments(numArguments) {
}
int getNumArguments() const {
return numArguments;
}
double evaluate(const double* arguments) const {
return 0.0;
}
double evaluateDerivative(const double* arguments, const int* derivOrder) const {
return 0.0;
}
CustomFunction* clone() const {
return new FunctionPlaceholder(numArguments);
}
};
CustomCentroidBondForceImpl::CustomCentroidBondForceImpl(const CustomCentroidBondForce& owner) : owner(owner) {
}
CustomCentroidBondForceImpl::~CustomCentroidBondForceImpl() {
}
void CustomCentroidBondForceImpl::initialize(ContextImpl& context) {
kernel = context.getPlatform().createKernel(CalcCustomCentroidBondForceKernel::Name(), context);
// Check for errors in the specification of parameters and exclusions.
const System& system = context.getSystem();
vector<int> particles;
vector<double> weights;
for (int i = 0; i < owner.getNumGroups(); i++) {
owner.getGroupParameters(i, particles, weights);
for (int j = 0; j < (int) particles.size(); j++)
if (particles[j] < 0 || particles[j] >= system.getNumParticles()) {
stringstream msg;
msg << "CustomCentroidBondForce: Illegal particle index for a group: ";
msg << particles[j];
throw OpenMMException(msg.str());
}
if (weights.size() != particles.size() && weights.size() > 0) {
stringstream msg;
msg << "CustomCentroidBondForce: Wrong number of weights for group ";
msg << i;
throw OpenMMException(msg.str());
}
}
vector<int> groups;
vector<double> parameters;
int numBondParameters = owner.getNumPerBondParameters();
for (int i = 0; i < owner.getNumBonds(); i++) {
owner.getBondParameters(i, groups, parameters);
for (int j = 0; j < (int) groups.size(); j++)
if (groups[j] < 0 || groups[j] >= owner.getNumGroups()) {
stringstream msg;
msg << "CustomCentroidBondForce: Illegal group index for a bond: ";
msg << groups[j];
throw OpenMMException(msg.str());
}
if (parameters.size() != numBondParameters) {
stringstream msg;
msg << "CustomCentroidBondForce: Wrong number of parameters for bond ";
msg << i;
throw OpenMMException(msg.str());
}
}
kernel.getAs<CalcCustomCentroidBondForceKernel>().initialize(context.getSystem(), owner);
}
double CustomCentroidBondForceImpl::calcForcesAndEnergy(ContextImpl& context, bool includeForces, bool includeEnergy, int groups) {
if ((groups&(1<<owner.getForceGroup())) != 0)
return kernel.getAs<CalcCustomCentroidBondForceKernel>().execute(context, includeForces, includeEnergy);
return 0.0;
}
vector<string> CustomCentroidBondForceImpl::getKernelNames() {
vector<string> names;
names.push_back(CalcCustomCentroidBondForceKernel::Name());
return names;
}
map<string, double> CustomCentroidBondForceImpl::getDefaultParameters() {
map<string, double> parameters;
for (int i = 0; i < owner.getNumGlobalParameters(); i++)
parameters[owner.getGlobalParameterName(i)] = owner.getGlobalParameterDefaultValue(i);
return parameters;
}
ParsedExpression CustomCentroidBondForceImpl::prepareExpression(const CustomCentroidBondForce& force, const map<string, CustomFunction*>& customFunctions, map<string, vector<int> >& distances,
map<string, vector<int> >& angles, map<string, vector<int> >& dihedrals) {
CustomCentroidBondForceImpl::FunctionPlaceholder custom(1);
CustomCentroidBondForceImpl::FunctionPlaceholder distance(2);
CustomCentroidBondForceImpl::FunctionPlaceholder angle(3);
CustomCentroidBondForceImpl::FunctionPlaceholder dihedral(4);
map<string, CustomFunction*> functions = customFunctions;
functions["distance"] = &distance;
functions["angle"] = &angle;
functions["dihedral"] = &dihedral;
ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions);
map<string, int> groups;
set<string> variables;
for (int i = 0; i < force.getNumGroupsPerBond(); i++) {
stringstream name, x, y, z;
name << 'g' << (i+1);
x << 'x' << (i+1);
y << 'y' << (i+1);
z << 'z' << (i+1);
groups[name.str()] = i;
variables.insert(x.str());
variables.insert(y.str());
variables.insert(z.str());
}
for (int i = 0; i < force.getNumGlobalParameters(); i++)
variables.insert(force.getGlobalParameterName(i));
for (int i = 0; i < force.getNumPerBondParameters(); i++)
variables.insert(force.getPerBondParameterName(i));
return ParsedExpression(replaceFunctions(expression.getRootNode(), groups, distances, angles, dihedrals, variables)).optimize();
}
ExpressionTreeNode CustomCentroidBondForceImpl::replaceFunctions(const ExpressionTreeNode& node, map<string, int> groups,
map<string, vector<int> >& distances, map<string, vector<int> >& angles, map<string, vector<int> >& dihedrals, set<string>& variables) {
const Operation& op = node.getOperation();
if (op.getId() == Operation::VARIABLE && variables.find(op.getName()) == variables.end())
throw OpenMMException("CustomCentroidBondForce: Unknown variable '"+op.getName()+"'");
if (op.getId() != Operation::CUSTOM || (op.getName() != "distance" && op.getName() != "angle" && op.getName() != "dihedral"))
{
// This is not an angle or dihedral, so process its children.
vector<ExpressionTreeNode> children;
for (int i = 0; i < (int) node.getChildren().size(); i++)
children.push_back(replaceFunctions(node.getChildren()[i], groups, distances, angles, dihedrals, variables));
return ExpressionTreeNode(op.clone(), children);
}
const Operation::Custom& custom = static_cast<const Operation::Custom&>(op);
// Identify the groups this term is based on.
int numArgs = custom.getNumArguments();
vector<int> indices(numArgs);
for (int i = 0; i < numArgs; i++) {
map<string, int>::const_iterator iter = groups.find(node.getChildren()[i].getOperation().getName());
if (iter == groups.end())
throw OpenMMException("CustomCentroidBondForce: Unknown group '"+node.getChildren()[i].getOperation().getName()+"'");
indices[i] = iter->second;
}
// Select a name for the variable and add it to the appropriate map.
stringstream variable;
if (numArgs == 2)
variable << "distance";
else if (numArgs == 3)
variable << "angle";
else
variable << "dihedral";
for (int i = 0; i < numArgs; i++)
variable << indices[i];
string name = variable.str();
if (numArgs == 2)
distances[name] = indices;
else if (numArgs == 3)
angles[name] = indices;
else
dihedrals[name] = indices;
// Return a new node that represents it as a simple variable.
return ExpressionTreeNode(new Operation::Variable(name));
}
vector<pair<int, int> > CustomCentroidBondForceImpl::getBondedParticles() const {
vector<pair<int, int> > bonds;
for (int i = 0; i < owner.getNumBonds(); i++) {
vector<int> groups;
vector<double> parameters;
owner.getBondParameters(i, groups, parameters);
for (int j = 1; j < groups.size(); j++)
for (int k = 0; k < j; k++)
addBondsBetweenGroups(j, k, bonds);
}
return bonds;
}
void CustomCentroidBondForceImpl::addBondsBetweenGroups(int group1, int group2, vector<pair<int, int> >& bonds) const {
vector<int> atoms1;
vector<int> atoms2;
vector<double> weights;
owner.getGroupParameters(group1, atoms1, weights);
owner.getGroupParameters(group2, atoms2, weights);
for (int i = 0; i < atoms1.size(); i++)
for (int j = 0; j < atoms2.size(); j++)
bonds.push_back(make_pair(atoms1[i], atoms2[j]));
}
void CustomCentroidBondForceImpl::updateParametersInContext(ContextImpl& context) {
kernel.getAs<CalcCustomCentroidBondForceKernel>().copyParametersToContext(context, owner);
}
void CustomCentroidBondForceImpl::computeNormalizedWeights(const CustomCentroidBondForce& force, const System& system, vector<vector<double> >& weights) {
int numGroups = force.getNumGroups();
weights.resize(numGroups);
for (int i = 0; i < numGroups; i++) {
vector<int> particles;
vector<double> groupWeights;
force.getGroupParameters(i, particles, groupWeights);
int numParticles = particles.size();
// If weights were not specified, use particle masses.
if (groupWeights.size() == 0) {
groupWeights.resize(numParticles);
for (int j = 0; j < numParticles; j++)
groupWeights[j] = system.getParticleMass(particles[j]);
}
// Normalize the weights.
double total = 0;
for (int j = 0; j < numParticles; j++)
total += groupWeights[j];
if (total == 0.0) {
stringstream msg;
msg << "CustomCentroidBondForce: Weights for group ";
msg << i;
msg << " add to 0";
throw OpenMMException(msg.str());
}
weights[i].resize(numParticles);
for (int j = 0; j < numParticles; j++)
weights[i][j] = groupWeights[j]/total;
}
}
...@@ -136,24 +136,37 @@ ParsedExpression CustomCompoundBondForceImpl::prepareExpression(const CustomComp ...@@ -136,24 +136,37 @@ ParsedExpression CustomCompoundBondForceImpl::prepareExpression(const CustomComp
functions["dihedral"] = &dihedral; functions["dihedral"] = &dihedral;
ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions); ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions);
map<string, int> atoms; map<string, int> atoms;
set<string> variables;
for (int i = 0; i < force.getNumParticlesPerBond(); i++) { for (int i = 0; i < force.getNumParticlesPerBond(); i++) {
stringstream name; stringstream name, x, y, z;
name << 'p' << (i+1); name << 'p' << (i+1);
x << 'x' << (i+1);
y << 'y' << (i+1);
z << 'z' << (i+1);
atoms[name.str()] = i; atoms[name.str()] = i;
variables.insert(x.str());
variables.insert(y.str());
variables.insert(z.str());
} }
return ParsedExpression(replaceFunctions(expression.getRootNode(), atoms, distances, angles, dihedrals)).optimize(); for (int i = 0; i < force.getNumGlobalParameters(); i++)
variables.insert(force.getGlobalParameterName(i));
for (int i = 0; i < force.getNumPerBondParameters(); i++)
variables.insert(force.getPerBondParameterName(i));
return ParsedExpression(replaceFunctions(expression.getRootNode(), atoms, distances, angles, dihedrals, variables)).optimize();
} }
ExpressionTreeNode CustomCompoundBondForceImpl::replaceFunctions(const ExpressionTreeNode& node, map<string, int> atoms, ExpressionTreeNode CustomCompoundBondForceImpl::replaceFunctions(const ExpressionTreeNode& node, map<string, int> atoms,
map<string, vector<int> >& distances, map<string, vector<int> >& angles, map<string, vector<int> >& dihedrals) { map<string, vector<int> >& distances, map<string, vector<int> >& angles, map<string, vector<int> >& dihedrals, set<string>& variables) {
const Operation& op = node.getOperation(); const Operation& op = node.getOperation();
if (op.getId() == Operation::VARIABLE && variables.find(op.getName()) == variables.end())
throw OpenMMException("CustomCompoundBondForce: Unknown variable '"+op.getName()+"'");
if (op.getId() != Operation::CUSTOM || (op.getName() != "distance" && op.getName() != "angle" && op.getName() != "dihedral")) if (op.getId() != Operation::CUSTOM || (op.getName() != "distance" && op.getName() != "angle" && op.getName() != "dihedral"))
{ {
// This is not an angle or dihedral, so process its children. // This is not an angle or dihedral, so process its children.
vector<ExpressionTreeNode> children; vector<ExpressionTreeNode> children;
for (int i = 0; i < (int) node.getChildren().size(); i++) for (int i = 0; i < (int) node.getChildren().size(); i++)
children.push_back(replaceFunctions(node.getChildren()[i], atoms, distances, angles, dihedrals)); children.push_back(replaceFunctions(node.getChildren()[i], atoms, distances, angles, dihedrals, variables));
return ExpressionTreeNode(op.clone(), children); return ExpressionTreeNode(op.clone(), children);
} }
const Operation::Custom& custom = static_cast<const Operation::Custom&>(op); const Operation::Custom& custom = static_cast<const Operation::Custom&>(op);
......
...@@ -119,3 +119,7 @@ ForceImpl* CustomExternalForce::createImpl() const { ...@@ -119,3 +119,7 @@ ForceImpl* CustomExternalForce::createImpl() const {
void CustomExternalForce::updateParametersInContext(Context& context) { void CustomExternalForce::updateParametersInContext(Context& context) {
dynamic_cast<CustomExternalForceImpl&>(getImplInContext(context)).updateParametersInContext(getContextImpl(context)); dynamic_cast<CustomExternalForceImpl&>(getImplInContext(context)).updateParametersInContext(getContextImpl(context));
} }
bool CustomExternalForce::usesPeriodicBoundaryConditions() const {
return (energyExpression.find("periodicdistance") != string::npos);
}
...@@ -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-2012 Stanford University and the Authors. * * Portions copyright (c) 2008-2015 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -215,19 +215,28 @@ ParsedExpression CustomHbondForceImpl::prepareExpression(const CustomHbondForce& ...@@ -215,19 +215,28 @@ ParsedExpression CustomHbondForceImpl::prepareExpression(const CustomHbondForce&
atoms["d1"] = 3; atoms["d1"] = 3;
atoms["d2"] = 4; atoms["d2"] = 4;
atoms["d3"] = 5; atoms["d3"] = 5;
return ParsedExpression(replaceFunctions(expression.getRootNode(), atoms, distances, angles, dihedrals)).optimize(); set<string> variables;
for (int i = 0; i < force.getNumPerDonorParameters(); i++)
variables.insert(force.getPerDonorParameterName(i));
for (int i = 0; i < force.getNumPerAcceptorParameters(); i++)
variables.insert(force.getPerAcceptorParameterName(i));
for (int i = 0; i < force.getNumGlobalParameters(); i++)
variables.insert(force.getGlobalParameterName(i));
return ParsedExpression(replaceFunctions(expression.getRootNode(), atoms, distances, angles, dihedrals, variables)).optimize();
} }
ExpressionTreeNode CustomHbondForceImpl::replaceFunctions(const ExpressionTreeNode& node, map<string, int> atoms, ExpressionTreeNode CustomHbondForceImpl::replaceFunctions(const ExpressionTreeNode& node, map<string, int> atoms,
map<string, vector<int> >& distances, map<string, vector<int> >& angles, map<string, vector<int> >& dihedrals) { map<string, vector<int> >& distances, map<string, vector<int> >& angles, map<string, vector<int> >& dihedrals, set<string>& variables) {
const Operation& op = node.getOperation(); const Operation& op = node.getOperation();
if (op.getId() == Operation::VARIABLE && variables.find(op.getName()) == variables.end())
throw OpenMMException("CustomHBondForce: Unknown variable '"+op.getName()+"'");
if (op.getId() != Operation::CUSTOM || op.getNumArguments() < 2) if (op.getId() != Operation::CUSTOM || op.getNumArguments() < 2)
{ {
// This is not an angle or dihedral, so process its children. // This is not an angle or dihedral, so process its children.
vector<ExpressionTreeNode> children; vector<ExpressionTreeNode> children;
for (int i = 0; i < (int) node.getChildren().size(); i++) for (int i = 0; i < (int) node.getChildren().size(); i++)
children.push_back(replaceFunctions(node.getChildren()[i], atoms, distances, angles, dihedrals)); children.push_back(replaceFunctions(node.getChildren()[i], atoms, distances, angles, dihedrals, variables));
return ExpressionTreeNode(op.clone(), children); return ExpressionTreeNode(op.clone(), children);
} }
const Operation::Custom& custom = static_cast<const Operation::Custom&>(op); const Operation::Custom& custom = static_cast<const Operation::Custom&>(op);
......
...@@ -165,24 +165,40 @@ ParsedExpression CustomManyParticleForceImpl::prepareExpression(const CustomMany ...@@ -165,24 +165,40 @@ ParsedExpression CustomManyParticleForceImpl::prepareExpression(const CustomMany
functions["dihedral"] = &dihedral; functions["dihedral"] = &dihedral;
ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions); ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions);
map<string, int> atoms; map<string, int> atoms;
set<string> variables;
for (int i = 0; i < force.getNumParticlesPerSet(); i++) { for (int i = 0; i < force.getNumParticlesPerSet(); i++) {
stringstream name; stringstream name, x, y, z;
name << 'p' << (i+1); name << 'p' << (i+1);
x << 'x' << (i+1);
y << 'y' << (i+1);
z << 'z' << (i+1);
atoms[name.str()] = i; atoms[name.str()] = i;
variables.insert(x.str());
variables.insert(y.str());
variables.insert(z.str());
for (int j = 0; j < force.getNumPerParticleParameters(); j++) {
stringstream param;
param << force.getPerParticleParameterName(j) << (i+1);
variables.insert(param.str());
}
} }
return ParsedExpression(replaceFunctions(expression.getRootNode(), atoms, distances, angles, dihedrals)).optimize(); for (int i = 0; i < force.getNumGlobalParameters(); i++)
variables.insert(force.getGlobalParameterName(i));
return ParsedExpression(replaceFunctions(expression.getRootNode(), atoms, distances, angles, dihedrals, variables)).optimize();
} }
ExpressionTreeNode CustomManyParticleForceImpl::replaceFunctions(const ExpressionTreeNode& node, map<string, int> atoms, ExpressionTreeNode CustomManyParticleForceImpl::replaceFunctions(const ExpressionTreeNode& node, map<string, int> atoms,
map<string, vector<int> >& distances, map<string, vector<int> >& angles, map<string, vector<int> >& dihedrals) { map<string, vector<int> >& distances, map<string, vector<int> >& angles, map<string, vector<int> >& dihedrals, set<string>& variables) {
const Operation& op = node.getOperation(); const Operation& op = node.getOperation();
if (op.getId() == Operation::VARIABLE && variables.find(op.getName()) == variables.end())
throw OpenMMException("CustomManyParticleForce: Unknown variable '"+op.getName()+"'");
if (op.getId() != Operation::CUSTOM || (op.getName() != "distance" && op.getName() != "angle" && op.getName() != "dihedral")) if (op.getId() != Operation::CUSTOM || (op.getName() != "distance" && op.getName() != "angle" && op.getName() != "dihedral"))
{ {
// This is not an angle or dihedral, so process its children. // This is not an angle or dihedral, so process its children.
vector<ExpressionTreeNode> children; vector<ExpressionTreeNode> children;
for (int i = 0; i < (int) node.getChildren().size(); i++) for (int i = 0; i < (int) node.getChildren().size(); i++)
children.push_back(replaceFunctions(node.getChildren()[i], atoms, distances, angles, dihedrals)); children.push_back(replaceFunctions(node.getChildren()[i], atoms, distances, angles, dihedrals, variables));
return ExpressionTreeNode(op.clone(), children); return ExpressionTreeNode(op.clone(), children);
} }
const Operation::Custom& custom = static_cast<const Operation::Custom&>(op); const Operation::Custom& custom = static_cast<const Operation::Custom&>(op);
......
...@@ -61,6 +61,14 @@ ForceImpl& Force::getImplInContext(Context& context) { ...@@ -61,6 +61,14 @@ ForceImpl& Force::getImplInContext(Context& context) {
throw OpenMMException("getImplInContext: This Force is not present in the Context"); throw OpenMMException("getImplInContext: This Force is not present in the Context");
} }
const ForceImpl& Force::getImplInContext(const Context& context) const {
const vector<ForceImpl*>& impls = context.getImpl().getForceImpls();
for (int i = 0; i < (int) impls.size(); i++)
if (&impls[i]->getOwner() == this)
return *impls[i];
throw OpenMMException("getImplInContext: This Force is not present in the Context");
}
ContextImpl& Force::getContextImpl(Context& context) { ContextImpl& Force::getContextImpl(Context& context) {
return context.getImpl(); return context.getImpl();
} }
...@@ -113,6 +113,10 @@ void NonbondedForce::setPMEParameters(double alpha, int nx, int ny, int nz) { ...@@ -113,6 +113,10 @@ void NonbondedForce::setPMEParameters(double alpha, int nx, int ny, int nz) {
this->nz = nz; this->nz = nz;
} }
void NonbondedForce::getPMEParametersInContext(const Context& context, double& alpha, int& nx, int& ny, int& nz) const {
dynamic_cast<const NonbondedForceImpl&>(getImplInContext(context)).getPMEParameters(alpha, nx, ny, nz);
}
int NonbondedForce::addParticle(double charge, double sigma, double epsilon) { int NonbondedForce::addParticle(double charge, double sigma, double epsilon) {
particles.push_back(ParticleInfo(charge, sigma, epsilon)); particles.push_back(ParticleInfo(charge, sigma, epsilon));
return particles.size()-1; return particles.size()-1;
......
...@@ -278,3 +278,7 @@ double NonbondedForceImpl::calcDispersionCorrection(const System& system, const ...@@ -278,3 +278,7 @@ double NonbondedForceImpl::calcDispersionCorrection(const System& system, const
void NonbondedForceImpl::updateParametersInContext(ContextImpl& context) { void NonbondedForceImpl::updateParametersInContext(ContextImpl& context) {
kernel.getAs<CalcNonbondedForceKernel>().copyParametersToContext(context, owner); kernel.getAs<CalcNonbondedForceKernel>().copyParametersToContext(context, owner);
} }
void NonbondedForceImpl::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
kernel.getAs<CalcNonbondedForceKernel>().getPMEParameters(alpha, nx, ny, nz);
}
...@@ -92,6 +92,46 @@ private: ...@@ -92,6 +92,46 @@ private:
Kernel referenceKernel; Kernel referenceKernel;
}; };
/**
* This kernel is invoked by HarmonicAngleForce to calculate the forces acting on the system and the energy of the system.
*/
class CpuCalcHarmonicAngleForceKernel : public CalcHarmonicAngleForceKernel {
public:
CpuCalcHarmonicAngleForceKernel(std::string name, const Platform& platform, CpuPlatform::PlatformData& data) :
CalcHarmonicAngleForceKernel(name, platform), data(data), angleIndexArray(NULL), angleParamArray(NULL) {
}
~CpuCalcHarmonicAngleForceKernel();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the HarmonicAngleForce this kernel will be used for
*/
void initialize(const System& system, const HarmonicAngleForce& force);
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param includeForces true if forces should be calculated
* @param includeEnergy true if the energy should be calculated
* @return the potential energy due to the force
*/
double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
/**
* Copy changed parameters over to a context.
*
* @param context the context to copy parameters to
* @param force the HarmonicAngleForce to copy the parameters from
*/
void copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force);
private:
CpuPlatform::PlatformData& data;
int numAngles;
int **angleIndexArray;
RealOpenMM **angleParamArray;
CpuBondForce bondForce;
};
/** /**
* This kernel is invoked by PeriodicTorsionForce to calculate the forces acting on the system and the energy of the system. * This kernel is invoked by PeriodicTorsionForce to calculate the forces acting on the system and the energy of the system.
*/ */
...@@ -204,6 +244,15 @@ public: ...@@ -204,6 +244,15 @@ public:
* @param force the NonbondedForce to copy the parameters from * @param force the NonbondedForce to copy the parameters from
*/ */
void copyParametersToContext(ContextImpl& context, const NonbondedForce& force); void copyParametersToContext(ContextImpl& context, const NonbondedForce& force);
/**
* Get the parameters being used for PME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private: private:
class PmeIO; class PmeIO;
CpuPlatform::PlatformData& data; CpuPlatform::PlatformData& data;
...@@ -220,6 +269,7 @@ private: ...@@ -220,6 +269,7 @@ private:
CpuNeighborList* neighborList; CpuNeighborList* neighborList;
CpuNonbondedForce* nonbonded; CpuNonbondedForce* nonbonded;
Kernel optimizedPme; Kernel optimizedPme;
CpuBondForce bondForce;
}; };
/** /**
......
/* Portions copyright (c) 2013 Stanford University and Simbios. /* Portions copyright (c) 2013-2015 Stanford University and Simbios.
* Authors: Peter Eastman * Authors: Peter Eastman
* Contributors: * Contributors:
* *
...@@ -37,6 +37,7 @@ class CpuLangevinDynamics : public ReferenceStochasticDynamics { ...@@ -37,6 +37,7 @@ class CpuLangevinDynamics : public ReferenceStochasticDynamics {
public: public:
class Update1Task; class Update1Task;
class Update2Task; class Update2Task;
class Update3Task;
/** /**
* Constructor. * Constructor.
* *
...@@ -80,9 +81,21 @@ public: ...@@ -80,9 +81,21 @@ public:
void updatePart2(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& velocities, void updatePart2(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& velocities,
std::vector<OpenMM::RealVec>& forces, std::vector<RealOpenMM>& inverseMasses, std::vector<OpenMM::RealVec>& xPrime); std::vector<OpenMM::RealVec>& forces, std::vector<RealOpenMM>& inverseMasses, std::vector<OpenMM::RealVec>& xPrime);
/**
* Third update
*
* @param numberOfAtoms number of atoms
* @param atomCoordinates atom coordinates
* @param velocities velocities
* @param inverseMasses inverse atom masses
*/
void updatePart3(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& velocities,
std::vector<RealOpenMM>& inverseMasses, std::vector<OpenMM::RealVec>& xPrime);
private: private:
void threadUpdate1(int threadIndex); void threadUpdate1(int threadIndex);
void threadUpdate2(int threadIndex); void threadUpdate2(int threadIndex);
void threadUpdate3(int threadIndex);
OpenMM::ThreadPool& threads; OpenMM::ThreadPool& threads;
OpenMM::CpuRandom& random; OpenMM::CpuRandom& random;
std::vector<OpenMM_SFMT::SFMT> threadRandom; std::vector<OpenMM_SFMT::SFMT> threadRandom;
......
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