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
......@@ -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
......@@ -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
......
......@@ -695,6 +695,63 @@ of the time. These tests will say so in the error message:
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:
......@@ -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]')
......
......@@ -62,7 +62,7 @@ public:
/**
* 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;
/**
......
......@@ -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
* @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 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] 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;
/**
......@@ -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
* @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 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] 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;
/**
......@@ -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
* @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 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] 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
......@@ -257,7 +257,7 @@ public:
/**
* 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;
/**
......@@ -293,9 +293,9 @@ 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
* @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;
......@@ -337,10 +337,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 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
* @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