Unverified Commit 83b8ea75 authored by Zheng GONG's avatar Zheng GONG Committed by GitHub
Browse files

Merge pull request #1 from openmm/master

Update from upstream
parents ba62a938 2ca749a1
...@@ -75,7 +75,7 @@ matrix: ...@@ -75,7 +75,7 @@ matrix:
- sudo: false - sudo: false
dist: trusty dist: trusty
python: 2.7_with_system_site_packages python: 3.6
env: ==STATIC_LIB== env: ==STATIC_LIB==
OPENCL=false OPENCL=false
CUDA=false CUDA=false
...@@ -85,8 +85,8 @@ matrix: ...@@ -85,8 +85,8 @@ matrix:
- sudo: false - sudo: false
dist: trusty dist: trusty
python: 2.7_with_system_site_packages python: 3.6
env: ==PYTHON_2== env: ==PYTHON_3_6==
OPENCL=false OPENCL=false
CUDA=false CUDA=false
CC=$CCACHE/clang CC=$CCACHE/clang
...@@ -95,9 +95,9 @@ matrix: ...@@ -95,9 +95,9 @@ matrix:
CMAKE_FLAGS="-DOPENMM_GENERATE_API_DOCS=ON" CMAKE_FLAGS="-DOPENMM_GENERATE_API_DOCS=ON"
- sudo: false - sudo: false
dist: trusty dist: xenial
python: 3.4 python: 3.8
env: ==PYTHON_3== env: ==PYTHON_3_8==
OPENCL=false OPENCL=false
CUDA=false CUDA=false
CC=$CCACHE/gcc CC=$CCACHE/gcc
......
...@@ -112,7 +112,7 @@ public: ...@@ -112,7 +112,7 @@ public:
* @param particle3 the index of the third particle * @param particle3 the index of the third particle
* @param weight1 the weight factor (between 0 and 1) for the first particle * @param weight1 the weight factor (between 0 and 1) for the first particle
* @param weight2 the weight factor (between 0 and 1) for the second particle * @param weight2 the weight factor (between 0 and 1) for the second particle
* @param weight2 the weight factor (between 0 and 1) for the third particle * @param weight3 the weight factor (between 0 and 1) for the third particle
*/ */
ThreeParticleAverageSite(int particle1, int particle2, int particle3, double weight1, double weight2, double weight3); ThreeParticleAverageSite(int particle1, int particle2, int particle3, double weight1, double weight2, double weight3);
/** /**
......
...@@ -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) 2014-2016 Stanford University and the Authors. * * Portions copyright (c) 2014-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "openmm/TabulatedFunction.h" #include "openmm/TabulatedFunction.h"
#include "openmm/internal/windowsExport.h" #include "openmm/internal/windowsExport.h"
#include "lepton/CustomFunction.h" #include "lepton/CustomFunction.h"
#include <memory>
#include <vector> #include <vector>
namespace OpenMM { namespace OpenMM {
...@@ -146,6 +147,22 @@ private: ...@@ -146,6 +147,22 @@ private:
std::vector<double> values; std::vector<double> values;
}; };
/**
* This is a lightweight wrapper around an immutable CustomFunction. It makes
* cloning very inexpensive since nothing needs to be copied except a single
* pointer.
*/
class OPENMM_EXPORT SharedFunctionWrapper : public Lepton::CustomFunction {
public:
SharedFunctionWrapper(std::shared_ptr<const CustomFunction> pointer);
int getNumArguments() const;
double evaluate(const double* arguments) const;
double evaluateDerivative(const double* arguments, const int* derivOrder) const;
CustomFunction* clone() const;
private:
std::shared_ptr<const CustomFunction> pointer;
};
} // namespace OpenMM } // namespace OpenMM
#endif /*OPENMM_REFERENCETABULATEDFUNCTION_H_*/ #endif /*OPENMM_REFERENCETABULATEDFUNCTION_H_*/
...@@ -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) 2014-2016 Stanford University and the Authors. * * Portions copyright (c) 2014-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -56,19 +56,22 @@ using namespace std; ...@@ -56,19 +56,22 @@ using namespace std;
using Lepton::CustomFunction; using Lepton::CustomFunction;
extern "C" OPENMM_EXPORT CustomFunction* createReferenceTabulatedFunction(const TabulatedFunction& function) { extern "C" OPENMM_EXPORT CustomFunction* createReferenceTabulatedFunction(const TabulatedFunction& function) {
CustomFunction* fn;
if (dynamic_cast<const Continuous1DFunction*>(&function) != NULL) if (dynamic_cast<const Continuous1DFunction*>(&function) != NULL)
return new ReferenceContinuous1DFunction(dynamic_cast<const Continuous1DFunction&>(function)); fn = new ReferenceContinuous1DFunction(dynamic_cast<const Continuous1DFunction&>(function));
if (dynamic_cast<const Continuous2DFunction*>(&function) != NULL) else if (dynamic_cast<const Continuous2DFunction*>(&function) != NULL)
return new ReferenceContinuous2DFunction(dynamic_cast<const Continuous2DFunction&>(function)); fn = new ReferenceContinuous2DFunction(dynamic_cast<const Continuous2DFunction&>(function));
if (dynamic_cast<const Continuous3DFunction*>(&function) != NULL) else if (dynamic_cast<const Continuous3DFunction*>(&function) != NULL)
return new ReferenceContinuous3DFunction(dynamic_cast<const Continuous3DFunction&>(function)); fn = new ReferenceContinuous3DFunction(dynamic_cast<const Continuous3DFunction&>(function));
if (dynamic_cast<const Discrete1DFunction*>(&function) != NULL) else if (dynamic_cast<const Discrete1DFunction*>(&function) != NULL)
return new ReferenceDiscrete1DFunction(dynamic_cast<const Discrete1DFunction&>(function)); fn = new ReferenceDiscrete1DFunction(dynamic_cast<const Discrete1DFunction&>(function));
if (dynamic_cast<const Discrete2DFunction*>(&function) != NULL) else if (dynamic_cast<const Discrete2DFunction*>(&function) != NULL)
return new ReferenceDiscrete2DFunction(dynamic_cast<const Discrete2DFunction&>(function)); fn = new ReferenceDiscrete2DFunction(dynamic_cast<const Discrete2DFunction&>(function));
if (dynamic_cast<const Discrete3DFunction*>(&function) != NULL) else if (dynamic_cast<const Discrete3DFunction*>(&function) != NULL)
return new ReferenceDiscrete3DFunction(dynamic_cast<const Discrete3DFunction&>(function)); fn = new ReferenceDiscrete3DFunction(dynamic_cast<const Discrete3DFunction&>(function));
else
throw OpenMMException("createReferenceTabulatedFunction: Unknown function type"); throw OpenMMException("createReferenceTabulatedFunction: Unknown function type");
return new SharedFunctionWrapper(shared_ptr<const CustomFunction>(fn));
} }
ReferenceContinuous1DFunction::ReferenceContinuous1DFunction(const Continuous1DFunction& function) : function(function) { ReferenceContinuous1DFunction::ReferenceContinuous1DFunction(const Continuous1DFunction& function) : function(function) {
...@@ -298,3 +301,22 @@ double ReferenceDiscrete3DFunction::evaluateDerivative(const double* arguments, ...@@ -298,3 +301,22 @@ double ReferenceDiscrete3DFunction::evaluateDerivative(const double* arguments,
CustomFunction* ReferenceDiscrete3DFunction::clone() const { CustomFunction* ReferenceDiscrete3DFunction::clone() const {
return new ReferenceDiscrete3DFunction(function); return new ReferenceDiscrete3DFunction(function);
} }
SharedFunctionWrapper::SharedFunctionWrapper(shared_ptr<const CustomFunction> pointer) : pointer(pointer) {
}
int SharedFunctionWrapper::getNumArguments() const {
return pointer->getNumArguments();
}
double SharedFunctionWrapper::evaluate(const double* arguments) const {
return pointer->evaluate(arguments);
}
double SharedFunctionWrapper::evaluateDerivative(const double* arguments, const int* derivOrder) const {
return pointer->evaluateDerivative(arguments, derivOrder);
}
CustomFunction* SharedFunctionWrapper::clone() const {
return new SharedFunctionWrapper(pointer);
}
...@@ -563,8 +563,11 @@ class GromacsTopFile(object): ...@@ -563,8 +563,11 @@ class GromacsTopFile(object):
if atomName in atomReplacements: if atomName in atomReplacements:
atomName = atomReplacements[atomName] atomName = atomReplacements[atomName]
# Try to guess the element. # Try to determine the element.
atomicNumber = self._atomTypes[fields[1]][2]
if atomicNumber is None:
# Try to guess the element from the name.
upper = atomName.upper() upper = atomName.upper()
if upper.startswith('CL'): if upper.startswith('CL'):
element = elem.chlorine element = elem.chlorine
...@@ -577,6 +580,10 @@ class GromacsTopFile(object): ...@@ -577,6 +580,10 @@ class GromacsTopFile(object):
element = elem.get_by_symbol(atomName[0]) element = elem.get_by_symbol(atomName[0])
except KeyError: except KeyError:
element = None element = None
elif atomicNumber == '0':
element = None
else:
element = elem.Element.getByAtomicNumber(int(atomicNumber))
atoms.append(top.addAtom(atomName, element, r)) atoms.append(top.addAtom(atomName, element, r))
# Add bonds to the topology # Add bonds to the topology
......
...@@ -1004,7 +1004,7 @@ class Modeller(object): ...@@ -1004,7 +1004,7 @@ class Modeller(object):
del context del context
return actualVariants return actualVariants
def addExtraParticles(self, forcefield): def addExtraParticles(self, forcefield, ignoreExternalBonds=False):
"""Add missing extra particles to the model that are required by a force """Add missing extra particles to the model that are required by a force
field. field.
...@@ -1023,6 +1023,10 @@ class Modeller(object): ...@@ -1023,6 +1023,10 @@ class Modeller(object):
---------- ----------
forcefield : ForceField forcefield : ForceField
the ForceField defining what extra particles should be present the ForceField defining what extra particles should be present
ignoreExternalBonds : boolean=False
If true, ignore external bonds when matching residues to templates.
This is useful when the Topology represents one piece of a larger
molecule, so chains are not terminated properly.
""" """
# Create copies of all residue templates that have had all extra points removed. # Create copies of all residue templates that have had all extra points removed.
...@@ -1090,7 +1094,7 @@ class Modeller(object): ...@@ -1090,7 +1094,7 @@ class Modeller(object):
signature = _createResidueSignature([atom.element for atom in residue.atoms()]) signature = _createResidueSignature([atom.element for atom in residue.atoms()])
if signature in forcefield._templateSignatures: if signature in forcefield._templateSignatures:
for t in forcefield._templateSignatures[signature]: for t in forcefield._templateSignatures[signature]:
if compiled.matchResidueToTemplate(residue, t, bondedToAtom, False) is not None: if compiled.matchResidueToTemplate(residue, t, bondedToAtom, ignoreExternalBonds) is not None:
matchFound = True matchFound = True
if matchFound: if matchFound:
# Just copy the residue over. # Just copy the residue over.
...@@ -1109,7 +1113,7 @@ class Modeller(object): ...@@ -1109,7 +1113,7 @@ class Modeller(object):
if signature in forcefield._templateSignatures: if signature in forcefield._templateSignatures:
for t in forcefield._templateSignatures[signature]: for t in forcefield._templateSignatures[signature]:
if t in templatesNoEP: if t in templatesNoEP:
matches = compiled.matchResidueToTemplate(residueNoEP, templatesNoEP[t], bondedToAtomNoEP, False) matches = compiled.matchResidueToTemplate(residueNoEP, templatesNoEP[t], bondedToAtomNoEP, ignoreExternalBonds)
if matches is not None: if matches is not None:
template = t; template = t;
# Record the corresponding atoms. # Record the corresponding atoms.
......
...@@ -48,6 +48,11 @@ try: ...@@ -48,6 +48,11 @@ try:
have_gzip = True have_gzip = True
except: have_gzip = False except: have_gzip = False
try:
import numpy
have_numpy = True
except: have_numpy = False
class SimulatedTempering(object): class SimulatedTempering(object):
"""SimulatedTempering implements the simulated tempering algorithm for accelerated sampling. """SimulatedTempering implements the simulated tempering algorithm for accelerated sampling.
...@@ -214,6 +219,9 @@ class SimulatedTempering(object): ...@@ -214,6 +219,9 @@ class SimulatedTempering(object):
# Rescale the velocities. # Rescale the velocities.
scale = math.sqrt(self.temperatures[j]/self.temperatures[self.currentTemperature]) scale = math.sqrt(self.temperatures[j]/self.temperatures[self.currentTemperature])
if have_numpy:
velocities = scale*state.getVelocities(asNumpy=True).value_in_unit(unit.nanometers/unit.picoseconds)
else:
velocities = [v*scale for v in state.getVelocities().value_in_unit(unit.nanometers/unit.picoseconds)] velocities = [v*scale for v in state.getVelocities().value_in_unit(unit.nanometers/unit.picoseconds)]
self.simulation.context.setVelocities(velocities) self.simulation.context.setVelocities(velocities)
......
...@@ -196,10 +196,11 @@ class Simulation(object): ...@@ -196,10 +196,11 @@ class Simulation(object):
while stepsToGo > 10: while stepsToGo > 10:
self.integrator.step(10) # Only take 10 steps at a time, to give Python more chances to respond to a control-c. self.integrator.step(10) # Only take 10 steps at a time, to give Python more chances to respond to a control-c.
stepsToGo -= 10 stepsToGo -= 10
self.currentStep += 10
if endTime is not None and datetime.now() >= endTime: if endTime is not None and datetime.now() >= endTime:
return return
self.integrator.step(stepsToGo) self.integrator.step(stepsToGo)
self.currentStep += nextSteps self.currentStep += stepsToGo
if anyReport: if anyReport:
# One or more reporters are ready to generate reports. Organize them into three # One or more reporters are ready to generate reports. Organize them into three
# groups: ones that want wrapped positions, ones that want unwrapped positions, # groups: ones that want wrapped positions, ones that want unwrapped positions,
......
...@@ -172,6 +172,13 @@ class TestGromacsTopFile(unittest.TestCase): ...@@ -172,6 +172,13 @@ class TestGromacsTopFile(unittest.TestCase):
top = GromacsTopFile('systems/bnz.top') top = GromacsTopFile('systems/bnz.top')
gro = GromacsGroFile('systems/bnz.gro') gro = GromacsGroFile('systems/bnz.gro')
for atom in top.topology.atoms():
if atom.name.startswith('C'):
self.assertEqual(elem.carbon, atom.element)
elif atom.name.startswith('H'):
self.assertEqual(elem.hydrogen, atom.element)
else:
self.assertIsNone(atom.element)
system = top.createSystem() system = top.createSystem()
self.assertEqual(26, system.getNumParticles()) self.assertEqual(26, system.getNumParticles())
......
...@@ -147,6 +147,12 @@ class TestSimulation(unittest.TestCase): ...@@ -147,6 +147,12 @@ class TestSimulation(unittest.TestCase):
self.assertTrue(endTime >= startTime+timedelta(seconds=5)) self.assertTrue(endTime >= startTime+timedelta(seconds=5))
self.assertTrue(endTime < startTime+timedelta(seconds=10)) self.assertTrue(endTime < startTime+timedelta(seconds=10))
# Check that the time and step count are consistent.
time = simulation.context.getState().getTime().value_in_unit(picoseconds)
expectedTime = simulation.currentStep*integrator.getStepSize().value_in_unit(picoseconds)
self.assertAlmostEqual(expectedTime, time)
# Load the checkpoint and state and make sure they are both correct. # Load the checkpoint and state and make sure they are both correct.
velocities = simulation.context.getState(getVelocities=True).getVelocities() velocities = simulation.context.getState(getVelocities=True).getVelocities()
......
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