Commit 76f7acf7 authored by Nate Stanley's avatar Nate Stanley
Browse files

Merge branch 'master' into update_ug

parents 4fd6934b c3847685
.. _app :
Application Layer
=================
Loaders and Setup
~~~~~~~~~~~~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
{% for fileclass in fileclasses %}
~{{ fileclass }}
{% endfor %}
Representation and Manipulation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
~simtk.openmm.app.topology.Topology
~simtk.openmm.app.modeller.Modeller
Simulation
~~~~~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
~simtk.openmm.app.forcefield.ForceField
~simtk.openmm.app.simulation.Simulation
Reporting Output
~~~~~~~~~~~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
{% for reporter in reporters %}
~{{ reporter }}
{% endfor %}
Extras
~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
{% for extra in app_extras %}
~{{ extra }}
{% endfor %}
# -*- coding: utf-8 -*-
import sys
import os
import simtk.openmm.version
extensions = ['sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.autosummary',
'sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'process-docstring',
'sphinxcontrib.lunrsearch']
autosummary_generate = True
autodoc_default_flags = ['members', 'inherited-members']
autodoc_member_order = 'bysource'
source_suffix = '.rst'
master_doc = 'index'
project = u'OpenMM'
copyright = u'2015, Stanford University and the Authors'
version = simtk.openmm.version.short_version
release = simtk.openmm.version.full_version
exclude_patterns = ['_build', '_templates']
html_static_path = ['_static']
templates_path = ['_templates']
pygments_style = 'sphinx'
html_theme = "alabaster"
html_theme_options = {
'description': "High performance molecular simulation on GPUs",
'github_button': False,
# 'github_user': 'pandegroup',
# 'github_repo': 'openmm',
'logo_name': False,
'logo': 'logo.png',
}
html_sidebars = {
'**': [
'about.html',
'searchbox.html',
'navigation.html',
]
}
# Napoleon settings
napoleon_google_docstring = False
napoleon_numpy_docstring = True
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = False
napoleon_use_admonition_for_notes = False
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_rtype = True
.. currentmodule:: simtk.openmm.openmm
OpenMM Python API
=================
The Python API provides information about the classes and methods available in OpenMM for Python developers.
OpenMM consists of two parts. First, there is a set of :ref:`libraries <library>` for performing many types of computations needed for molecular simulations: force evaluation, numerical integration, energy minimization, etc.
Second, there is an :ref:`application layer <app>`, a set of Python libraries providing a high level interface for running simulations. This layer is targeted at computational biologists or other people who want to run simulations, and who may or may not be programmers.
See the user guide for more details.
.. toctree::
:maxdepth: 2
app
library
.. _library :
Library Layer
=============
Core Objects
~~~~~~~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
:nosignatures:
~simtk.openmm.openmm.System
~simtk.openmm.openmm.Context
~simtk.openmm.openmm.Platform
~simtk.openmm.openmm.State
Forces
~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
:nosignatures:
{% for force in forces %}
~{{ force }}
{% endfor %}
Integrators
~~~~~~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
:nosignatures:
{% for integrator in integrators %}
~{{ integrator }}
{% endfor %}
Extras
~~~~~~
.. autosummary::
:toctree: generated/
:template: class.rst
:nosignatures:
{% for extra in library_extras %}
~{{ extra }}
{% endfor %}
import re
def process_docstring(app, what, name, obj, options, lines):
"""This hook edits the docstrings to replace "<tt><pre>" html tags
with sphinx directives.
"""
def repl(m):
s = m.group(1)
if not s.startswith(linesep):
s = linesep + s
newline = '.. code-block:: c++' + linesep
return newline + ' ' + s.replace(linesep, linesep + ' ')
if name == 'simtk.openmm.openmm.CustomTorsionForce':
print(lines)
linesep = '|LINEBREAK|'
joined = linesep.join(lines)
joined = re.sub(r'<tt><pre>((|LINEBREAK|)?.*?)</pre></tt>', repl, joined)
joined = re.sub(r'<tt>(.*?)</tt>', repl, joined)
lines[:] = [(l if not l.isspace() else '') for l in joined.split(linesep)]
def setup(app):
app.connect('autodoc-process-docstring', process_docstring)
def test():
lines = ['Hello World', '<tt><pre>', 'contents', '</pre></tt>', '', '<tt>contents2</tt>']
linesRef = ['Hello World', '.. code-block:: c++', '', ' contents', '', '', '.. code-block:: c++', '', ' contents2']
process_docstring(None, None, None, None, None, lines)
assert lines == linesRef
if __name__ == '__main__':
test()
"""
The function of this script is to render the Jinja2 templates in the current
directory into input files for sphinx. It introspects the OpenMM Python module
to find all of the classes and formats them for inclusion into the templates.
"""
from os.path import dirname, join, splitext, basename
from glob import glob
import inspect
import jinja2
import simtk.openmm
import simtk.openmm.app
def fullname(klass):
return klass.__module__ + '.' + klass.__name__
def library_template_variables():
"""Create the data structure available to the Jinja2 renderer when
filling in the templates.
This function extracts all of classes in ``simtk.openmm.openmm`` and returns
a dictionary with them grouped into three lists, the integrators, the forces,
and the remainder (library_extras).
A couple core classes are skipped, because they're included manually in the
template.
"""
data = {
'integrators': [],
'forces': [],
'library_extras': [],
}
mm_klasses = inspect.getmembers(simtk.openmm, predicate=inspect.isclass)
# gather all Force subclasses
for name, klass in mm_klasses:
if issubclass(klass, simtk.openmm.openmm.Force):
data['forces'].append(fullname(klass))
# gather all Integrator subclasses
for _, klass in mm_klasses:
if issubclass(klass, simtk.openmm.openmm.Integrator):
data['integrators'].append(fullname(klass))
# gather all extra subclasses in simtk.openmm.openmm
# core classes that are already included in library.rst.jinja2
exclude = ['simtk.openmm.openmm.Platform', 'simtk.openmm.openmm.Context',
'simtk.openmm.openmm.System', 'simtk.openmm.openmm.State']
exclude.extend(data['forces'])
exclude.extend(data['integrators'])
# these classes are useless and not worth documenting.
exclude.extend([
'simtk.openmm.openmm.SwigPyIterator',
'simtk.openmm.openmm.OpenMMException'])
for _, klass in mm_klasses:
full = fullname(klass)
if full not in exclude and not klass.__name__[0].islower():
data['library_extras'].append(full)
return data
def app_template_variables():
"""Create the data structure available to the Jinja2 renderer when
filling in the templates.
This function extracts all of classes in ``simtk.openmm.app`` and returns
a dictionary with them grouped into three lists, the reporters, the
classes with the word "File" in the name, and the remainder.
Four classes are skipped (see exclude), because they're included manually
in the template.
"""
data = {
'reporters': [],
'fileclasses': [],
'app_extras': [],
}
app_klasses = inspect.getmembers(simtk.openmm.app, predicate=inspect.isclass)
# gather all Reporters
for name, klass in app_klasses:
if name.endswith('Reporter'):
data['reporters'].append(fullname(klass))
# gather all classes with "File" in the name
for name, klass in app_klasses:
if 'File' in name:
data['fileclasses'].append(fullname(klass))
# gather all extra subclasses in simtk.openmm.app
exclude = ['simtk.openmm.app.topology.Topology',
'simtk.openmm.app.modeller.Modeller',
'simtk.openmm.app.forcefield.ForceField',
'simtk.openmm.app.simulation.Simulation']
exclude.extend(data['reporters'])
exclude.extend(data['fileclasses'])
for _, klass in app_klasses:
full = fullname(klass)
if full not in exclude and not klass.__name__[0].islower():
data['app_extras'].append(full)
return data
def main():
here = dirname(__file__)
templateLoader = jinja2.FileSystemLoader(here)
templateEnv = jinja2.Environment(loader=templateLoader)
data = library_template_variables()
data.update(app_template_variables())
for template_fn in map(basename, glob(join(here, '*.jinja2'))):
output_fn = splitext(template_fn)[0]
print('Rendering %s to %s...' % (template_fn, output_fn))
template = templateEnv.get_template(template_fn)
output_text = template.render(data)
with open(output_fn, 'w') as f:
f.write(output_text)
if __name__ == '__main__':
main()
......@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'agogo'
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
......
......@@ -38,20 +38,64 @@ Follow these instructions to install OpenMM. There also is an online
troubleshooting guide that describes common problems and how to fix them
(http://wiki.simtk.org/openmm/FAQApp).
There are two ways to install OpenMM: using the Conda package manager (http://conda.pydata.org),
or with standalone installers. (A third option is to compile it from source, which is
discussed in Chapter :ref:`compiling-openmm-from-source-code`.) Using Conda is
the easier method, and is recommended for most users. It is described first,
and then the following sections describe how to use the standalone installers
for various platforms.
Installing with Conda
*********************
Conda is included as part of the Anaconda Python distribution, which you can
download from http://docs.continuum.io/anaconda/install. This is a Python
distribution specifically designed for scientific applications, with many of the
most popular mathematical and scientific packages preinstalled. Alternatively
you can use Miniconda (available from http://conda.pydata.org/miniconda.html),
which includes only Python itself, plus the Conda package manager. That offers
a much smaller initial download, with the ability to then install only the
packages you want.
1. Begin by installing the most recent 64 bit, Python 3.x version of either
Anaconda or Miniconda.
2. (Optional) If you want to run OpenMM on a GPU, install CUDA and/or OpenCL.
* If you have an Nvidia GPU, download CUDA 7.5 from
https://developer.nvidia.com/cuda-downloads. Be sure to install both the
drivers and toolkit. OpenCL is included with the CUDA drivers.
* If you have an AMD GPU and are using Linux or Windows, download the latest
version of the Catalyst driver from http://support.amd.com. On OS X, OpenCL
is included with the operating system and is supported on OS X 10.10.3 or
later.
3. Open a command line terminal and type the following command
::
conda install -c omnia openmm
4. Verify your installation by typing the following command:
::
python -m simtk.testInstallation
This command confirms that OpenMM is installed, checks whether GPU acceleration
is available (via the OpenCL and/or CUDA platforms), and verifies that all
platforms produce consistent results.
.. _installing-on-mac-os-x:
Installing on Mac OS X
**********************
OpenMM works on Mac OS X 10.7 or later.
.. note::
The OpenCL implementations on all recent versions of Mac OS X contain serious
bugs that make them unsuitable for use with OpenMM. GPU acceleration is
therefore only supported with the CUDA platform. This limits it to only Nvidia
GPUs, not AMD or Intel GPUs.
OpenMM works on Mac OS X 10.7 or later. OpenCL is supported on OS X 10.10.3 or
later.
1. Download the pre-compiled binary of OpenMM for Mac OS X, then double click
1. Download the pre-compiled binary of OpenMM for Mac OS X from
https://simtk.org/project/xml/downloads.xml?group_id=161, then double click
the .zip file to expand it.
2. If you have not already done so, install Apples Xcode developer tools from
......@@ -61,7 +105,7 @@ and tell it to install the command line tools. With Xcode 4.2 and earlier, the
command line tools are automatically installed when you install Xcode.)
3. (Optional) If you have an Nvidia GPU and want to use the CUDA platform,
download CUDA 7.0 from https://developer.nvidia.com/cuda-downloads. Be sure to
download CUDA 7.5 from https://developer.nvidia.com/cuda-downloads. Be sure to
install both the drivers and toolkit.
4. (Optional) If you plan to use the CPU platform, it is recommended that you
......@@ -116,7 +160,8 @@ produce an error. You will only see this option if your laptop has two GPUs
Installing on Linux
*******************
1. Download the pre-compiled binary of OpenMM for Linux, then double click the
1. Download the pre-compiled binary of OpenMM for Linux from
https://simtk.org/project/xml/downloads.xml?group_id=161, then double click the
.zip file to expand it.
2. Make sure you have Python 2.6 or higher (earlier versions will not work) and
......@@ -126,7 +171,7 @@ into a console window.
3. (Optional) If you want to run OpenMM on a GPU, install CUDA and/or OpenCL.
* If you have an Nvidia GPU, download CUDA 7.0 from
* If you have an Nvidia GPU, download CUDA 7.5 from
https://developer.nvidia.com/cuda-downloads. Be sure to install both the
drivers and toolkit. OpenCL is included with the CUDA drivers.
* If you have an AMD GPU, download the latest version of the Catalyst driver
......@@ -180,7 +225,8 @@ platforms produce consistent results.
Installing on Windows
*********************
1. Download the pre-compiled binary of OpenMM for Windows, then double click the
1. Download the pre-compiled binary of OpenMM for Windows from
https://simtk.org/project/xml/downloads.xml?group_id=161, then double click the
.zip file to expand it. Move the files to :file:`C:\\Program Files\\OpenMM`.
2. Make sure you have the 64-bit version of Python 3.3 or 3.4 (other versions will not
......@@ -197,7 +243,7 @@ and ignore it.)
4. (Optional) If you want to run OpenMM on a GPU, install CUDA and/or OpenCL.
* If you have an Nvidia GPU, download CUDA 7.0 from
* If you have an Nvidia GPU, download CUDA 7.5 from
https://developer.nvidia.com/cuda-downloads. Be sure to install both the
drivers and toolkit. OpenCL is included with the CUDA drivers.
* If you have an AMD GPU, download the latest version of the Catalyst driver
......@@ -723,7 +769,7 @@ For the main force field, OpenMM provides the following options:
.. tabularcolumns:: |l|L|
============================= ================================================================================
File Force Field
File Force Field
============================= ================================================================================
:code:`amber96.xml` Amber96\ :cite:`Kollman1997`
:code:`amber99sb.xml` Amber99\ :cite:`Wang2000` with modified backbone torsions\ :cite:`Hornak2006`
......@@ -731,7 +777,7 @@ File Force Field
:code:`amber99sbnmr.xml` Amber99SB with modifications to fit NMR data\ :cite:`Li2010`
:code:`amber03.xml` Amber03\ :cite:`Duan2003`
:code:`amber10.xml` Amber10 (documented in the AmberTools_ manual as `ff10`)
:code:`amoeba2009.xml` AMOEBA 2009\ :cite:`Ren2002`. This force field is deprecated. It is
:code:`amoeba2009.xml` AMOEBA 2009\ :cite:`Ren2002`. This force field is deprecated. It is
recommended to use AMOEBA 2013 instead.
:code:`amoeba2013.xml` AMOEBA 2013\ :cite:`Shi2013`
:code:`charmm_polar_2013.xml` CHARMM 2013 polarizable force field\ :cite:`Lopes2013`
......@@ -746,14 +792,14 @@ files:
.. tabularcolumns:: |l|L|
=================== ============================================
File Water Model
File Water Model
=================== ============================================
:code:`tip3p.xml` TIP3P water model\ :cite:`Jorgensen1983`
:code:`tip3pfb.xml` TIP3P-FB water model\ :cite:`Wang2014`
:code:`tip4pew.xml` TIP4P-Ew water model\ :cite:`Horn2004`
:code:`tip4pfb.xml` TIP4P-FB water model\ :cite:`Wang2014`
:code:`tip5p.xml` TIP5P water model\ :cite:`Mahoney2000`
:code:`spce.xml` SPC/E water model\ :cite:`Berendsen1987`
:code:`tip3p.xml` TIP3P water model\ :cite:`Jorgensen1983`
:code:`tip3pfb.xml` TIP3P-FB water model\ :cite:`Wang2014`
:code:`tip4pew.xml` TIP4P-Ew water model\ :cite:`Horn2004`
:code:`tip4pfb.xml` TIP4P-FB water model\ :cite:`Wang2014`
:code:`tip5p.xml` TIP5P water model\ :cite:`Mahoney2000`
:code:`spce.xml` SPC/E water model\ :cite:`Berendsen1987`
:code:`swm4ndp.xml` SWM4-NDP water model\ :cite:`Lamoureux2006`
=================== ============================================
......@@ -769,7 +815,7 @@ the following files:
.. tabularcolumns:: |l|L|
========================= =================================================================================================
File Implicit Solvation Model
File Implicit Solvation Model
========================= =================================================================================================
:code:`amber96_obc.xml` GBSA-OBC solvation model\ :cite:`Onufriev2004` for use with Amber96 force field
:code:`amber99_obc.xml` GBSA-OBC solvation model for use with Amber99 force fields
......@@ -821,15 +867,15 @@ allowed values for :code:`implicitSolvent`\ :
.. tabularcolumns:: |l|L|
============= ==================================================================================================================================
Value Meaning
Value Meaning
============= ==================================================================================================================================
:code:`None` No implicit solvent is used.
:code:`HCT` Hawkins-Cramer-Truhlar GBSA model\ :cite:`Hawkins1995` (corresponds to igb=1 in AMBER)
:code:`OBC1` Onufriev-Bashford-Case GBSA model\ :cite:`Onufriev2004` using the GB\ :sup:`OBC`\ I parameters (corresponds to igb=2 in AMBER).
:code:`None` No implicit solvent is used.
:code:`HCT` Hawkins-Cramer-Truhlar GBSA model\ :cite:`Hawkins1995` (corresponds to igb=1 in AMBER)
:code:`OBC1` Onufriev-Bashford-Case GBSA model\ :cite:`Onufriev2004` using the GB\ :sup:`OBC`\ I parameters (corresponds to igb=2 in AMBER).
:code:`OBC2` Onufriev-Bashford-Case GBSA model\ :cite:`Onufriev2004` using the GB\ :sup:`OBC`\ II parameters (corresponds to igb=5 in AMBER).
This is the same model used by the GBSA-OBC files described in Section :ref:`force-fields`.
:code:`GBn` GBn solvation model\ :cite:`Mongan2007` (corresponds to igb=7 in AMBER).
:code:`GBn2` GBn2 solvation model\ :cite:`Nguyen2013` (corresponds to igb=8 in AMBER).
:code:`GBn` GBn solvation model\ :cite:`Mongan2007` (corresponds to igb=7 in AMBER).
:code:`GBn2` GBn2 solvation model\ :cite:`Nguyen2013` (corresponds to igb=8 in AMBER).
============= ==================================================================================================================================
......@@ -867,13 +913,13 @@ The :code:`nonbondedMethod` parameter can have any of the following values:
.. tabularcolumns:: |l|L|
========================= ===========================================================================================================================================================================================================================================
Value Meaning
Value Meaning
========================= ===========================================================================================================================================================================================================================================
:code:`NoCutoff` No cutoff is applied.
:code:`CutoffNonPeriodic` The reaction field method is used to eliminate all interactions beyond a cutoff distance. Not valid for AMOEBA.
:code:`NoCutoff` No cutoff is applied.
:code:`CutoffNonPeriodic` The reaction field method is used to eliminate all interactions beyond a cutoff distance. Not valid for AMOEBA.
:code:`CutoffPeriodic` The reaction field method is used to eliminate all interactions beyond a cutoff distance. Periodic boundary conditions are applied, so each atom interacts only with the nearest periodic copy of every other atom. Not valid for AMOEBA.
:code:`Ewald` Periodic boundary conditions are applied. Ewald summation is used to compute long range interactions. (This option is rarely used, since PME is much faster for all but the smallest systems.) Not valid for AMOEBA.
:code:`PME` Periodic boundary conditions are applied. The Particle Mesh Ewald method is used to compute long range interactions.
:code:`Ewald` Periodic boundary conditions are applied. Ewald summation is used to compute long range interactions. (This option is rarely used, since PME is much faster for all but the smallest systems.) Not valid for AMOEBA.
:code:`PME` Periodic boundary conditions are applied. The Particle Mesh Ewald method is used to compute long range interactions.
========================= ===========================================================================================================================================================================================================================================
......@@ -922,29 +968,33 @@ If :code:`vdwCutoff` is not specified, then the value of
Specifying the Polarization Method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OpenMM allows the setting of several other parameters particular to the AMOEBA
force field. The :code:`mutualInducedTargetEpsilon` option allows you to
specify the accuracy to which the induced dipoles are calculated at each time
step; the default value is 0.01. The :code:`polarization` setting
determines whether the calculation of the induced dipoles is continued until the
dipoles are self-consistent to within the tolerance specified by
:code:`mutualInducedTargetEpsilon` or whether a quick estimate of the induced
dipoles is used instead. The first option corresponds to the
:code:`polarization='mutual'` setting and is the default; the quick estimate
option is given by :code:`polarization='direct'` and in this case,
:code:`mutualInducedTargetEpsilon` is ignored, if provided. Simulations using
:code:`polarization='direct'` will be significantly faster than those with
:code:`polarization='mutual'`\ , but less accurate. Examples using the two
options are given below:
When using the AMOEBA force field, OpenMM allows the induced dipoles to be
calculated in any of three different ways. The slowest but potentially most
accurate method is to iterate the calculation until the dipoles converge to a
specified tolerance. To select this, specify :code:`polarization='mutual'`.
Use the :code:`mutualInducedTargetEpsilon` option to select the tolerance; for
most situations, a value of 0.00001 works well. Alternatively you can specify
:code:`polarization='extrapolated'`. This uses an analytic approximation
:cite:`Simmonett2015` to estimate what the fully converged dipoles will be without
actually continuing the calculation to convergence. In many cases this can be
significantly faster with only a small loss in accuracy. Finally, you can
specify :code:`polarization='direct'` to use the direct polarization
approximation, in which induced dipoles depend only on the fixed multipoles, not
on other induced dipoles. This is even faster, but it produces very different
forces from mutual polarization, so it should only be used with force fields
that have been specifically parameterized for use with this approximation.
Here are examples of using each method:
::
system = forcefield.createSystem(nonbondedMethod=PME,
nonbondedCutoff=1*nanometer,ewaldErrorTolerance=0.00001,
vdwCutoff=1.2*nanometer, mutualInducedTargetEpsilon=0.01)
system = forcefield.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer,
vdwCutoff=1.2*nanometer, polarization='mutual', mutualInducedTargetEpsilon=0.00001)
system = forcefield.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer,
vdwCutoff=1.2*nanometer, polarization='extrapolated')
system = forcefield.createSystem(nonbondedMethod=PME,
nonbondedCutoff=1*nanometer,ewaldErrorTolerance=0.00001,
vdwCutoff=1.2*nanometer, polarization ='direct')
system = forcefield.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer,
vdwCutoff=1.2*nanometer, polarization='direct')
Implicit Solvent and Solute Dielectrics
......@@ -984,11 +1034,11 @@ The :code:`constraints` parameter can have any of the following values:
.. tabularcolumns:: |l|L|
================ =============================================================================================================================================
Value Meaning
Value Meaning
================ =============================================================================================================================================
:code:`None` No constraints are applied. This is the default value.
:code:`HBonds` The lengths of all bonds that involve a hydrogen atom are constrained.
:code:`AllBonds` The lengths of all bonds are constrained.
:code:`None` No constraints are applied. This is the default value.
:code:`HBonds` The lengths of all bonds that involve a hydrogen atom are constrained.
:code:`AllBonds` The lengths of all bonds are constrained.
:code:`HAngles` The lengths of all bonds are constrained. In addition, all angles of the form H-X-H or H-O-X (where X is an arbitrary atom) are constrained.
================ =============================================================================================================================================
......@@ -1730,19 +1780,19 @@ Here is the definition of the :class:`ForceReporter` class:
.. samepage::
::
class ForceReporter(object):
def __init__(self, file, reportInterval):
self._out = open(file, 'w')
self._reportInterval = reportInterval
def __del__(self):
self._out.close()
def describeNextReport(self, simulation):
steps = self._reportInterval - simulation.currentStep%self._reportInterval
return (steps, False, False, True, False)
def report(self, simulation, state):
forces = state.getForces().value_in_unit(kilojoules/mole/nanometer)
for f in forces:
......@@ -2013,6 +2063,49 @@ are :code:`wo1`\ , :code:`wo2`\ , :code:`wo3`\ , :code:`wx1`\ , :code:`wx2`\ ,
:code:`wx3`\ , :code:`wy1`\ , :code:`wy2`\ , :code:`wy3`\ , :code:`p1`\ ,
:code:`p2`\ , and :code:`p3`\ .
Missing residue templates
=========================
.. CAUTION::
These features are experimental, and its API is subject to change.
You can use the :method:`getUnmatchedResidues()` method to get a list of residues
in the provided :code:`topology` object that do not currently have a matching
residue template defined in the :class:`ForceField`.
::
pdb = PDBFile('input.pdb')
forcefield = ForceField('amber99sb.xml', 'tip3p.xml')
unmatched_residues = forcefield.getUnmatchedResidues(topology)
This is useful for identifying issues with prepared systems, debugging issues
with residue template definitions, or identifying which additional residues need
to be parameterized.
As a convenience for parameterizing new residues, you can also get a list of
residues and empty residue templates using :method:`generateTemplatesForUnmatchedResidues`
::
pdb = PDBFile('input.pdb')
forcefield = ForceField('amber99sb.xml', 'tip3p.xml')
[templates, residues] = forcefield.generateTemplatesForUnmatchedResidues(topology)
# Se the atom types
for template in templates:
for atom in template.atoms:
atom.type = ... # set the atom types here
# Register the template with the forcefield.
forcefield.registerResidueTemplate(template)
If you find that templates seem to be incorrectly matched, another useful
function :method:`getMatchingTemplates()` can help you identify which templates
are being matched:
::
pdb = PDBFile('input.pdb')
forcefield = ForceField('amber99sb.xml', 'tip3p.xml')
templates = forcefield.getMatchingTemplates(topology)
for (residue, template) in zip(pdb.topology.residues(), templates):
print "Residue %d %s matched template %s" % (residue.id, residue.name, template.name)
<HarmonicBondForce>
===================
......@@ -2715,6 +2808,9 @@ The ForceField class is designed to be modular and extensible. This means you
can add support for entirely new force types, such as ones implemented with
plugins.
Adding new force types
======================
For every force class, there is a generator class that parses the
corresponding XML tag, then creates Force objects and adds them to the System.
ForceField maintains a map of tag names to generator classes. When a ForceField
......@@ -2778,3 +2874,58 @@ parsing it.
Now you can simply create a ForceField object as usual. If an XML file contains
a :code:`<MyForce>` tag, it will be recognized and processed correctly.
Adding residue template generators
==================================
.. CAUTION::
This feature is experimental, and its API is subject to change.
Typically, when :class:`ForceField` encounters a residue it does not have a template for,
it simply raises an :code:`Exception`, since it does not know how to assign atom types for
the unknown residue.
However, :class:`ForceField` has an API for registering *residue template generators* that are
called when a residue without an existing template is encountered. These generators
may create new residue templates that match existing atom types and parameters, or can
even create new atom types and new parameters that are added to :class:`ForceField`. This
functionality can be useful for adding residue template generators that are able to
parameterize small molecules that are not represented in a protein or nucleic acid
forcefield, for example, or for creating new residue templates for post-translationally
modified residues, covalently-bound ligands, or unnatural amino acids or bases.
To register a new residue template generator named :code:`generator`, simply call the
:meth:`registerTemplateGenerator` method on an existing :class:`ForceField` object:
::
forcefield.registerTemplateGenerator(generator)
This :code:`generator` function must conform to the following API:
::
def generator(forcefield, residue):
"""
Parameters
----------
forcefield : simtk.openmm.app.ForceField
The ForceField object to which residue templates and/or parameters are to be added.
residue : simtk.openmm.app.Topology.Residue
The residue topology for which a template is to be generated.
Returns
-------
success : bool
If the generator is able to successfully parameterize the residue, `True` is returned.
If the generator cannot parameterize the residue, it should return `False` and not modify `forcefield`.
The generator should either register a residue template directly with `forcefield.registerResidueTemplate(template)`
or it should call `forcefield.loadFile(file)` to load residue definitions from an ffxml file.
It can also use the `ForceField` programmatic API to add additional atom types (via `forcefield.registerAtomType(parameters)`)
or additional parameters.
"""
The :code:`ForceField` object will be modified by the residue template generator as residues without previously
defined templates are encountered. Because these templates are added to `ForceField` as new residue
types are encountered, subsequent residues will be parameterized using the same residue templates without
calling the :code:`generator` again.
......@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'agogo'
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
......
......@@ -154,9 +154,9 @@ OpenMM is based on a layered architecture, as shown in the following diagram:
.. figure:: ../images/ArchitectureLayers.jpg
:align: center
:width: 100%
:autonumber:`Figure,OpenMM architecture`: OpenMM architecture
At the highest level is the OpenMM public API. This is the API developers
program against when using OpenMM within their own applications. It is designed
to be simple, easy to understand, and completely platform independent. This is
......@@ -240,7 +240,7 @@ simulation might look like:
HarmonicAngleForce* angles = new HarmonicAngleForce();
system.addForce(angles);
for (int i = 0; i < numAngles; ++i)
angles->addAngle(angle[i].particle1, angle[i].particle2,
angles->addAngle(angle[i].particle1, angle[i].particle2,
angle[i].particle3, angle[i].angle, angle[i].k);
// ...create and initialize other force field terms in the same way
LangevinIntegrator integrator(temperature, friction, stepSize);
......@@ -506,7 +506,7 @@ Mac and Linux
On Mac and Linux machines, type the following two lines:
::
cd build_openmm
ccmake -i <path to OpenMM src directory>
......@@ -623,7 +623,7 @@ If you are installing to a system area, such as /usr/local/openmm/, you will
need to type:
::
sudo make install
sudo make install
Step 5: Install the Python API
******************************
......@@ -646,7 +646,7 @@ If you are installing into the system Python, such as /usr/bin/python, you will
need to type:
::
sudo make PythonInstall
sudo make PythonInstall
.. _test-your-build:
......@@ -668,7 +668,7 @@ Mac and Linux
Type:
::
make test
You should see a series of test results like this:
......@@ -688,13 +688,70 @@ some tests are stochastic, and therefore are expected to fail a small fraction
of the time. These tests will say so in the error message:
::
./TestReferenceLangevinIntegrator
./TestReferenceLangevinIntegrator
exception: Assertion failure at TestReferenceLangevinIntegrator.cpp:129. Expected 9.97741,
found 10.7884 (This test is stochastic and may occasionally fail)
Congratulations! You successfully have built and installed OpenMM from source.
Building the Documentation (Optional)
*************************************
The documentation that you're currently reading, as well as the developer guide and API
documentation can be built through CMake by setting the OpenMM option :code:`OPENMM_GENERATE_API_DOCS=ON`.
User Guide and Developer Guide
==============================
Generating the user guide and developer guide requires the following dependencies
* Sphinx (http://sphinx-doc.org/)
* sphinxcontrib-bibtex (https://pypi.python.org/pypi/sphinxcontrib-bibtex)
These dependencies may not be available in your system package manager, but should
be installable through Python's ``pip`` package manager. ::
pip install sphinx sphinxcontrib-bibtex
The developer and user guides can be built either as HTML or a PDFs. Building the
PDF version will also require a functional LaTeX installation.
To build the HTML version of the documentation, type: ::
make sphinxhtml
To build the PDF version of the documentation, type: ::
make sphinxpdf
Python and C++ API Documentation
================================
The following dependencies are required to build the Python and C++ API documentation.
* Sphinx (http://sphinx-doc.org/)
* sphinxcontrib-lunrsearch (https://pypi.python.org/pypi/sphinxcontrib-lunrsearch)
* sphinxcontrib-autodoc_doxygen (https://pypi.python.org/pypi/sphinxcontrib-autodoc_doxygen)
These dependencies may not be available in your system package manager, but should
be installable through Python's ``pip`` package manager. ::
pip install sphinx sphinxcontrib-lunrsearch sphinxcontrib-autodoc_doxygen
To build the C++ API documentation, type: ::
make C++ApiDocs
To build the Python API documentation, type: ::
make PythonApiDocs
.. _openmm-tutorials:
......@@ -734,12 +791,12 @@ HelloArgon and HelloSodiumChloride also serve as examples of how to do these map
sections below describe the HelloArgon, HelloSodiumChloride, and HelloEthane programs in more detail.
=============== ============== ========== ======== ======================================== ===============
Example Solvent Thermostat Boundary Forces & Constraints API
Example Solvent Thermostat Boundary Forces & Constraints API
=============== ============== ========== ======== ======================================== ===============
Argon Vacuum None None Non-bonded\* C++, C, Fortran
Sodium Chloride Implicit water Langevin None Non-bonded\* C++, C, Fortran
Ethane Vacuum None None Non-bonded\*, stretch, bend, torsion C++
Water Box Explicit water Andersen Periodic Non-bonded\*, stretch, bend, constraints C++
Ethane Vacuum None None Non-bonded\*, stretch, bend, torsion C++
Water Box Explicit water Andersen Periodic Non-bonded\*, stretch, bend, constraints C++
=============== ============== ========== ======== ======================================== ===============
\*van der Waals and Coulomb forces
......@@ -774,7 +831,7 @@ debug binaries.
.. figure:: ../images/VisualStudioSetConfiguration.jpg
:align: center
:width: 100%
:autonumber:`Figure,Visual Studio configuration`: Setting "Solution Configuration" to "Release" mode in Visual Studio
......@@ -789,7 +846,7 @@ previously been compiled.
.. figure:: ../images/VisualStudioLaunch.jpg
:align: center
:width: 100%
:autonumber:`Figure,run in Visual Studio`: Run a program in Visual Studio
You should see a series of lines like the following output on your screen:
......@@ -801,9 +858,9 @@ You should see a series of lines like the following output on your screen:
ATOM 2 AR AR 1 5.000 0.000 0.000 1.00 0.00
ATOM 3 AR AR 1 10.000 0.000 0.000 1.00 0.00
ENDMDL
MODEL 250
ATOM 1 AR AR 1 0.233 0.000 0.000 1.00 0.00
ATOM 2 AR AR 1 5.068 0.000 0.000 1.00 0.00
......@@ -819,7 +876,7 @@ You should see a series of lines like the following output on your screen:
ATOM 2 AR AR 1 5.097 0.000 0.000 1.00 0.00
ATOM 3 AR AR 1 9.717 0.000 0.000 1.00 0.00
ENDMDL
Determining the platform being used
-----------------------------------
......@@ -880,20 +937,20 @@ Type:::
Then run the program by typing:
::
./HelloArgon
./HelloArgon
You should see a series of lines like the following output on your screen:
::
REMARK Using OpenMM platform Reference
MODEL 1
ATOM 1 AR AR 1 0.000 0.000 0.000 1.00 0.00
ATOM 2 AR AR 1 5.000 0.000 0.000 1.00 0.00
ATOM 3 AR AR 1 10.000 0.000 0.000 1.00 0.00
ENDMDL
...
MODEL 250
ATOM 1 AR AR 1 0.233 0.000 0.000 1.00 0.00
ATOM 2 AR AR 1 5.068 0.000 0.000 1.00 0.00
......@@ -967,7 +1024,7 @@ The OpenMM header file *OpenMM.h* instructs the program to include
everything defined by the OpenMM libraries. Include the header file by adding
the following line at the top of your program: ::
#include "OpenMM.h"
Running a program on GPU platforms
......@@ -1002,7 +1059,7 @@ simulation. The main components of the simulation are within the function
// Create a system with nonbonded forces.
OpenMM::System system;
OpenMM::NonbondedForce* nonbond = new OpenMM::NonbondedForce();
OpenMM::NonbondedForce* nonbond = new OpenMM::NonbondedForce();
system.addForce(nonbond);
We then add the three argon atoms to the system. For this system, all the data
......@@ -1014,7 +1071,7 @@ simulation. The main components of the simulation are within the function
// Create three atoms.
std::vector<OpenMM::Vec3> initPosInNm(3);
for (int a = 0; a < 3; ++a)
for (int a = 0; a < 3; ++a)
{
initPosInNm[a] = OpenMM::Vec3(0.5*a,0,0); // location, nm
......@@ -1113,7 +1170,7 @@ simulation. The main components of the simulation are within the function
if (timeInPs >= 10.)
break;
// Advance state many steps at a time, for efficient use of OpenMM.
integrator.step(10); // (use a lot more than this normally)
......@@ -1128,7 +1185,7 @@ to ensure you do catch the exception.
.. code-block:: c
int main()
int main()
{
try {
simulateArgon();
......@@ -1152,12 +1209,12 @@ converts them to Angstroms (10\ :sup:`-10` m) to be compatible with the PDB
format. Again, we emphasize how important it is to track the units being used!
.. code-block:: c
void writePdbFrame(int frameNum, const OpenMM::State& state)
void writePdbFrame(int frameNum, const OpenMM::State& state)
{
// Reference atomic positions in the OpenMM State.
const std::vector<OpenMM::Vec3>& posInNm = state.getPositions();
// Use PDB MODEL cards to number trajectory frames
printf("MODEL %d\n", frameNum); // start of frame
for (int a = 0; a < (int)posInNm.size(); ++a)
......@@ -1238,7 +1295,7 @@ MD code, and will be used to demonstrate how to integrate OpenMM with an
existing MD program.
.. code-block:: c
// -----------------------------------------------------------------
// MODELING AND SIMULATION PARAMETERS
// -----------------------------------------------------------------
......@@ -1246,25 +1303,25 @@ existing MD program.
static const double FrictionInPerPs = 91.; // collisions per picosecond
static const double SolventDielectric = 80.; // typical for water
static const double SoluteDielectric = 2.; // typical for protein
static const double StepSizeInFs = 2; // integration step size (fs)
static const double ReportIntervalInFs = 50; // how often to issue PDB frame (fs)
static const double SimulationTimeInPs = 100; // total simulation time (ps)
// Decide whether to request energy calculations.
static const bool WantEnergy = true;
// -----------------------------------------------------------------
// ATOM AND FORCE FIELD DATA
// -----------------------------------------------------------------
// This is not part of OpenMM; just a struct we can use to collect atom
// parameters for this example. Normally atom parameters would come from the
// force field's parameterization file. We're going to use data in Angstrom and
// Kilocalorie units and show how to safely convert to OpenMM's internal unit
// This is not part of OpenMM; just a struct we can use to collect atom
// parameters for this example. Normally atom parameters would come from the
// force field's parameterization file. We're going to use data in Angstrom and
// Kilocalorie units and show how to safely convert to OpenMM's internal unit
// system which uses nanometers and kilojoules.
static struct MyAtomInfo {
const char* pdb;
static struct MyAtomInfo {
const char* pdb;
double mass, charge, vdwRadiusInAng, vdwEnergyInKcal,
gbsaRadiusInAng, gbsaScaleFactor;
double initPosInAng[3];
......@@ -1279,7 +1336,7 @@ existing MD program.
{" CL ", 35.45, -1, 2.4700, 0.1000, 1.735, 0.8, 0, 0, 10},
{""} // end of list
};
Interface routines
==================
......@@ -1325,34 +1382,34 @@ to change the build environment.
double frictionInPs,
double solventDielectric,
double soluteDielectric,
double stepSizeInFs,
double stepSizeInFs,
std::string& platformName);
static void myStepWithOpenMM(MyOpenMMData*, int numSteps);
static void myGetOpenMMState(MyOpenMMData*,
bool wantEnergy,
double& time,
double& energy,
double& energy,
MyAtomInfo atoms[]);
static void myTerminateOpenMM(MyOpenMMData*);
// -----------------------------------------------------------------
// MAIN PROGRAM
// -----------------------------------------------------------------
int main() {
const int NumReports = (int)(SimulationTimeInPs*1000 / ReportIntervalInFs + 0.5);
const int NumSilentSteps = (int)(ReportIntervalInFs / StepSizeInFs + 0.5);
// ALWAYS enclose all OpenMM calls with a try/catch block to make sure that
// usage and runtime errors are caught and reported.
try {
double time, energy;
std::string platformName;
// Set up OpenMM data structures; returns OpenMM Platform name.
MyOpenMMData* omm = myInitializeOpenMM(atoms, Temperature, FrictionInPerPs,
SolventDielectric, SoluteDielectric, StepSizeInFs, platformName);
// Run the simulation:
// (1) Write the first line of the PDB file and the initial configuration.
// (2) Run silently entirely within OpenMM between reporting intervals.
......@@ -1360,26 +1417,26 @@ to change the build environment.
printf("REMARK Using OpenMM platform %s\n", platformName.c_str());
myGetOpenMMState(omm, WantEnergy, time, energy, atoms);
myWritePDBFrame(1, time, energy, atoms);
for (int frame=2; frame <= NumReports; ++frame) {
myStepWithOpenMM(omm, NumSilentSteps);
myGetOpenMMState(omm, WantEnergy, time, energy, atoms);
myWritePDBFrame(frame, time, energy, atoms);
}
}
// Clean up OpenMM data structures.
myTerminateOpenMM(omm);
return 0; // Normal return from main.
}
// Catch and report usage and runtime errors detected by OpenMM and fail.
catch(const std::exception& e) {
printf("EXCEPTION: %s\n", e.what());
return 1;
}
}
We will examine the implementation of each of the four interface routines and
the opaque data structure (handle) in the sections below.
......@@ -1461,7 +1518,7 @@ there would be no change in the main program using the handle.
OpenMM::Context* context;
OpenMM::Integrator* integrator;
};
In addition to establishing pointers to the required three OpenMM objects,
:code:`MyOpenMMData` has a constructor :code:`MyOpenMMData()` that sets
the pointers for the three OpenMM objects to zero and a destructor
......@@ -1480,16 +1537,16 @@ OpenCL, Reference) was used.
.. code-block:: c
static MyOpenMMData*
static MyOpenMMData*
myInitializeOpenMM( const MyAtomInfo atoms[],
double temperature,
double frictionInPs,
double solventDielectric,
double soluteDielectric,
double stepSizeInFs,
std::string& platformName)
double stepSizeInFs,
std::string& platformName)
This initialization routine is very similar to the HelloArgon example program,
except that objects are created and put in the handle. For instance, just as in
the HelloArgon program, the first step is to load the OpenMM plug-ins, so that
......@@ -1498,14 +1555,14 @@ a System is created **and** assigned to the handle :code:`omm`\ .
Similarly, forces are added to the System which is already in the handle.
.. code-block:: c
// Load all available OpenMM plugins from their default location.
OpenMM::Platform::loadPluginsFromDirectory
(OpenMM::Platform::getDefaultPluginsDirectory());
// Allocate space to hold OpenMM objects while we're using them.
MyOpenMMData* omm = new MyOpenMMData();
// Create a System and Force objects within the System. Retain a reference
// to each force object so we can fill in the forces. Note: the OpenMM
// System takes ownership of the force objects;don't delete them yourself.
......@@ -1514,12 +1571,12 @@ Similarly, forces are added to the System which is already in the handle.
OpenMM::GBSAOBCForce* gbsa = new OpenMM::GBSAOBCForce();
omm->system->addForce(nonbond);
omm->system->addForce(gbsa);
// Specify dielectrics for GBSA implicit solvation.
gbsa->setSolventDielectric(solventDielectric);
gbsa->setSoluteDielectric(soluteDielectric);
In the next step, atoms are added to the System within the handle, with
information about each atom coming from the data structure that was passed into
the initialization function from the existing MD code. As shown in the
......@@ -1529,7 +1586,7 @@ atoms. For those unfamiliar with the C++ Standard Template Library, the
the given argument to the end of a C++ vector container.
.. code-block:: c
// Specify the atoms and their properties:
// (1) System needs to know the masses.
// (2) NonbondedForce needs charges,van der Waals properties(in MD units!).
......@@ -1538,24 +1595,24 @@ the given argument to the end of a C++ “vector” container.
std::vector<Vec3> initialPosInNm;
for (int n=0; *atoms[n].pdb; ++n) {
const MyAtomInfo& atom = atoms[n];
omm->system->addParticle(atom.mass);
nonbond->addParticle(atom.charge,
atom.vdwRadiusInAng * OpenMM::NmPerAngstrom
atom.vdwRadiusInAng * OpenMM::NmPerAngstrom
* OpenMM::SigmaPerVdwRadius,
atom.vdwEnergyInKcal * OpenMM::KJPerKcal);
gbsa->addParticle(atom.charge,
gbsa->addParticle(atom.charge,
atom.gbsaRadiusInAng * OpenMM::NmPerAngstrom,
atom.gbsaScaleFactor);
// Convert the initial position to nm and append to the array.
const Vec3 posInNm(atom.initPosInAng[0] * OpenMM::NmPerAngstrom,
atom.initPosInAng[1] * OpenMM::NmPerAngstrom,
atom.initPosInAng[2] * OpenMM::NmPerAngstrom);
initialPosInNm.push_back(posInNm);
**Units:** Here we emphasize the need to pay special attention to the
units. As mentioned earlier, the existing MD code in this example uses units
......@@ -1575,21 +1632,21 @@ then gets the platform that will be used to run the simulation and returns that,
along with the handle :code:`omm`\ , back to the calling function.
.. code-block:: c
// Choose an Integrator for advancing time, and a Context connecting the
// System with the Integrator for simulation. Let the Context choose the
// best available Platform. Initialize the configuration from the default
// positions we collected above. Initial velocities will be zero but could
// have been set here.
omm->integrator = new OpenMM::LangevinIntegrator(temperature,
frictionInPs,
omm->integrator = new OpenMM::LangevinIntegrator(temperature,
frictionInPs,
stepSizeInFs * OpenMM::PsPerFs);
omm->context = new OpenMM::Context(*omm->system, *omm->integrator);
omm->context->setPositions(initialPosInNm);
platformName = omm->context->getPlatform().getName();
return omm;
myGetOpenMMState
----------------
......@@ -1601,7 +1658,7 @@ use them without modification.
.. code-block:: c
static void
myGetOpenMMState(MyOpenMMData* omm, bool wantEnergy,
myGetOpenMMState(MyOpenMMData* omm, bool wantEnergy,
double& timeInPs, double& energyInKcal, MyAtomInfo atoms[])
Again, this is another interface routine in which you need to be very careful of
......@@ -1617,19 +1674,19 @@ the existing MD code.
infoMask += OpenMM::State::Energy; // for pot. energy (more expensive)
}
// Forces are also available (and cheap).
const OpenMM::State state = omm->context->getState(infoMask);
timeInPs = state.getTime(); // OpenMM time is in ps already
// Copy OpenMM positions into atoms array and change units from nm to Angstroms.
const std::vector<Vec3>& positionsInNm = state.getPositions();
for (int i=0; i < (int)positionsInNm.size(); ++i)
for (int j=0; j < 3; ++j)
atoms[i].posInAng[j] = positionsInNm[i][j] * OpenMM::AngstromsPerNm;
// If energy has been requested, obtain it and convert from kJ to kcal.
energyInKcal = 0;
if (wantEnergy)
if (wantEnergy)
energyInKcal = (state.getPotentialEnergy() + state.getKineticEnergy())
* OpenMM::KcalPerKJ;
......@@ -1641,8 +1698,8 @@ Integrator, and then sets the number of steps for the Integrator to take. It
does not return any values.
.. code-block:: c
static void
static void
myStepWithOpenMM(MyOpenMMData* omm, int numSteps) {
omm->integrator->step(numSteps);
}
......@@ -1654,12 +1711,12 @@ The :code:`myTerminateOpenMM` routine takes the handle and deletes all the
components, e.g., the Context and System, cleaning up the heap space.
.. code-block:: c
static void
static void
myTerminateOpenMM(MyOpenMMData* omm) {
delete omm;
}
HelloEthane Program
*******************
......@@ -1694,7 +1751,7 @@ routine, we also set up the bonds. If constraints are being used, then we tell
the System about the constrainable bonds:
.. code-block:: c
std::vector< std::pair<int,int> > bondPairs;
for (int i=0; bonds[i].type != EndOfList; ++i) {
const int* atom = bonds[i].atoms;
......@@ -1703,7 +1760,7 @@ the System about the constrainable bonds:
if (UseConstraints && bond.canConstrain) {
system.addConstraint(atom[0], atom[1],
bond.nominalLengthInAngstroms * OpenMM::NmPerAngstrom);
}
}
Otherwise, we need to give the HarmonicBondForce the bond stretch parameters.
......@@ -1716,11 +1773,11 @@ of 2 must be introduced when setting the bond stretch parameters in an OpenMM
system using data from an AMBER system.
.. code-block:: c
bondStretch.addBond(atom[0], atom[1], bond.nominalLengthInAngstroms * OpenMM::NmPerAngstrom,
bond.stiffnessInKcalPerAngstrom2 * 2 * OpenMM::KJPerKcal *
OpenMM::AngstromsPerNm * OpenMM::AngstromsPerNm);
**Non-bond exclusions:** Next, we deal with non-bond exclusions. These are
used for pairs of atoms that appear close to one another in the network of bonds
......@@ -1729,9 +1786,9 @@ are reduced in magnitude. First, we create a list of bonds to generate the non-
bond exclusions:
.. code-block:: c
bondPairs.push_back(std::make_pair(atom[0], atom[1]));
OpenMM’s non-bonded force provides a convenient routine for creating the common
exceptions. These are: (1) for atoms connected by one bond (1-2) or connected by
just one additional bond (1-3), Coulomb and van der Waals terms do not apply;
......@@ -1741,28 +1798,28 @@ general, you may introduce additional exceptions, but the standard ones suffice
here and in many other circumstances.
.. code-block:: c
// Exclude 1-2, 1-3 bonded atoms from nonbonded forces, and scale down 1-4 bonded atoms.
nonbond.createExceptionsFromBonds(bondPairs, Coulomb14Scale, LennardJones14Scale);
// Create the 1-2-3 bond angle harmonic terms.
for (int i=0; angles[i].type != EndOfList; ++i) {
const int* atom = angles[i].atoms;
const AngleType& angle = angleType[angles[i].type];
// See note under bond stretch above regarding the factor of 2 here.
bondBend.addAngle(atom[0],atom[1],atom[2],
angle.nominalAngleInDegrees * OpenMM::RadiansPerDegree,
angle.stiffnessInKcalPerRadian2 * 2 *
angle.stiffnessInKcalPerRadian2 * 2 *
OpenMM::KJPerKcal);
}
// Create the 1-2-3-4 bond torsion (dihedral) terms.
for (int i=0; torsions[i].type != EndOfList; ++i) {
const int* atom = torsions[i].atoms;
const TorsionType& torsion = torsionType[torsions[i].type];
bondTorsion.addTorsion(atom[0],atom[1],atom[2],atom[3],
torsion.periodicity,
bondTorsion.addTorsion(atom[0],atom[1],atom[2],atom[3],
torsion.periodicity,
torsion.phaseInDegrees * OpenMM::RadiansPerDegree,
torsion.amplitudeInKcal * OpenMM::KJPerKcal);
}
......@@ -2118,7 +2175,7 @@ OpenMM_DoubleArray
.. code-block:: c
OpenMM_DoubleArray*
OpenMM_DoubleArray*
OpenMM_DoubleArray_create(int size);
void OpenMM_DoubleArray_destroy(OpenMM_DoubleArray*);
int OpenMM_DoubleArray_getSize(const OpenMM_DoubleArray*);
......@@ -2132,7 +2189,7 @@ OpenMM_StringArray
.. code-block:: c
OpenMM_StringArray*
OpenMM_StringArray*
OpenMM_StringArray_create(int size);
void OpenMM_StringArray_destroy(OpenMM_StringArray*);
int OpenMM_StringArray_getSize(const OpenMM_StringArray*);
......@@ -2146,14 +2203,14 @@ OpenMM_Vec3Array
.. code-block:: c
OpenMM_Vec3Array*
OpenMM_Vec3Array*
OpenMM_Vec3Array_create(int size);
void OpenMM_Vec3Array_destroy(OpenMM_Vec3Array*);
int OpenMM_Vec3Array_getSize(const OpenMM_Vec3Array*);
void OpenMM_Vec3Array_resize(OpenMM_Vec3Array*, int size);
void OpenMM_Vec3Array_append(OpenMM_Vec3Array*, const OpenMM_Vec3 vec);
void OpenMM_Vec3Array_set(OpenMM_Vec3Array*, int index, const OpenMM_Vec3 vec);
const OpenMM_Vec3*
const OpenMM_Vec3*
OpenMM_Vec3Array_get(const OpenMM_Vec3Array*, int index);
OpenMM_BondArray
......@@ -2165,14 +2222,14 @@ its functional return.
.. code-block:: c
OpenMM_BondArray*
OpenMM_BondArray*
OpenMM_BondArray_create(int size);
void OpenMM_BondArray_destroy(OpenMM_BondArray*);
int OpenMM_BondArray_getSize(const OpenMM_BondArray*);
void OpenMM_BondArray_resize(OpenMM_BondArray*, int size);
void OpenMM_BondArray_append(OpenMM_BondArray*, int particle1, int particle2);
void OpenMM_BondArray_set(OpenMM_BondArray*, int index, int particle1, int particle2);
void OpenMM_BondArray_get(const OpenMM_BondArray*, int index,
void OpenMM_BondArray_get(const OpenMM_BondArray*, int index,
int* particle1, int* particle2);
OpenMM_ParameterArray
......@@ -2551,7 +2608,7 @@ Note that if you are using the system Python (as opposed to a locally installed
version), you may need to use the :code:`sudo` command when running
:code:`python setup.py install`\ .
::
export OPENMM_INCLUDE_PATH=/usr/local/openmm/include
export OPENMM_LIB_PATH=/usr/local/openmm/lib
python setup.py build
......@@ -2574,7 +2631,7 @@ notable differences:
::
myContext.getState(getEnergy=True, getForce=False, )
#. Wherever the C++ API uses references to return multiple values from a method,
the Python API returns a tuple. For example, in C++ you would query a
HarmonicBondForce for a bonds parameters as follows:
......@@ -2583,7 +2640,7 @@ notable differences:
int particle1, particle2;
double length, k;
f.getBondParameters(i, particle1, particle2, length, k);
In Python, the equivalent code is:
::
......@@ -2625,7 +2682,7 @@ Creating and using OpenMM objects is then done exactly as in C++:
Note that when setting the cutoff distance, we explicitly specify that it is in
nanometers. We could just as easily specify it in different units:
::
nb.setCutoffDistance(12*unit.angstrom)
The use of units in OpenMM is discussed in the next section.
......@@ -2754,7 +2811,7 @@ dimension. For example, dividing a distance by a time results in a velocity.
m = 0.36 * kilogram; # mass
F = m * a; # force in kg*m/s**2::
Multiplication or division of two Units results in a composite Unit.
::
......@@ -3128,7 +3185,7 @@ errors for that system. Finally, the median of those values for all test
systems was computed to give the value shown in the table.
==================================== ======================== ==================== =================== =====================
Force OpenCL (single) OpenCL (double) CUDA (single) CUDA (double)
Force OpenCL (single) OpenCL (double) CUDA (single) CUDA (double)
==================================== ======================== ==================== =================== =====================
Total Force 2.53·10\ :sup:`-6` 1.44·10\ :sup:`-7` 2.56·10\ :sup:`-6` 8.78·10\ :sup:`-8`
HarmonicBondForce 2.88·10\ :sup:`-6` 1.57·10\ :sup:`-13` 2.88·10\ :sup:`-6` 1.57·10\ :sup:`-13`
......@@ -3161,7 +3218,7 @@ precision that was used for calculations (see Chapter :ref:`platform-specific-pr
.. figure:: ../images/EnergyDrift.png
:align: center
:autonumber:`Figure,energy drift`: Total energy versus time for simulations run in three different
precision modes.
......@@ -3262,21 +3319,21 @@ All rotation axis types are supported: ‘Z-then-X’, ‘Bisector’, ‘Z-Bise
================================= ================================== ======================================================================================================================================================================================
TINKER Force OpenMM Force Option/Note
TINKER Force OpenMM Force Option/Note
================================= ================================== ======================================================================================================================================================================================
ebond1 (bondterm) AmoebaBondForce bndtyp='HARMONIC' supported, 'MORSE' not implemented
Eangle71 (angleterm) AmoebaAngleForce angtyp='HARMONIC' and 'IN-PLANE' supported; 'LINEAR' and 'FOURIER' not implemented
etors1a (torsionterm) PeriodicTorsionForce All options implemented; smoothing version(etors1b) not supported
etortor1 (tortorterm) AmoebaTorsionTorsionForce All options implemented
eopbend1 (opbendterm) AmoebaOutOfPlaneBendForce opbtyp = 'ALLINGER' implemented; 'W-D-C' not implemented
epitors1 (pitorsterm) AmoebaPiTorsionForce All options implemented
estrbnd1 (strbndterm) AmoebaStretchBendForce All options implemented
ehal1a (vdwterm) AmoebaVdwForce ehal1b(LIGHTS) not supported
empole1a (mpoleterm) AmoebaMultipoleForce poltyp = 'MUTUAL', 'DIRECT' supported
empole1c (mpoleterm) PME AmoebaMultipoleForce poltyp = 'MUTUAL', 'DIRECT' supported; boundary= 'VACUUM' unsupported
ebond1 (bondterm) AmoebaBondForce bndtyp='HARMONIC' supported, 'MORSE' not implemented
Eangle71 (angleterm) AmoebaAngleForce angtyp='HARMONIC' and 'IN-PLANE' supported; 'LINEAR' and 'FOURIER' not implemented
etors1a (torsionterm) PeriodicTorsionForce All options implemented; smoothing version(etors1b) not supported
etortor1 (tortorterm) AmoebaTorsionTorsionForce All options implemented
eopbend1 (opbendterm) AmoebaOutOfPlaneBendForce opbtyp = 'ALLINGER' implemented; 'W-D-C' not implemented
epitors1 (pitorsterm) AmoebaPiTorsionForce All options implemented
estrbnd1 (strbndterm) AmoebaStretchBendForce All options implemented
ehal1a (vdwterm) AmoebaVdwForce ehal1b(LIGHTS) not supported
empole1a (mpoleterm) AmoebaMultipoleForce poltyp = 'MUTUAL', 'DIRECT' supported
empole1c (mpoleterm) PME AmoebaMultipoleForce poltyp = 'MUTUAL', 'DIRECT' supported; boundary= 'VACUUM' unsupported
esolv1 (solvateterm) | AmoebaWcaDispersionForce, Only born-radius=grycuk and solvate=GK supported; unsupported solvate settings:
| AmoebaGeneralizedKirkwoodForce ASP, SASA, ONION, pb, 'GB-HPMF’, 'Gk-HPMF; SASA computation is based on ACE approximation
eurey1 (ureyterm) HarmonicBondForce All options implemented
eurey1 (ureyterm) HarmonicBondForce All options implemented
================================= ================================== ======================================================================================================================================================================================
:autonumber:`Table,mapping from TINKER`\ : Mapping between TINKER and OpenMM AMOEBA forces
......@@ -3545,7 +3602,7 @@ term. This yields much closer agreement between OpenMM and TINKER,
demonstrating that the difference comes entirely from that one term.
========================= ========================== ===================
Solvent Model single double
Solvent Model single double
========================= ========================== ===================
Implicit 1.04·10\ :sup:`-2` 1.04·10\ :sup:`-2`
Implicit (no cavity term) 9.23·10\ :sup:`-6` 1.17·10\ :sup:`-6`
......@@ -3655,4 +3712,3 @@ The equations of motion can be integrated with two different methods:
temperature, while using a much lower temperature for their relative internal
motion. In practice, this produces dipole moments very close to those from the
SCF solution while being much faster to compute.
......@@ -389,6 +389,17 @@
type = {Journal Article}
}
@article{Simmonett2015
author = {Simmonett, Andrew C. and Pickard, Frank C. and Shao, Yihan and Cheatham, Thomas E. and Brooks, Bernard R.},
title = {Efficient treatment of induced dipoles},
journal = {Journal of Chemical Physics},
year = {2015},
volume = {143},
number = {7},
pages = {074115},
type = {Journal Article}
}
@article{Sindhikara2009,
author = {Sindhikara, Daniel J. and Kim, Seonah and Voter,
Arthur F. and Roitberg, Adrian E.},
......
......@@ -36,22 +36,18 @@ def runOneTest(testName, options):
if amoeba:
constraints = None
epsilon = float(options.epsilon)
if epsilon == 0:
polarization = 'direct'
else:
polarization = 'mutual'
if explicit:
ff = app.ForceField('amoeba2009.xml')
pdb = app.PDBFile('5dfr_solv-cube_equil.pdb')
cutoff = 0.7*unit.nanometers
vdwCutoff = 0.9*unit.nanometers
system = ff.createSystem(pdb.topology, nonbondedMethod=app.PME, nonbondedCutoff=cutoff, vdwCutoff=vdwCutoff, constraints=constraints, ewaldErrorTolerance=0.00075, mutualInducedTargetEpsilon=epsilon, polarization=polarization)
system = ff.createSystem(pdb.topology, nonbondedMethod=app.PME, nonbondedCutoff=cutoff, vdwCutoff=vdwCutoff, constraints=constraints, ewaldErrorTolerance=0.00075, mutualInducedTargetEpsilon=epsilon, polarization=options.polarization)
else:
ff = app.ForceField('amoeba2009.xml', 'amoeba2009_gk.xml')
pdb = app.PDBFile('5dfr_minimized.pdb')
cutoff = 2.0*unit.nanometers
vdwCutoff = 1.2*unit.nanometers
system = ff.createSystem(pdb.topology, nonbondedMethod=app.NoCutoff, constraints=constraints, mutualInducedTargetEpsilon=epsilon, polarization=polarization)
system = ff.createSystem(pdb.topology, nonbondedMethod=app.NoCutoff, constraints=constraints, mutualInducedTargetEpsilon=epsilon, polarization=options.polarization)
for f in system.getForces():
if isinstance(f, mm.AmoebaMultipoleForce) or isinstance(f, mm.AmoebaVdwForce) or isinstance(f, mm.AmoebaGeneralizedKirkwoodForce) or isinstance(f, mm.AmoebaWcaDispersionForce):
f.setForceGroup(1)
......@@ -127,7 +123,8 @@ parser.add_option('--platform', dest='platform', choices=platformNames, help='na
parser.add_option('--test', dest='test', choices=('gbsa', 'rf', 'pme', 'amoebagk', 'amoebapme'), help='the test to perform: gbsa, rf, pme, amoebagk, or amoebapme [default: all]')
parser.add_option('--pme-cutoff', default='0.9', dest='cutoff', type='float', help='direct space cutoff for PME in nm [default: 0.9]')
parser.add_option('--seconds', default='60', dest='seconds', type='float', help='target simulation length in seconds [default: 60]')
parser.add_option('--mutual-epsilon', default='1e-4', dest='epsilon', type='float', help='mutual induced epsilon for AMOEBA [default: 1e-4]')
parser.add_option('--polarization', default='mutual', dest='polarization', choices=('direct', 'extrapolated', 'mutual'), help='the polarization method for AMOEBA: direct, extrapolated, or mutual [default: mutual]')
parser.add_option('--mutual-epsilon', default='1e-5', dest='epsilon', type='float', help='mutual induced epsilon for AMOEBA [default: 1e-5]')
parser.add_option('--heavy-hydrogens', action='store_true', default=False, dest='heavy', help='repartition mass to allow a larger time step')
parser.add_option('--device', default=None, dest='device', help='device index for CUDA or OpenCL')
parser.add_option('--precision', default='single', dest='precision', choices=('single', 'mixed', 'double'), help='precision mode for CUDA or OpenCL: single, mixed, or double [default: single]')
......
......@@ -40,16 +40,16 @@ namespace OpenMM {
/**
* A Kernel encapsulates a particular implementation of a calculation that can be performed on the data
* in a Context. Kernel objects are created by Platforms:
*
*
* <pre>
* Kernel kernel = platform.createKernel(kernelName);
* </pre>
*
*
* The Kernel class itself does not specify any details of what calculation is to be performed or the API
* for calling it. Instead, subclasses of KernelImpl will define APIs which are appropriate to particular
* calculations. To execute a Kernel, you therefore request its implementation object and cast it to the
* correct type:
*
*
* <pre>
* dynamic_cast<AddStreamsImpl&>(kernel.getImpl()).execute(stream1, stream2);
* </pre>
......@@ -61,8 +61,8 @@ public:
Kernel(const Kernel& copy);
/**
* Create a Kernel that wraps a KernelImpl.
*
* @param name the name of the kernel to create
*
* @param KernelImpl the KernelImpl to wrap
*/
Kernel(KernelImpl* impl);
~Kernel();
......
......@@ -53,7 +53,7 @@ class KernelFactory;
* To get a Platform object, call
*
* <pre>
* Platform& platform Platform::findPlatform(kernelNames);
* Platform& platform = Platform::findPlatform(kernelNames);
* </pre>
*
* passing in the names of all kernels that will be required for the calculation you plan to perform. It
......@@ -78,6 +78,9 @@ public:
/**
* Get whether this Platform supports double precision arithmetic. If this returns false, the platform
* is permitted to represent double precision values internally as single precision.
*
* @deprecated This method is not well defined, and is too simplistic to describe the actual behavior of
* some Platforms, such as ones that offer multiple precision modes. It will be removed in a future release.
*/
virtual bool supportsDoublePrecision() const = 0;
/**
......
......@@ -369,8 +369,8 @@ public:
* Get the donor and acceptor in a pair whose interaction should be excluded.
*
* @param index the index of the exclusion for which to get donor and acceptor indices
* @param[out] particle1 the index of the donor
* @param[out] particle2 the index of the acceptor
* @param[out] donor the index of the donor
* @param[out] acceptor the index of the acceptor
*/
void getExclusionParticles(int index, int& donor, int& acceptor) const;
/**
......
......@@ -40,10 +40,10 @@ namespace OpenMM {
/**
* A TabulatedFunction uses a set of tabulated values to define a mathematical function.
* It can be used by various custom forces.
*
*
* TabulatedFunction is an abstract class with concrete subclasses for more specific
* types of functions. There are subclasses for:
*
*
* <ul>
* <li>1, 2, and 3 dimensional functions. The dimensionality of a function means
* the number of input arguments it takes.</li>
......@@ -69,7 +69,7 @@ class OPENMM_EXPORT Continuous1DFunction : public TabulatedFunction {
public:
/**
* Create a Continuous1DFunction f(x) based on a set of tabulated values.
*
*
* @param values the tabulated values of the function f(x) at uniformly spaced values of x between min
* and max. A natural cubic spline is used to interpolate between the tabulated values.
* The function is assumed to be zero for x &lt; min or x &gt; max.
......@@ -80,11 +80,11 @@ public:
/**
* Get the parameters for the tabulated function.
*
* @param values the tabulated values of the function f(x) at uniformly spaced values of x between min
* and max. A natural cubic spline is used to interpolate between the tabulated values.
* The function is assumed to be zero for x &lt; min or x &gt; max.
* @param min the value of x corresponding to the first element of values
* @param max the value of x corresponding to the last element of values
* @param[out] values the tabulated values of the function f(x) at uniformly spaced values of x between min
* and max. A natural cubic spline is used to interpolate between the tabulated values.
* The function is assumed to be zero for x &lt; min or x &gt; max.
* @param[out] min the value of x corresponding to the first element of values
* @param[out] max the value of x corresponding to the last element of values
*/
void getFunctionParameters(std::vector<double>& values, double& min, double& max) const;
/**
......@@ -113,7 +113,7 @@ class OPENMM_EXPORT Continuous2DFunction : public TabulatedFunction {
public:
/**
* Create a Continuous2DFunction f(x,y) based on a set of tabulated values.
*
*
* @param values the tabulated values of the function f(x,y) at xsize uniformly spaced values of x between xmin
* and xmax, and ysize values of y between ymin and ymax. A natural cubic spline is used to interpolate between the tabulated values.
* The function is assumed to be zero when x or y is outside its specified range. The values should be ordered so that
......@@ -129,16 +129,16 @@ public:
/**
* Get the parameters for the tabulated function.
*
* @param values the tabulated values of the function f(x,y) at xsize uniformly spaced values of x between xmin
* and xmax, and ysize values of y between ymin and ymax. A natural cubic spline is used to interpolate between the tabulated values.
* The function is assumed to be zero when x or y is outside its specified range. The values should be ordered so that
* values[i+xsize*j] = f(x_i,y_j), where x_i is the i'th uniformly spaced value of x. This must be of length xsize*ysize.
* @param xsize the number of table elements along the x direction
* @param ysize the number of table elements along the y direction
* @param xmin the value of x corresponding to the first element of values
* @param xmax the value of x corresponding to the last element of values
* @param ymin the value of y corresponding to the first element of values
* @param ymax the value of y corresponding to the last element of values
* @param[out] values the tabulated values of the function f(x,y) at xsize uniformly spaced values of x between xmin
* and xmax, and ysize values of y between ymin and ymax. A natural cubic spline is used to interpolate between the tabulated values.
* The function is assumed to be zero when x or y is outside its specified range. The values should be ordered so that
* values[i+xsize*j] = f(x_i,y_j), where x_i is the i'th uniformly spaced value of x. This must be of length xsize*ysize.
* @param[out] xsize the number of table elements along the x direction
* @param[out] ysize the number of table elements along the y direction
* @param[out] xmin the value of x corresponding to the first element of values
* @param[out] xmax the value of x corresponding to the last element of values
* @param[out] ymin the value of y corresponding to the first element of values
* @param[out] ymax the value of y corresponding to the last element of values
*/
void getFunctionParameters(int& xsize, int& ysize, std::vector<double>& values, double& xmin, double& xmax, double& ymin, double& ymax) const;
/**
......@@ -173,7 +173,7 @@ class OPENMM_EXPORT Continuous3DFunction : public TabulatedFunction {
public:
/**
* Create a Continuous3DFunction f(x,y,z) based on a set of tabulated values.
*
*
* @param values the tabulated values of the function f(x,y,z) at xsize uniformly spaced values of x between xmin
* and xmax, ysize values of y between ymin and ymax, and zsize values of z between zmin and zmax.
* A natural cubic spline is used to interpolate between the tabulated values. The function is
......@@ -194,21 +194,21 @@ public:
/**
* Get the parameters for the tabulated function.
*
* @param values the tabulated values of the function f(x,y,z) at xsize uniformly spaced values of x between xmin
* and xmax, ysize values of y between ymin and ymax, and zsize values of z between zmin and zmax.
* A natural cubic spline is used to interpolate between the tabulated values. The function is
* assumed to be zero when x, y, or z is outside its specified range. The values should be ordered so
* that values[i+xsize*j+xsize*ysize*k] = f(x_i,y_j,z_k), where x_i is the i'th uniformly spaced value of x.
* This must be of length xsize*ysize*zsize.
* @param xsize the number of table elements along the x direction
* @param ysize the number of table elements along the y direction
* @param ysize the number of table elements along the z direction
* @param xmin the value of x corresponding to the first element of values
* @param xmax the value of x corresponding to the last element of values
* @param ymin the value of y corresponding to the first element of values
* @param ymax the value of y corresponding to the last element of values
* @param zmin the value of z corresponding to the first element of values
* @param zmax the value of z corresponding to the last element of values
* @param[out] values the tabulated values of the function f(x,y,z) at xsize uniformly spaced values of x between xmin
* and xmax, ysize values of y between ymin and ymax, and zsize values of z between zmin and zmax.
* A natural cubic spline is used to interpolate between the tabulated values. The function is
* assumed to be zero when x, y, or z is outside its specified range. The values should be ordered so
* that values[i+xsize*j+xsize*ysize*k] = f(x_i,y_j,z_k), where x_i is the i'th uniformly spaced value of x.
* This must be of length xsize*ysize*zsize.
* @param[out] xsize the number of table elements along the x direction
* @param[out] ysize the number of table elements along the y direction
* @param[out] zsize the number of table elements along the z direction
* @param[out] xmin the value of x corresponding to the first element of values
* @param[out] xmax the value of x corresponding to the last element of values
* @param[out] ymin the value of y corresponding to the first element of values
* @param[out] ymax the value of y corresponding to the last element of values
* @param[out] zmin the value of z corresponding to the first element of values
* @param[out] zmax the value of z corresponding to the last element of values
*/
void getFunctionParameters(int& xsize, int& ysize, int& zsize, std::vector<double>& values, double& xmin, double& xmax, double& ymin, double& ymax, double& zmin, double& zmax) const;
/**
......@@ -222,7 +222,7 @@ public:
* This must be of length xsize*ysize*zsize.
* @param xsize the number of table elements along the x direction
* @param ysize the number of table elements along the y direction
* @param ysize the number of table elements along the z direction
* @param zsize the number of table elements along the z direction
* @param xmin the value of x corresponding to the first element of values
* @param xmax the value of x corresponding to the last element of values
* @param ymin the value of y corresponding to the first element of values
......@@ -250,14 +250,14 @@ class OPENMM_EXPORT Discrete1DFunction : public TabulatedFunction {
public:
/**
* Create a Discrete1DFunction f(x) based on a set of tabulated values.
*
*
* @param values the tabulated values of the function f(x)
*/
Discrete1DFunction(const std::vector<double>& values);
/**
* Get the parameters for the tabulated function.
*
* @param values the tabulated values of the function f(x)
* @param[out] values the tabulated values of the function f(x)
*/
void getFunctionParameters(std::vector<double>& values) const;
/**
......@@ -283,7 +283,7 @@ class OPENMM_EXPORT Discrete2DFunction : public TabulatedFunction {
public:
/**
* Create a Discrete2DFunction f(x,y) based on a set of tabulated values.
*
*
* @param xsize the number of table elements along the x direction
* @param ysize the number of table elements along the y direction
* @param values the tabulated values of the function f(x,y), ordered so that
......@@ -293,10 +293,10 @@ public:
/**
* Get the parameters for the tabulated function.
*
* @param xsize the number of table elements along the x direction
* @param ysize the number of table elements along the y direction
* @param values the tabulated values of the function f(x,y), ordered so that
* values[i+xsize*j] = f(i,j). This must be of length xsize*ysize.
* @param[out] xsize the number of table elements along the x direction
* @param[out] ysize the number of table elements along the y direction
* @param[out] values the tabulated values of the function f(x,y), ordered so that
* values[i+xsize*j] = f(i,j). This must be of length xsize*ysize.
*/
void getFunctionParameters(int& xsize, int& ysize, std::vector<double>& values) const;
/**
......@@ -326,7 +326,7 @@ class OPENMM_EXPORT Discrete3DFunction : public TabulatedFunction {
public:
/**
* Create a Discrete3DFunction f(x,y,z) based on a set of tabulated values.
*
*
* @param xsize the number of table elements along the x direction
* @param ysize the number of table elements along the y direction
* @param zsize the number of table elements along the z direction
......@@ -337,11 +337,11 @@ public:
/**
* Get the parameters for the tabulated function.
*
* @param xsize the number of table elements along the x direction
* @param ysize the number of table elements along the y direction
* @param zsize the number of table elements along the z direction
* @param values the tabulated values of the function f(x,y,z), ordered so that
* values[i+xsize*j+xsize*ysize*k] = f(i,j,k). This must be of length xsize*ysize*zsize.
* @param[out] xsize the number of table elements along the x direction
* @param[out] ysize the number of table elements along the y direction
* @param[out] zsize the number of table elements along the z direction
* @param[out] values the tabulated values of the function f(x,y,z), ordered so that
* values[i+xsize*j+xsize*ysize*k] = f(i,j,k). This must be of length xsize*ysize*zsize.
*/
void getFunctionParameters(int& xsize, int& ysize, int& zsize, std::vector<double>& values) const;
/**
......
......@@ -115,9 +115,9 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
// Find the displacement to move it into the first periodic box.
Vec3 diff;
diff -= periodicBoxSize[0]*static_cast<int>(center[0]/periodicBoxSize[0][0]);
diff -= periodicBoxSize[1]*static_cast<int>(center[1]/periodicBoxSize[1][1]);
diff -= periodicBoxSize[2]*static_cast<int>(center[2]/periodicBoxSize[2][2]);
diff += periodicBoxSize[2]*floor(center[2]/periodicBoxSize[2][2]);
diff += periodicBoxSize[1]*floor((center[1]-diff[1])/periodicBoxSize[1][1]);
diff += periodicBoxSize[0]*floor((center[0]-diff[0])/periodicBoxSize[0][0]);
// Translate all the particles in the molecule.
for (int j = 0; j < (int) molecules[i].size(); j++) {
......
......@@ -449,4 +449,5 @@ void ContextImpl::loadCheckpoint(istream& stream) {
parameters[name] = value;
}
updateStateDataKernel.getAs<UpdateStateDataKernel>().loadCheckpoint(*this, stream);
hasSetPositions = true;
}
......@@ -92,6 +92,15 @@ void testCheckpoint() {
integrator.step(10);
State s4 = context.getState(State::Positions | State::Velocities | State::Parameters);
compareStates(s2, s4);
// See if a checkpoint created from one Context can be loaded into a different one.
VerletIntegrator integrator2(0.001);
Context context2(system, integrator2, platform);
stream1.seekg(0, stream1.beg);
context2.loadCheckpoint(stream1);
State s5 = context2.getState(State::Positions | State::Velocities | State::Parameters | State::Energy);
compareStates(s1, s5);
}
void runPlatformTests() {
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2012 Stanford University and the Authors. *
* Portions copyright (c) 2008-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -109,19 +109,27 @@ public:
static const std::string key = "CudaTempDirectory";
return key;
}
/**
* This is the name of the parameter for selecting whether to disable use of a separate stream for PME.
*/
static const std::string& CudaDisablePmeStream() {
static const std::string key = "CudaDisablePmeStream";
return key;
}
};
class OPENMM_EXPORT_CUDA CudaPlatform::PlatformData {
public:
PlatformData(ContextImpl* context, const System& system, const std::string& deviceIndexProperty, const std::string& blockingProperty, const std::string& precisionProperty,
const std::string& cpuPmeProperty, const std::string& compilerProperty, const std::string& tempProperty, const std::string& hostCompilerProperty);
const std::string& cpuPmeProperty, const std::string& compilerProperty, const std::string& tempProperty, const std::string& hostCompilerProperty,
const std::string& pmeStreamProperty);
~PlatformData();
void initializeContexts(const System& system);
void syncContexts();
ContextImpl* context;
std::vector<CudaContext*> contexts;
std::vector<double> contextEnergy;
bool hasInitializedContexts, removeCM, peerAccessSupported, useCpuPme;
bool hasInitializedContexts, removeCM, peerAccessSupported, useCpuPme, disablePmeStream;
int cmMotionFrequency;
int stepCount, computeForceCount;
double time;
......
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