Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
c2c0208b
Commit
c2c0208b
authored
Aug 11, 2014
by
peastman
Browse files
Deleted obsolete documentation files
parent
37246338
Changes
43
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
0 additions
and
7717 deletions
+0
-7717
docs/images/Argon.png
docs/images/Argon.png
+0
-0
docs/images/EnergyDrift.png
docs/images/EnergyDrift.png
+0
-0
docs/images/ScriptBuilder.png
docs/images/ScriptBuilder.png
+0
-0
docs/images/SystemContextRelationships.jpg
docs/images/SystemContextRelationships.jpg
+0
-0
docs/images/VisualStudioLaunch.jpg
docs/images/VisualStudioLaunch.jpg
+0
-0
docs/images/VisualStudioSetConfiguration.jpg
docs/images/VisualStudioSetConfiguration.jpg
+0
-0
docs/licenses/GPL.txt
docs/licenses/GPL.txt
+0
-674
docs/licenses/LGPL.txt
docs/licenses/LGPL.txt
+0
-165
docs/licenses/Licenses.txt
docs/licenses/Licenses.txt
+0
-108
docs/sphinx/autonumber.py
docs/sphinx/autonumber.py
+0
-70
docs/sphinx/caption.py
docs/sphinx/caption.py
+0
-18
docs/sphinx/numsec.py
docs/sphinx/numsec.py
+0
-52
docs/sphinx/samepage.py
docs/sphinx/samepage.py
+0
-17
docs/usersguide/Makefile
docs/usersguide/Makefile
+0
-153
docs/usersguide/application.rst
docs/usersguide/application.rst
+0
-2470
docs/usersguide/conf.py
docs/usersguide/conf.py
+0
-254
docs/usersguide/header.rst
docs/usersguide/header.rst
+0
-7
docs/usersguide/index.rst
docs/usersguide/index.rst
+0
-41
docs/usersguide/introduction.rst
docs/usersguide/introduction.rst
+0
-57
docs/usersguide/library.rst
docs/usersguide/library.rst
+0
-3631
No files found.
docs/images/Argon.png
deleted
100644 → 0
View file @
37246338
32.8 KB
docs/images/EnergyDrift.png
deleted
100644 → 0
View file @
37246338
130 KB
docs/images/ScriptBuilder.png
deleted
100644 → 0
View file @
37246338
259 KB
docs/images/SystemContextRelationships.jpg
deleted
100644 → 0
View file @
37246338
57.5 KB
docs/images/VisualStudioLaunch.jpg
deleted
100644 → 0
View file @
37246338
220 KB
docs/images/VisualStudioSetConfiguration.jpg
deleted
100644 → 0
View file @
37246338
88 KB
docs/licenses/GPL.txt
deleted
100644 → 0
View file @
37246338
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
docs/licenses/LGPL.txt
deleted
100644 → 0
View file @
37246338
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
docs/licenses/Licenses.txt
deleted
100644 → 0
View file @
37246338
OpenMM was developed by Simbios, the NIH National Center for Physics-Based
Simulation of Biological Structures at Stanford, funded under the NIH Roadmap
for Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright © 2008-2009 Stanford University and the Authors.
There are several licenses which cover different parts of OpenMM as described
below.
1. API and Reference Platform
The OpenMM API and the Reference Platform may be used under the terms of the
MIT License:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2. CUDA and OpenCL Platforms
The CUDA Platform and OpenCL Platform may be used under the terms of the GNU
Lesser General Public License. A copy of this license may be found in the
accompanying file "LGPL.txt". It in turn incorporates the terms of the GNU
General Public License, which may be found in the accompanying file "GPL.txt".
3. SIMD-oriented Fast Mersenne Twister (SFMT)
OpenMM uses the SFMT library which is copyright 2006-2007 Mutsuo Saito, Makoto
Matsumoto and Hiroshima University. It may be used under the following terms:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the Hiroshima University nor the names of
its contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4. Hilbert Curve
OpenMM uses an implementation of Hilbert curves which is copyright 1998-2000
Rice University. It may be used under the following terms:
This software is copyrighted by Rice University. It may be freely copied,
modified, and redistributed, provided that the copyright notice is
preserved on all copies.
There is no warranty or other guarantee of fitness for this software,
it is provided solely "as is". Bug reports or fixes may be sent
to the author, who may or may not act on them as he desires.
You may include this software in a program or other software product,
but must display the notice:
Hilbert Curve implementation copyright 1998, Rice University
in any place where the end-user would see your own copyright.
If you modify this software, you should include a notice giving the
name of the person performing the modification, the date of modification,
and the reason for such modification.
5. GPU-BBSort
The CUDA platform uses the GPU-BBSort library written by Chen Shifu. It
includes the following license statement:
The code is distributed under BSD license, you are allowed to use, modify
or sell this code, but a statement is required if you used this code any where.
\ No newline at end of file
docs/sphinx/autonumber.py
deleted
100644 → 0
View file @
37246338
from
docutils.parsers.rst
import
roles
from
docutils.nodes
import
Text
,
reference
,
section
from
sphinx.roles
import
XRefRole
class
autonumber
(
Text
):
pass
class
autonumber_ref
(
reference
):
pass
def
autonumber_role
(
name
,
rawtext
,
text
,
lineno
,
inliner
,
options
=
{},
content
=
[]):
return
([
autonumber
(
text
)],
[])
def
doctree_resolved
(
app
,
doctree
,
docname
):
index
=
{};
refTable
=
{}
if
app
.
config
.
autonumber_by_chapter
:
# Record the number of each chapter
env
=
app
.
builder
.
env
sectionNumbers
=
{}
for
doc
in
env
.
toc_secnumbers
:
sections
=
env
.
toc_secnumbers
[
doc
]
for
sectionId
in
sections
:
sectionNumbers
[
sectionId
[
1
:]]
=
sections
[
sectionId
]
lastChapter
=
-
1
# Assign numbers to all the autonumbered objects.
for
node
in
doctree
.
traverse
(
autonumber
):
category
=
node
.
astext
().
split
(
','
)[
0
]
if
category
in
index
:
nextNumber
=
index
[
category
]
+
1
else
:
nextNumber
=
1
if
app
.
config
.
autonumber_by_chapter
:
parent
=
node
.
parent
chapter
=
None
while
chapter
is
None
:
if
isinstance
(
parent
,
section
):
chapter
=
parent
parent
=
parent
.
parent
chapter
=
sectionNumbers
[
chapter
.
attributes
[
'ids'
][
0
]][
0
]
if
chapter
!=
lastChapter
:
index
=
{}
newNode
=
Text
(
'%s %d-%d'
%
(
category
,
chapter
,
nextNumber
))
lastChapter
=
chapter
else
:
newNode
=
Text
(
'%s %d'
%
(
category
,
nextNumber
))
index
[
category
]
=
nextNumber
refTable
[
node
.
astext
()]
=
newNode
node
.
parent
.
replace
(
node
,
newNode
)
# Replace references with the name of the referenced object
for
ref_info
in
doctree
.
traverse
(
autonumber_ref
):
target
=
ref_info
[
'reftarget'
]
if
target
not
in
refTable
:
raise
ValueError
(
'Unknown target for autonumber reference: '
+
target
)
ref_info
.
replace_self
(
Text
(
refTable
[
target
].
astext
()))
def
setup
(
app
):
app
.
add_config_value
(
'autonumber_by_chapter'
,
True
,
False
)
roles
.
register_local_role
(
'autonumber'
,
autonumber_role
)
app
.
add_node
(
autonumber
)
app
.
add_node
(
autonumber_ref
)
app
.
add_role
(
'numref'
,
XRefRole
(
nodeclass
=
autonumber_ref
))
app
.
connect
(
'doctree-resolved'
,
doctree_resolved
)
docs/sphinx/caption.py
deleted
100644 → 0
View file @
37246338
from
docutils.parsers.rst
import
Directive
from
docutils.nodes
import
compound
,
raw
class
CaptionDirective
(
Directive
):
has_content
=
True
def
run
(
self
):
latexPrefix
=
raw
(
''
,
'{
\\
centering'
,
format
=
'latex'
)
latexSuffix
=
raw
(
''
,
'
\\
par}
\\
bigskip'
,
format
=
'latex'
)
text
=
'
\n
'
.
join
(
self
.
content
)
content_node
=
compound
(
rawsource
=
text
)
self
.
state
.
nested_parse
(
self
.
content
,
self
.
content_offset
,
content_node
)
content_node
.
attributes
[
'classes'
].
append
(
'caption'
)
return
[
latexPrefix
,
content_node
,
latexSuffix
]
def
setup
(
app
):
app
.
add_directive
(
'caption'
,
CaptionDirective
)
docs/sphinx/numsec.py
deleted
100644 → 0
View file @
37246338
"""
Changes section references to be the section number
instead of the title of the section.
"""
from
docutils
import
nodes
import
sphinx.domains.std
class
CustomStandardDomain
(
sphinx
.
domains
.
std
.
StandardDomain
):
def
__init__
(
self
,
env
):
env
.
settings
[
'footnote_references'
]
=
'superscript'
sphinx
.
domains
.
std
.
StandardDomain
.
__init__
(
self
,
env
)
def
resolve_xref
(
self
,
env
,
fromdocname
,
builder
,
typ
,
target
,
node
,
contnode
):
res
=
super
(
CustomStandardDomain
,
self
).
resolve_xref
(
env
,
fromdocname
,
builder
,
typ
,
target
,
node
,
contnode
)
if
res
is
None
:
return
res
if
typ
==
'ref'
and
not
node
[
'refexplicit'
]:
docname
,
labelid
,
sectname
=
self
.
data
[
'labels'
].
get
(
target
,
(
''
,
''
,
''
))
res
[
'refdocname'
]
=
docname
return
res
def
doctree_resolved
(
app
,
doctree
,
docname
):
secnums
=
app
.
builder
.
env
.
toc_secnumbers
for
node
in
doctree
.
traverse
(
nodes
.
reference
):
if
'refdocname'
in
node
:
refdocname
=
node
[
'refdocname'
]
if
refdocname
in
secnums
:
secnum
=
secnums
[
refdocname
]
emphnode
=
node
.
children
[
0
]
textnode
=
emphnode
.
children
[
0
]
toclist
=
app
.
builder
.
env
.
tocs
[
refdocname
]
anchorname
=
None
for
refnode
in
toclist
.
traverse
(
nodes
.
reference
):
if
refnode
.
astext
()
==
textnode
.
astext
():
anchorname
=
refnode
[
'anchorname'
]
if
anchorname
is
None
:
continue
linktext
=
'.'
.
join
(
map
(
str
,
secnum
[
anchorname
]))
node
.
replace
(
emphnode
,
nodes
.
Text
(
linktext
))
def
setup
(
app
):
app
.
override_domain
(
CustomStandardDomain
)
app
.
connect
(
'doctree-resolved'
,
doctree_resolved
)
docs/sphinx/samepage.py
deleted
100644 → 0
View file @
37246338
from
docutils.parsers.rst
import
Directive
from
docutils.nodes
import
compound
,
raw
class
SamepageDirective
(
Directive
):
has_content
=
True
def
run
(
self
):
prefix
=
raw
(
''
,
'
\\
par
\\
begin{samepage}'
,
format
=
'latex'
)
suffix
=
raw
(
''
,
'
\\
end{samepage}
\\
par'
,
format
=
'latex'
)
text
=
'
\n
'
.
join
(
self
.
content
)
content_node
=
compound
(
rawsource
=
text
)
self
.
state
.
nested_parse
(
self
.
content
,
self
.
content_offset
,
content_node
)
return
[
prefix
,
content_node
,
suffix
]
def
setup
(
app
):
app
.
add_directive
(
'samepage'
,
SamepageDirective
)
docs/usersguide/Makefile
deleted
100644 → 0
View file @
37246338
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS
=
SPHINXBUILD
=
sphinx-build
PAPER
=
BUILDDIR
=
_build
# Internal variables.
PAPEROPT_a4
=
-D
latex_paper_size
=
a4
PAPEROPT_letter
=
-D
latex_paper_size
=
letter
ALLSPHINXOPTS
=
-d
$(BUILDDIR)
/doctrees
$
(
PAPEROPT_
$(PAPER)
)
$(SPHINXOPTS)
.
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS
=
$
(
PAPEROPT_
$(PAPER)
)
$(SPHINXOPTS)
.
.PHONY
:
help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help
:
@
echo
"Please use
\`
make <target>' where <target> is one of"
@
echo
" html to make standalone HTML files"
@
echo
" dirhtml to make HTML files named index.html in directories"
@
echo
" singlehtml to make a single large HTML file"
@
echo
" pickle to make pickle files"
@
echo
" json to make JSON files"
@
echo
" htmlhelp to make HTML files and a HTML help project"
@
echo
" qthelp to make HTML files and a qthelp project"
@
echo
" devhelp to make HTML files and a Devhelp project"
@
echo
" epub to make an epub"
@
echo
" latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@
echo
" latexpdf to make LaTeX files and run them through pdflatex"
@
echo
" text to make text files"
@
echo
" man to make manual pages"
@
echo
" texinfo to make Texinfo files"
@
echo
" info to make Texinfo files and run them through makeinfo"
@
echo
" gettext to make PO message catalogs"
@
echo
" changes to make an overview of all changed/added/deprecated items"
@
echo
" linkcheck to check all external links for integrity"
@
echo
" doctest to run all doctests embedded in the documentation (if enabled)"
clean
:
-
rm
-rf
$(BUILDDIR)
/
*
html
:
$(SPHINXBUILD)
-b
html
$(ALLSPHINXOPTS)
$(BUILDDIR)
/html
@
echo
@
echo
"Build finished. The HTML pages are in
$(BUILDDIR)
/html."
dirhtml
:
$(SPHINXBUILD)
-b
dirhtml
$(ALLSPHINXOPTS)
$(BUILDDIR)
/dirhtml
@
echo
@
echo
"Build finished. The HTML pages are in
$(BUILDDIR)
/dirhtml."
singlehtml
:
$(SPHINXBUILD)
-b
singlehtml
$(ALLSPHINXOPTS)
$(BUILDDIR)
/singlehtml
@
echo
@
echo
"Build finished. The HTML page is in
$(BUILDDIR)
/singlehtml."
pickle
:
$(SPHINXBUILD)
-b
pickle
$(ALLSPHINXOPTS)
$(BUILDDIR)
/pickle
@
echo
@
echo
"Build finished; now you can process the pickle files."
json
:
$(SPHINXBUILD)
-b
json
$(ALLSPHINXOPTS)
$(BUILDDIR)
/json
@
echo
@
echo
"Build finished; now you can process the JSON files."
htmlhelp
:
$(SPHINXBUILD)
-b
htmlhelp
$(ALLSPHINXOPTS)
$(BUILDDIR)
/htmlhelp
@
echo
@
echo
"Build finished; now you can run HTML Help Workshop with the"
\
".hhp project file in
$(BUILDDIR)
/htmlhelp."
qthelp
:
$(SPHINXBUILD)
-b
qthelp
$(ALLSPHINXOPTS)
$(BUILDDIR)
/qthelp
@
echo
@
echo
"Build finished; now you can run "
qcollectiongenerator
" with the"
\
".qhcp project file in
$(BUILDDIR)
/qthelp, like this:"
@
echo
"# qcollectiongenerator
$(BUILDDIR)
/qthelp/OpenMMDeveloperGuide.qhcp"
@
echo
"To view the help file:"
@
echo
"# assistant -collectionFile
$(BUILDDIR)
/qthelp/OpenMMDeveloperGuide.qhc"
devhelp
:
$(SPHINXBUILD)
-b
devhelp
$(ALLSPHINXOPTS)
$(BUILDDIR)
/devhelp
@
echo
@
echo
"Build finished."
@
echo
"To view the help file:"
@
echo
"# mkdir -p
$$
HOME/.local/share/devhelp/OpenMMDeveloperGuide"
@
echo
"# ln -s
$(BUILDDIR)
/devhelp
$$
HOME/.local/share/devhelp/OpenMMDeveloperGuide"
@
echo
"# devhelp"
epub
:
$(SPHINXBUILD)
-b
epub
$(ALLSPHINXOPTS)
$(BUILDDIR)
/epub
@
echo
@
echo
"Build finished. The epub file is in
$(BUILDDIR)
/epub."
latex
:
$(SPHINXBUILD)
-b
latex
$(ALLSPHINXOPTS)
$(BUILDDIR)
/latex
@
echo
@
echo
"Build finished; the LaTeX files are in
$(BUILDDIR)
/latex."
@
echo
"Run
\`
make' in that directory to run these through (pdf)latex"
\
"(use
\`
make latexpdf' here to do that automatically)."
latexpdf
:
$(SPHINXBUILD)
-b
latex
$(ALLSPHINXOPTS)
$(BUILDDIR)
/latex
@
echo
"Running LaTeX files through pdflatex..."
$(MAKE)
-C
$(BUILDDIR)
/latex all-pdf
@
echo
"pdflatex finished; the PDF files are in
$(BUILDDIR)
/latex."
text
:
$(SPHINXBUILD)
-b
text
$(ALLSPHINXOPTS)
$(BUILDDIR)
/text
@
echo
@
echo
"Build finished. The text files are in
$(BUILDDIR)
/text."
man
:
$(SPHINXBUILD)
-b
man
$(ALLSPHINXOPTS)
$(BUILDDIR)
/man
@
echo
@
echo
"Build finished. The manual pages are in
$(BUILDDIR)
/man."
texinfo
:
$(SPHINXBUILD)
-b
texinfo
$(ALLSPHINXOPTS)
$(BUILDDIR)
/texinfo
@
echo
@
echo
"Build finished. The Texinfo files are in
$(BUILDDIR)
/texinfo."
@
echo
"Run
\`
make' in that directory to run these through makeinfo"
\
"(use
\`
make info' here to do that automatically)."
info
:
$(SPHINXBUILD)
-b
texinfo
$(ALLSPHINXOPTS)
$(BUILDDIR)
/texinfo
@
echo
"Running Texinfo files through makeinfo..."
make
-C
$(BUILDDIR)
/texinfo info
@
echo
"makeinfo finished; the Info files are in
$(BUILDDIR)
/texinfo."
gettext
:
$(SPHINXBUILD)
-b
gettext
$(I18NSPHINXOPTS)
$(BUILDDIR)
/locale
@
echo
@
echo
"Build finished. The message catalogs are in
$(BUILDDIR)
/locale."
changes
:
$(SPHINXBUILD)
-b
changes
$(ALLSPHINXOPTS)
$(BUILDDIR)
/changes
@
echo
@
echo
"The overview file is in
$(BUILDDIR)
/changes."
linkcheck
:
$(SPHINXBUILD)
-b
linkcheck
$(ALLSPHINXOPTS)
$(BUILDDIR)
/linkcheck
@
echo
@
echo
"Link check complete; look for any errors in the above output "
\
"or in
$(BUILDDIR)
/linkcheck/output.txt."
doctest
:
$(SPHINXBUILD)
-b
doctest
$(ALLSPHINXOPTS)
$(BUILDDIR)
/doctest
@
echo
"Testing of doctests in the sources finished, look at the "
\
"results in
$(BUILDDIR)
/doctest/output.txt."
docs/usersguide/application.rst
deleted
100644 → 0
View file @
37246338
..
include
::
header
.
rst
..
_the
-
openmm
-
application
-
layer
-
introduction
:
The
OpenMM
Application
Layer
:
Introduction
##########################################
The
first
thing
to
understand
about
the
OpenMM
“
application
layer
”
is
that
it
is
not
exactly
an
application
in
the
traditional
sense
:
there
is
no
program
called
“
OpenMM
”
that
you
run
.
Rather
,
it
is
a
collection
of
libraries
written
in
the
Python
programming
language
.
Those
libraries
can
easily
be
chained
together
to
create
Python
programs
that
run
simulations
.
But
don
’
t
worry
! You don’t need
to
know
anything
about
Python
programming
(
or
programming
at
all
)
to
use
it
.
Nearly
all
molecular
simulation
applications
ask
you
to
write
some
sort
of
“
script
”
that
specifies
the
details
of
the
simulation
to
run
.
With
OpenMM
,
that
script
happens
to
be
written
in
Python
.
But
it
is
no
harder
to
write
than
those
for
most
other
applications
,
and
this
guide
will
teach
you
everything
you
need
to
know
.
There
is
even
a
graphical
interface
that
can
write
the
script
for
you
based
on
a
simple
set
of
options
(
see
section
:
ref
:`
the
-
script
-
builder
-
application
`),
so
you
never
need
to
type
a
single
line
of
code
!
On
the
other
hand
,
if
you
don
’
t
mind
doing
a
little
programming
,
this
approach
gives
you
enormous
power
and
flexibility
.
Your
script
has
complete
access
to
the
entire
OpenMM
application
programming
interface
(
API
),
as
well
as
the
full
power
of
the
Python
language
and
libraries
.
You
have
complete
control
over
every
detail
of
the
simulation
,
from
defining
the
molecular
system
to
analyzing
the
results
.
..
_installing
-
openmm
:
Installing
OpenMM
#################
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
).
Installing
on
Mac
OS
X
**********************
OpenMM
works
on
Mac
OS
X
10.7
or
later
.
GPU
acceleration
is
currently
only
supported
on
Nvidia
GPUs
,
not
on
AMD
or
Intel
GPUs
.
\
**
Important
:**
A
serious
bug
was
introduced
in
Mac
OS
X
10.7.5
that
prevents
OpenMM
’
s
OpenCL
platform
from
working
correctly
.
At
the
time
of
this
writing
,
the
bug
is
present
in
all
versions
from
10.7.5
onward
.
The
CUDA
platform
(
see
below
)
is
not
affected
by
the
bug
,
so
if
you
have
an
affected
version
of
OS
X
,
you
should
use
it
instead
of
the
OpenCL
platform
.
1.
Download
the
pre
-
compiled
binary
of
OpenMM
for
Mac
OS
X
,
then
double
click
the
.
zip
file
to
expand
it
.
2.
If
you
have
not
already
done
so
,
install
Apple
’
s
Xcode
developer
tools
from
the
App
Store
.
They
are
required
to
use
OpenMM
.
(
With
Xcode
4.3
and
later
,
you
must
then
launch
Xcode
,
open
the
Preferences
window
,
go
to
the
Downloads
tab
,
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
5.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
install
FFTW
,
available
from
http
://
www
.
fftw
.
org
.
When
configuring
it
,
be
sure
to
specify
single
precision
and
multiple
threads
(
the
|--|\
:
code
:`
enable
-
float
`
and
|--|\
:
code
:`
enable
-
threads
`
options
).
OpenMM
will
still
work
without
FFTW
,
but
the
performance
of
particle
mesh
Ewald
(
PME
)
will
be
much
worse
.
5.
Launch
the
Terminal
application
.
Change
to
the
OpenMM
directory
by
typing
::
cd
<
openmm_directory
>
where
:
code
:`<
openmm_directory
>`
is
the
path
to
the
OpenMM
folder
.
Then
run
the
install
script
by
typing
::
sudo
./
install
.
sh
It
will
prompt
you
for
an
install
location
and
the
path
to
the
python
executable
.
Unless
you
are
certain
you
know
what
you
are
doing
,
accept
the
defaults
for
both
options
.
6.
(
Optional
)
To
use
the
CUDA
platform
on
an
Nvidia
GPU
,
you
must
add
the
CUDA
libraries
to
your
library
path
so
your
computer
knows
where
to
find
them
.
You
can
do
this
by
typing
::
export
DYLD_LIBRARY_PATH
=/
usr
/
local
/
cuda
/
lib
This
will
affect
only
the
particular
Terminal
window
you
type
it
into
.
If
you
want
to
run
OpenMM
in
another
Terminal
window
,
you
must
type
the
above
command
in
the
new
window
.
If
you
plan
to
use
the
CUDA
platform
,
OpenMM
also
needs
to
locate
the
CUDA
kernel
compiler
(
nvcc
).
By
default
it
looks
for
it
in
the
location
:
file
:`/
usr
/
local
/
cuda
/
bin
/
nvcc
`.
If
you
have
installed
the
CUDA
toolkit
in
a
different
location
,
you
can
set
OPENMM_CUDA_COMPILER
to
tell
OpenMM
where
to
find
it
.
For
example
,
::
export
OPENMM_CUDA_COMPILER
=/
opt
/
CUDA
/
cuda
-
5.5
/
bin
/
nvcc
7.
Verify
your
installation
by
running
the
“
testInstallation
.
py
”
script
found
in
the
“
examples
”
folder
of
your
OpenMM
installation
.
To
run
it
,
cd
to
the
examples
folder
and
type
::
python
testInstallation
.
py
This
script
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
.
Important
Note
:
Some
Mac
laptops
have
two
GPUs
,
only
one
of
which
is
capable
of
running
OpenMM
.
If
you
have
a
laptop
,
open
the
System
Preferences
and
go
to
the
Energy
Saver
panel
.
There
will
be
a
checkbox
labeled
“
Automatic
graphics
switching
”
,
which
should
be
disabled
.
Otherwise
,
trying
to
run
OpenMM
may
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
.
zip
file
to
expand
it
.
2.
Make
sure
you
have
Python
2.6
or
higher
(
earlier
versions
will
not
work
)
and
a
C
++
compiler
(
typically
gcc
or
clang
)
installed
on
your
computer
.
You
can
check
what
version
of
Python
is
installed
by
typing
:
code
:`
python
`
|--|\
:
code
:`
version
`
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
5.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
from
http
://
support
.
amd
.
com
.
4.
(
Optional
)
If
you
plan
to
use
the
CPU
platform
,
it
is
recommended
that
you
install
FFTW
.
It
is
probably
available
through
your
system
’
s
package
manager
such
as
:
code
:`
yum
`
or
:
code
:`
apt
-
get
`\
.
Alternatively
,
you
can
download
it
from
http
://
www
.
fftw
.
org
.
When
configuring
it
,
be
sure
to
specify
single
precision
and
multiple
threads
(
the
|--|\
:
code
:`
enable
-
float
`
and
|--|\
:
code
:`
enable
-
threads
`
options
).
OpenMM
will
still
work
without
FFTW
,
but
the
performance
of
particle
mesh
Ewald
(
PME
)
will
be
much
worse
.
5.
In
a
console
window
,
change
to
the
OpenMM
directory
by
typing
::
cd
<
openmm_directory
>
where
:
code
:`<
openmm_directory
>`
is
the
path
to
the
OpenMM
folder
.
Then
run
the
install
script
by
typing
::
sudo
./
install
.
sh
It
will
prompt
you
for
an
install
location
and
the
path
to
the
python
executable
.
Unless
you
are
certain
you
know
what
you
are
doing
,
accept
the
defaults
for
both
options
.
6.
(
Optional
)
To
use
the
CUDA
platform
on
an
Nvidia
GPU
,
you
must
add
the
CUDA
libraries
to
your
library
path
so
your
computer
knows
where
to
find
them
.
You
can
do
this
by
typing
::
export
LD_LIBRARY_PATH
=/
usr
/
local
/
cuda
/
lib
This
will
affect
only
the
particular
console
window
you
type
it
into
.
If
you
want
to
run
OpenMM
in
another
console
window
,
you
must
type
the
above
command
in
the
new
window
.
If
you
plan
to
use
the
CUDA
platform
,
OpenMM
also
needs
to
locate
the
CUDA
kernel
compiler
(
nvcc
).
By
default
it
looks
for
it
in
the
location
:
file
:`/
usr
/
local
/
cuda
/
bin
/
nvcc
`.
If
you
have
installed
the
CUDA
toolkit
in
a
different
location
,
you
can
set
OPENMM_CUDA_COMPILER
to
tell
OpenMM
where
to
find
it
.
For
example
,
::
export
OPENMM_CUDA_COMPILER
=/
opt
/
CUDA
/
cuda
-
5.5
/
bin
/
nvcc
7.
Verify
your
installation
by
running
the
“
testInstallation
.
py
”
script
found
in
the
“
examples
”
folder
of
your
OpenMM
installation
.
To
run
it
,
cd
to
the
examples
folder
and
type
::
python
testInstallation
.
py
This
script
confirms
that
OpenMM
is
installed
,
checks
whether
GPU
acceleration
is
available
(
via
that
OpenCL
and
/
or
CUDA
platforms
),
and
verifies
that
all
platforms
produce
consistent
results
.
Installing
on
Windows
*********************
1.
Download
the
pre
-
compiled
binary
of
OpenMM
for
Windows
,
then
double
click
the
.
zip
file
to
expand
it
.
Move
the
files
to
:
file
:`
C
:\\
Program
Files
\\
OpenMM
`.
(
On
64
bit
Windows
,
use
:
file
:`
C
:\\
Program
Files
(
x86
)\\
OpenMM
`).
2.
Make
sure
you
have
the
32
-
bit
version
of
Python
3.3
(
other
versions
will
not
work
)
installed
on
your
computer
.
To
do
this
,
launch
the
Python
program
(
either
the
command
line
version
or
the
GUI
version
).
The
first
line
in
the
Python
window
will
indicate
the
version
you
have
,
as
well
as
whether
you
have
a
32
-
bit
or
64
-
bit
version
.
3.
Double
click
the
Python
API
Installer
to
install
the
Python
components
.
(
On
some
versions
of
Windows
,
a
“
Program
Compatibility
Assistant
”
window
may
appear
with
the
warning
,
“
This
program
might
not
have
installed
correctly
.
”
This
is
just
Microsoft
trying
to
scare
you
.
Click
“
This
program
installed
correctly
”
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
5.5
from
https
://
developer
.
nvidia
.
com
/
cuda
-
downloads
.
Be
sure
to
install
both
the
drivers
and
toolkit
.
For
64
-
bit
machines
,
you
should
install
the
64
-
bit
driver
,
but
download
the
32
-
bit
version
of
the
toolkit
since
the
OpenMM
binary
is
32
-
bit
.
OpenCL
is
included
with
the
CUDA
drivers
.
*
If
you
have
an
AMD
GPU
,
download
the
latest
version
of
the
Catalyst
driver
from
http
://
support
.
amd
.
com
.
5.
(
Optional
)
If
you
plan
to
use
the
CPU
platform
,
it
is
recommended
that
you
install
FFTW
.
Precompiled
binaries
are
available
from
http
://
www
.
fftw
.
org
.
Even
on
64
-
bit
machines
you
should
use
the
32
-
bit
version
since
the
OpenMM
binary
is
32
-
bit
.
OpenMM
will
still
work
without
FFTW
,
but
the
performance
of
particle
mesh
Ewald
(
PME
)
will
be
much
worse
.
6.
Before
running
OpenMM
,
you
must
add
the
OpenMM
and
FFTW
libraries
to
your
PATH
environment
variable
.
You
may
also
need
to
add
the
Python
executable
to
your
PATH
.
*
To
find
out
if
the
Python
executable
is
already
in
your
PATH
,
open
a
command
prompt
window
by
clicking
on
Start
->
Programs
->
Accessories
->
Command
Prompt
.
(
On
Windows
7
,
select
Start
->
All
Programs
->
Accessories
->
Command
Prompt
).
Type
::
python
If
you
get
an
error
message
,
such
as
"‘python’ is not recognized as an
internal or external command, operable program or batch file,"
then
you
need
to
add
Python
to
your
PATH
.
To
do
so
,
locate
it
by
typing
::
dir
C
:\
py
*
The
files
are
typically
located
in
a
directory
like
:
file
:`
C
:\\
Python33
`.
Remember
this
location
.
You
will
need
to
enter
it
,
along
with
the
location
of
the
OpenMM
libraries
,
later
in
this
process
.
*
Click
on
Start
->
Control
Panel
->
System
(
On
Windows
7
,
select
Start
->
Control
Panel
->
System
and
Security
->
System
)
*
Click
on
the
“
Advanced
”
tab
or
the
“
Advanced
system
settings
”
link
*
Click
“
Environment
Variables
”
*
Under
“
System
variables
,
”
select
the
line
for
“
Path
”
and
click
“
Edit
…”
*
Add
:
file
:`
C
:\\
Program
Files
\\
OpenMM
\\
lib
`
and
:
file
:`
C
:\\
Program
Files
\\
OpenMM
\\
lib
\\
plugins
`
to
the
“
Variable
value
”
.
If
you
also
need
to
add
Python
or
FFTW
to
your
PATH
,
enter
their
directory
locations
here
.
Directory
locations
need
to
be
separated
by
semi
-
colons
(;).
If
you
installed
OpenMM
somewhere
other
than
the
default
location
,
you
must
also
set
OPENMM_PLUGIN_DIR
to
point
to
the
plugins
directory
.
If
this
variable
is
not
set
,
it
will
assume
plugins
are
in
the
default
location
(:
file
:`
C
:\\
Program
Files
\\
OpenMM
\\
lib
\\
plugins
`
or
:
file
:`
C
:\\
Program
Files
(
x86
)\\
OpenMM
\\
lib
\\
plugins
`).
7.
Verify
your
installation
by
running
the
“
testInstallation
.
py
”
script
found
in
the
“
examples
”
folder
of
your
OpenMM
installation
.
To
run
it
,
open
a
command
window
,
cd
to
the
examples
folder
,
and
type
::
python
testInstallation
.
py
This
script
confirms
that
OpenMM
is
installed
,
checks
whether
GPU
acceleration
is
available
(
via
that
OpenCL
and
/
or
CUDA
platforms
),
and
verifies
that
all
platforms
produce
consistent
results
.
Running
Simulations
###################
..
_a
-
first
-
example
:
A
First
Example
***************
Let
’
s
begin
with
our
first
example
of
an
OpenMM
script
.
It
loads
a
PDB
file
called
“
input
.
pdb
”
,
models
it
using
the
AMBER99SB
force
field
and
TIP3P
water
model
,
energy
minimizes
it
,
simulates
it
for
10
,
000
steps
with
a
Langevin
integrator
,
and
saves
a
frame
to
a
PDB
file
called
“
output
.
pdb
”
every
1000
time
steps
.
..
samepage
::
::
from
simtk
.
openmm
.
app
import
*
from
simtk
.
openmm
import
*
from
simtk
.
unit
import
*
from
sys
import
stdout
pdb
=
PDBFile
(
'input.pdb'
)
forcefield
=
ForceField
(
'amber99sb.xml'
,
'tip3p.xml'
)
system
=
forcefield
.
createSystem
(
pdb
.
topology
,
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
constraints
=
HBonds
)
integrator
=
LangevinIntegrator
(
300
*
kelvin
,
1
/
picosecond
,
0.002
*
picoseconds
)
simulation
=
Simulation
(
pdb
.
topology
,
system
,
integrator
)
simulation
.
context
.
setPositions
(
pdb
.
positions
)
simulation
.
minimizeEnergy
()
simulation
.
reporters
.
append
(
PDBReporter
(
'output.pdb'
,
1000
))
simulation
.
reporters
.
append
(
StateDataReporter
(
stdout
,
1000
,
step
=
True
,
potentialEnergy
=
True
,
temperature
=
True
))
simulation
.
step
(
10000
)
..
caption
::
:
autonumber
:`
Example
,
PDB
example
`
You
can
find
this
script
in
the
“
examples
”
folder
of
your
OpenMM
installation
.
It
is
called
“
simulatePdb
.
py
”
.
To
execute
it
from
a
command
line
,
go
to
your
terminal
/
console
/
command
prompt
window
(
see
Chapter
:
ref
:`
installing
-
openmm
`
on
setting
up
the
window
to
use
OpenMM
).
Navigate
to
the
“
examples
”
folder
by
typing
::
cd
<
examples_directory
>
where
the
typical
directory
is
:
file
:`/
usr
/
local
/
openmm
/
examples
`
on
Linux
and
Mac
machines
and
:
file
:`
C
:\\
Program
Files
\\
OpenMM
\\
examples
`
on
Windows
machines
.
Then
type
::
python
simulatePdb
.
py
You
can
name
your
own
scripts
whatever
you
want
,
but
their
names
should
end
with
“
.
py
”
.
Let
’
s
go
through
the
script
line
by
line
and
see
how
it
works
.
::
from
simtk
.
openmm
.
app
import
*
from
simtk
.
openmm
import
*
from
simtk
.
unit
import
*
from
sys
import
stdout
These
lines
are
just
telling
the
Python
interpreter
about
some
libraries
we
will
be
using
.
Don
’
t
worry
about
exactly
what
they
mean
.
Just
include
them
at
the
start
of
your
scripts
.
::
pdb
=
PDBFile
(
'input.pdb'
)
This
line
loads
the
PDB
file
from
disk
.
(
The
input
.
pdb
file
in
the
examples
directory
contains
the
villin
headpiece
in
explicit
solvent
.)
More
precisely
,
it
creates
a
PDBFile
object
,
passes
the
file
name
input
.
pdb
to
it
as
an
argument
,
and
assigns
the
object
to
a
variable
called
:
code
:`
pdb
`\
.
The
PDBFile
object
contains
the
information
that
was
read
from
the
file
:
the
molecular
topology
and
atom
positions
.
Your
file
need
not
be
called
“
input
.
pdb
”
.
Feel
free
to
change
this
line
to
specify
any
file
you
want
.
Make
sure
you
include
the
single
quotes
around
the
file
name
.
::
forcefield
=
ForceField
(
'amber99sb.xml'
,
'tip3p.xml'
)
This
line
specifies
the
force
field
to
use
for
the
simulation
.
Force
fields
are
defined
by
XML
files
.
Chapter
:
ref
:`
creating
-
force
-
fields
`
describes
how
to
write
these
files
,
if
you
are
interested
in
that
sort
of
thing
,
but
you
probably
won
’
t
need
to
.
OpenMM
includes
XML
files
defining
lots
of
standard
force
fields
(
see
section
:
ref
:`
force
-
fields
`).
In
this
case
we
load
two
of
those
files
:
amber99sb
.
xml
,
which
contains
the
AMBER99SB
force
field
,
and
tip3p
.
xml
,
which
contains
the
TIP3P
water
model
.
The
ForceField
object
is
assigned
to
a
variable
called
:
code
:`
forcefield
`\
.
::
system
=
forcefield
.
createSystem
(
pdb
.
topology
,
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
constraints
=
HBonds
)
This
line
combines
the
force
field
with
the
molecular
topology
loaded
from
the
PDB
file
to
create
a
complete
mathematical
description
of
the
system
we
want
to
simulate
.
(
More
precisely
,
we
invoke
the
ForceField
object
’
s
“
createSystem
”
function
.
It
creates
a
System
object
,
which
we
assign
to
the
variable
:
code
:`
system
`\
.)
It
specifies
some
additional
options
about
how
to
do
that
:
use
particle
mesh
Ewald
for
the
long
range
electrostatic
interactions
(:
code
:`
nonbondedMethod
=
PME
`\
),
use
a
1
nm
cutoff
for
the
direct
space
interactions
(\
:
code
:`
nonbondedCutoff
=
1
*
nanometer
`\
),
and
constrain
the
length
of
all
bonds
that
involve
a
hydrogen
atom
(\
:
code
:`
constraints
=
HBonds
`\
).
::
integrator
=
LangevinIntegrator
(
300
*
kelvin
,
1
/
picosecond
,
0.002
*
picoseconds
)
This
line
creates
the
integrator
to
use
for
advancing
the
equations
of
motion
.
It
specifies
a
LangevinIntegrator
,
which
(
surprise
!) performs Langevin dynamics,
and
assigns
it
to
a
variable
called
:
code
:`
integrator
`\
.
It
also
specifies
the
values
of
three
parameters
that
are
specific
to
Langevin
dynamics
:
the
simulation
temperature
(
300
K
),
the
friction
coefficient
(
1
ps
\
:
sup
:`-
1
`\
),
and
the
step
size
(
0.002
ps
).
::
simulation
=
Simulation
(
pdb
.
topology
,
system
,
integrator
)
This
line
combines
the
molecular
topology
,
system
,
and
integrator
to
begin
a
new
simulation
.
It
creates
a
Simulation
object
and
assigns
it
to
a
variable
called
\
:
code
:`
simulation
`\
.
A
Simulation
object
coordinates
all
the
processes
involved
in
running
a
simulation
,
such
as
advancing
time
and
writing
output
.
::
simulation
.
context
.
setPositions
(
pdb
.
positions
)
This
line
specifies
the
initial
atom
positions
for
the
simulation
:
in
this
case
,
the
positions
that
were
loaded
from
the
PDB
file
.
::
simulation
.
minimizeEnergy
()
This
line
tells
OpenMM
to
perform
a
local
energy
minimization
.
It
is
usually
a
good
idea
to
do
this
at
the
start
of
a
simulation
,
since
the
coordinates
in
the
PDB
file
might
produce
very
large
forces
.
::
simulation
.
reporters
.
append
(
PDBReporter
(
'output.pdb'
,
1000
))
This
line
creates
a
“
reporter
”
to
generate
output
during
the
simulation
,
and
adds
it
to
the
Simulation
object
’
s
list
of
reporters
.
A
PDBReporter
writes
structures
to
a
PDB
file
.
We
specify
that
the
output
file
should
be
called
“
output
.
pdb
”
,
and
that
a
structure
should
be
written
every
1000
time
steps
.
::
simulation
.
reporters
.
append
(
StateDataReporter
(
stdout
,
1000
,
step
=
True
,
potentialEnergy
=
True
,
temperature
=
True
))
It
can
be
useful
to
get
regular
status
reports
as
a
simulation
runs
so
you
can
monitor
its
progress
.
This
line
adds
another
reporter
to
print
out
some
basic
information
every
1000
time
steps
:
the
current
step
index
,
the
potential
energy
of
the
system
,
and
the
temperature
.
We
specify
:
code
:`
stdout
`
(
not
in
quotes
)
as
the
output
file
,
which
means
to
write
the
results
to
the
console
.
We
also
could
have
given
a
file
name
(
in
quotes
),
just
as
we
did
for
the
PDBReporter
,
to
write
the
information
to
a
file
.
::
simulation
.
step
(
10000
)
Finally
,
we
run
the
simulation
,
integrating
the
equations
of
motion
for
10
,
000
time
steps
.
Once
it
is
finished
,
you
can
load
the
PDB
file
into
any
program
you
want
for
analysis
and
visualization
(
VMD
,
PyMol
,
AmberTools
,
etc
.).
..
_using_amber_files
:
Using
AMBER
Files
*****************
OpenMM
can
build
a
system
in
several
different
ways
.
One
option
,
as
shown
above
,
is
to
start
with
a
PDB
file
and
then
select
a
force
field
with
which
to
model
it
.
Alternatively
,
you
can
use
AmberTools
to
model
your
system
.
In
that
case
,
you
provide
a
prmtop
file
and
an
inpcrd
file
.
OpenMM
loads
the
files
and
creates
a
system
from
them
.
This
is
shown
in
the
following
script
.
It
can
be
found
in
OpenMM
’
s
“
examples
”
folder
with
the
name
“
simulateAmber
.
py
”
.
..
samepage
::
::
from
simtk
.
openmm
.
app
import
*
from
simtk
.
openmm
import
*
from
simtk
.
unit
import
*
from
sys
import
stdout
prmtop
=
AmberPrmtopFile
(
'input.prmtop'
)
inpcrd
=
AmberInpcrdFile
(
'input.inpcrd'
)
system
=
prmtop
.
createSystem
(
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
constraints
=
HBonds
)
integrator
=
LangevinIntegrator
(
300
*
kelvin
,
1
/
picosecond
,
0.002
*
picoseconds
)
simulation
=
Simulation
(
prmtop
.
topology
,
system
,
integrator
)
simulation
.
context
.
setPositions
(
inpcrd
.
positions
)
simulation
.
minimizeEnergy
()
simulation
.
reporters
.
append
(
PDBReporter
(
'output.pdb'
,
1000
))
simulation
.
reporters
.
append
(
StateDataReporter
(
stdout
,
1000
,
step
=
True
,
potentialEnergy
=
True
,
temperature
=
True
))
simulation
.
step
(
10000
)
..
caption
::
:
autonumber
:`
Example
,
AMBER
example
`
This
script
is
very
similar
to
the
previous
one
.
There
are
just
a
few
significant
differences
:
::
prmtop
=
AmberPrmtopFile
(
'input.prmtop'
)
inpcrd
=
AmberInpcrdFile
(
'input.inpcrd'
)
In
these
lines
,
we
load
the
prmtop
file
and
inpcrd
file
.
More
precisely
,
we
create
AmberPrmtopFile
and
AmberInpcrdFile
objects
and
assign
them
to
the
variables
:
code
:`
prmtop
`
and
:
code
:`
inpcrd
`\
,
respectively
.
As
before
,
you
can
change
these
lines
to
specify
any
files
you
want
.
Be
sure
to
include
the
single
quotes
around
the
file
names
.
::
system
=
prmtop
.
createSystem
(
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
constraints
=
HBonds
)
This
line
creates
the
system
.
In
the
previous
section
,
we
loaded
the
topology
from
a
PDB
file
and
then
had
the
force
field
create
a
system
based
on
it
.
In
this
case
,
we
don
’
t
need
a
force
field
;
the
prmtop
file
already
contains
the
force
field
parameters
,
so
it
can
create
the
system
directly
.
::
simulation
=
Simulation
(
prmtop
.
topology
,
system
,
integrator
)
simulation
.
context
.
setPositions
(
inpcrd
.
positions
)
Notice
that
we
now
get
the
topology
from
the
prmtop
file
and
the
atom
positions
from
the
inpcrd
file
.
In
the
previous
section
,
both
of
these
came
from
a
PDB
file
,
but
AMBER
puts
the
topology
and
positions
in
separate
files
.
..
_using_gromacs_files
:
Using
Gromacs
Files
*******************
A
third
option
for
creating
your
system
is
to
use
the
Gromacs
setup
tools
.
They
produce
a
gro
file
containing
the
coordinates
and
a
top
file
containing
the
topology
.
OpenMM
can
load
these
exactly
as
it
did
the
AMBER
files
.
This
is
shown
in
the
following
script
.
It
can
be
found
in
OpenMM
’
s
“
examples
”
folder
with
the
name
“
simulateGromacs
.
py
”
.
..
samepage
::
::
from
simtk
.
openmm
.
app
import
*
from
simtk
.
openmm
import
*
from
simtk
.
unit
import
*
from
sys
import
stdout
gro
=
GromacsGroFile
(
'input.gro'
)
top
=
GromacsTopFile
(
'input.top'
,
unitCellDimensions
=
gro
.
getUnitCellDimensions
(),
includeDir
=
'/usr/local/gromacs/share/gromacs/top'
)
system
=
top
.
createSystem
(
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
constraints
=
HBonds
)
integrator
=
LangevinIntegrator
(
300
*
kelvin
,
1
/
picosecond
,
0.002
*
picoseconds
)
simulation
=
Simulation
(
top
.
topology
,
system
,
integrator
)
simulation
.
context
.
setPositions
(
gro
.
positions
)
simulation
.
minimizeEnergy
()
simulation
.
reporters
.
append
(
PDBReporter
(
'output.pdb'
,
1000
))
simulation
.
reporters
.
append
(
StateDataReporter
(
stdout
,
1000
,
step
=
True
,
potentialEnergy
=
True
,
temperature
=
True
))
simulation
.
step
(
10000
)
..
caption
::
:
autonumber
:`
Example
,
Gromacs
example
`
This
script
is
nearly
identical
to
the
previous
one
,
just
replacing
AmberInpcrdFile
and
AmberPrmtopFile
with
GromacsGroFile
and
GromacsTopFile
.
Note
that
when
we
create
the
GromacsTopFile
,
we
specify
values
for
two
extra
options
.
First
,
we
specify
:
code
:`
unitCellDimensions
=
gro
.
getUnitCellDimensions
()`\
.
Unlike
OpenMM
and
AMBER
,
which
store
the
periodic
unit
cell
dimensions
with
the
topology
,
Gromacs
stores
them
with
the
coordinates
.
To
let
GromacsTopFile
create
a
Topology
object
,
we
therefore
need
to
tell
it
the
unit
cell
dimensions
that
were
loaded
from
the
gro
file
.
You
only
need
to
do
this
if
you
are
simulating
a
periodic
system
.
For
implicit
solvent
simulations
,
it
usually
can
be
omitted
.
Second
,
we
specify
:
code
:`
includeDir
=
'/usr/local/gromacs/share/gromacs/top'
`\
.
Unlike
AMBER
,
which
stores
all
the
force
field
parameters
directly
in
a
prmtop
file
,
Gromacs
just
stores
references
to
force
field
definition
files
that
are
installed
with
the
Gromacs
application
.
OpenMM
needs
to
know
where
to
find
these
files
,
so
the
:
code
:`
includeDir
`
parameter
specifies
the
directory
containing
them
.
If
you
omit
this
parameter
,
OpenMM
will
assume
the
default
location
:
file
:`/
usr
/
local
/
gromacs
/
share
/
gromacs
/
top
`,
which
is
often
where
they
are
installed
on
Unix
-
like
operating
systems
.
So
in
:
numref
:`
Example
,
Gromacs
example
`
we
actually
could
have
omitted
this
parameter
,
but
if
the
Gromacs
files
were
installed
in
any
other
location
,
we
would
need
to
include
it
.
..
_the
-
script
-
builder
-
application
:
The
Script
Builder
Application
******************************
One
option
for
writing
your
own
scripts
is
to
start
with
one
of
the
examples
given
above
(
the
one
in
section
:
ref
:`
a
-
first
-
example
`
if
you
are
starting
from
a
PDB
file
,
section
:
ref
:`
using_amber_files
`
if
you
are
starting
from
AMBER
prmtop
and
inpcrd
files
,
or
section
:
ref
:`
using_gromacs_files
`
if
you
are
starting
from
Gromacs
gro
and
top
files
),
then
customize
it
to
suit
your
needs
.
Another
option
is
to
use
the
OpenMM
Script
Builder
application
.
..
figure
::
../
images
/
ScriptBuilder
.
png
:
align
:
center
:
width
:
100
%
:
autonumber
:`
Figure
,
script
builder
`:
The
Script
Builder
application
This
is
a
web
application
available
at
https
://
builder
.
openmm
.
org
.
It
provides
a
graphical
interface
with
simple
choices
for
all
the
most
common
simulation
options
,
then
automatically
generates
a
script
based
on
them
.
As
you
change
the
settings
,
the
script
is
instantly
updated
to
reflect
them
.
Once
everything
is
set
the
way
you
want
,
click
the
“
Save
Script
”
button
to
save
it
to
disk
,
or
simply
copy
and
paste
it
into
a
text
editor
.
..
_simulation
-
parameters
:
Simulation
Parameters
*********************
Now
let
’
s
consider
lots
of
ways
you
might
want
to
customize
your
script
.
Platforms
=========
When
creating
a
Simulation
,
you
can
optionally
tell
it
what
Platform
to
use
.
OpenMM
includes
four
platforms
:
Reference
,
CPU
,
CUDA
,
and
OpenCL
.
For
a
description
of
the
differences
between
them
,
see
Section
:
ref
:`
platforms
`.
If
you
do
not
specify
a
Platform
,
it
will
select
one
automatically
.
Usually
its
choice
will
be
reasonable
,
but
you
may
want
to
change
it
.
The
following
lines
specify
to
use
the
CUDA
Platform
:
::
platform
=
Platform
.
getPlatformByName
(
'CUDA'
)
simulation
=
Simulation
(
prmtop
.
topology
,
system
,
integrator
,
platform
)
The
Platform
name
should
be
:
code
:`
OpenCL
`\
,
:
code
:`
CUDA
`\
,
:
code
:`
CPU
`\,
or
:
code
:`
Reference
`\
.
You
also
can
specify
Platform
-
specific
properties
that
customize
how
calculations
should
be
done
.
See
Chapter
:
ref
:`
platform
-
specific
-
properties
`
for
details
of
the
properties
that
each
Platform
supports
.
For
example
,
the
following
lines
specify
to
parallelize
work
across
two
different
GPUs
(
CUDA
devices
0
and
1
),
doing
all
computations
in
double
precision
:
::
platform
=
Platform
.
getPlatformByName
(
'CUDA'
)
properties
=
{
'CudaDeviceIndex'
:
'0,1'
,
'CudaPrecision'
:
'double'
}
simulation
=
Simulation
(
prmtop
.
topology
,
system
,
integrator
,
platform
,
properties
)
..
_force
-
fields
:
Force
Fields
============
When
you
create
a
force
field
,
you
specify
one
or
more
XML
files
from
which
to
load
the
force
field
definition
.
Most
often
,
there
will
be
one
file
to
define
the
main
force
field
,
and
possibly
a
second
file
to
define
the
water
model
(
either
implicit
or
explicit
).
For
example
:
::
forcefield
=
ForceField
(
'amber99sb.xml'
,
'tip3p.xml'
)
For
the
main
force
field
,
OpenMM
provides
the
following
options
:
..
tabularcolumns
::
|
l
|
L
|
=====================
================================================================================
File
Force
Field
=====================
================================================================================
amber96
.
xml
AMBER96
\
:
cite
:`
Kollman1997
`
amber99sb
.
xml
AMBER99
\
:
cite
:`
Wang2000
`
with
modified
backbone
torsions
\
:
cite
:`
Hornak2006
`
amber99sbildn
.
xml
AMBER99SB
plus
improved
side
chain
torsions
\
:
cite
:`
Lindorff
-
Larsen2010
`
amber99sbnmr
.
xml
AMBER99SB
with
modifications
to
fit
NMR
data
\
:
cite
:`
Li2010
`
amber03
.
xml
AMBER03
\
:
cite
:`
Duan2003
`
amber10
.
xml
AMBER10
amoeba2009
.
xml
AMOEBA
2009
\
:
cite
:`
Ren2002
`.
This
force
field
is
deprecated
.
It
is
recommended
to
use
AMOEBA
2013
instead
.
amoeba2013
.
xml
AMOEBA
2013
\
:
cite
:`
Shi2013
`
charmm_polar_2013
.
xml
CHARMM
2013
polarizable
force
field
\
:
cite
:`
Lopes2013
`
=====================
================================================================================
The
AMBER
files
do
not
include
parameters
for
water
molecules
.
This
allows
you
to
separately
select
which
water
model
you
want
to
use
.
For
simulations
that
include
explicit
water
molecules
,
you
should
also
specify
one
of
the
following
files
:
..
tabularcolumns
::
|
l
|
L
|
===========
============================================
File
Water
Model
===========
============================================
tip3p
.
xml
TIP3P
water
model
\
:
cite
:`
Jorgensen1983
`
tip3pfb
.
xml
TIP3P
-
FB
water
model
\
:
cite
:`
Wang2014
`
tip4pew
.
xml
TIP4P
-
Ew
water
model
\
:
cite
:`
Horn2004
`
tip4pfb
.
xml
TIP4P
-
FB
water
model
\
:
cite
:`
Wang2014
`
tip5p
.
xml
TIP5P
water
model
\
:
cite
:`
Mahoney2000
`
spce
.
xml
SPC
/
E
water
model
\
:
cite
:`
Berendsen1987
`
swm4ndp
.
xml
SWM4
-
NDP
water
model
\
:
cite
:`
Lamoureux2006
`
===========
============================================
For
the
polarizable
force
fields
(
AMOEBA
and
CHARMM
),
only
one
explicit
water
model
is
currently
available
and
the
water
parameters
are
included
in
the
same
file
as
the
macromolecule
parameters
.
Also
,
the
polarizable
force
fields
only
include
parameters
for
amino
acids
and
ions
,
not
for
nucleic
acids
.
If
you
want
to
include
an
implicit
solvation
model
,
you
can
also
specify
one
of
the
following
files
:
..
tabularcolumns
::
|
l
|
L
|
=================
=================================================================================================
File
Implicit
Solvation
Model
=================
=================================================================================================
amber96_obc
.
xml
GBSA
-
OBC
solvation
model
\
:
cite
:`
Onufriev2004
`
for
use
with
AMBER96
force
field
amber99_obc
.
xml
GBSA
-
OBC
solvation
model
for
use
with
AMBER99
force
fields
amber03_obc
.
xml
GBSA
-
OBC
solvation
model
for
use
with
AMBER03
force
field
amber10_obc
.
xml
GBSA
-
OBC
solvation
model
for
use
with
AMBER10
force
field
amoeba2009_gk
.
xml
Generalized
Kirkwood
solvation
model
\
:
cite
:`
Schnieders2007
`
for
use
with
AMOEBA
2009
force
field
amoeba2013_gk
.
xml
Generalized
Kirkwood
solvation
model
for
use
with
AMOEBA
2013
force
field
=================
=================================================================================================
For
example
,
to
use
the
GBSA
-
OBC
solvation
model
with
the
Amber99SB
force
field
,
you
would
type
:
::
forcefield
=
ForceField
(
'amber99sb.xml'
,
'amber99_obc.xml'
)
If
you
are
running
a
vacuum
simulation
,
you
do
not
need
to
specify
a
water
model
.
The
following
line
specifies
the
AMBER10
force
field
and
no
water
model
.
If
you
try
to
use
it
with
a
PDB
file
that
contains
explicit
water
,
it
will
produce
an
error
since
no
water
parameters
are
defined
:
::
forcefield
=
ForceField
(
'amber10.xml'
)
AMBER
Implicit
Solvent
======================
When
creating
a
system
from
a
prmtop
file
you
do
not
specify
force
field
files
,
so
you
need
a
different
way
to
tell
it
to
use
implicit
solvent
.
This
is
done
with
the
:
code
:`
implicitSolvent
`
parameter
:
::
system
=
prmtop
.
createSystem
(
implicitSolvent
=
OBC2
)
OpenMM
supports
most
of
the
implicit
solvent
models
used
by
AMBER
.
Here
are
the
allowed
values
for
:
code
:`
implicitSolvent
`\
:
..
tabularcolumns
::
|
l
|
L
|
=====
==================================================================================================================================
Value
Meaning
=====
==================================================================================================================================
None
No
implicit
solvent
is
used
.
HCT
Hawkins
-
Cramer
-
Truhlar
GBSA
model
\
:
cite
:`
Hawkins1995
`
(
corresponds
to
igb
=
1
in
AMBER
)
OBC1
Onufriev
-
Bashford
-
Case
GBSA
model
\
:
cite
:`
Onufriev2004
`
using
the
GB
\
:
sup
:`
OBC
`\
I
parameters
(
corresponds
to
igb
=
2
in
AMBER
).
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
`.
GBn
GBn
solvation
model
\
:
cite
:`
Mongan2007
`
(
corresponds
to
igb
=
7
in
AMBER
).
GBn2
GBn2
solvation
model
\
:
cite
:`
Nguyen2013
`
(
corresponds
to
igb
=
8
in
AMBER
).
=====
==================================================================================================================================
You
can
further
control
the
solvation
model
in
a
few
ways
.
First
,
you
can
specify
the
dielectric
constants
to
use
for
the
solute
and
solvent
:
::
system
=
prmtop
.
createSystem
(
implicitSolvent
=
OBC2
,
soluteDielectric
=
2.0
,
solventDielectric
=
80.0
)
If
they
are
not
specified
,
the
solute
and
solvent
dielectrics
default
to
1.0
and
78.5
,
respectively
.
These
values
were
chosen
for
consistency
with
AMBER
,
and
are
slightly
different
from
those
used
elsewhere
in
OpenMM
:
when
building
a
system
from
a
force
field
,
the
solvent
dielectric
defaults
to
78.3
.
You
also
can
model
the
effect
of
a
non
-
zero
salt
concentration
by
specifying
the
Debye
screening
parameter
:
::
system
=
prmtop
.
createSystem
(
implicitSolvent
=
OBC2
,
implicitSolventKappa
=
1.0
/
nanometer
)
Nonbonded
Interactions
======================
When
creating
the
system
(
either
from
a
force
field
or
a
prmtop
file
),
you
can
specify
options
about
how
nonbonded
interactions
should
be
treated
:
::
system
=
prmtop
.
createSystem
(
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
)
The
:
code
:`
nonbondedMethod
`
parameter
can
have
any
of
the
following
values
:
..
tabularcolumns
::
|
l
|
L
|
=================
===========================================================================================================================================================================================================================================
Value
Meaning
=================
===========================================================================================================================================================================================================================================
NoCutoff
No
cutoff
is
applied
.
CutoffNonPeriodic
The
reaction
field
method
is
used
to
eliminate
all
interactions
beyond
a
cutoff
distance
.
Not
valid
for
AMOEBA
.
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
.
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
.
PME
Periodic
boundary
conditions
are
applied
.
The
Particle
Mesh
Ewald
method
is
used
to
compute
long
range
interactions
.
=================
===========================================================================================================================================================================================================================================
When
using
any
method
other
than
:
code
:`
NoCutoff
`\
,
you
should
also
specify
a
cutoff
distance
.
Be
sure
to
specify
units
,
as
shown
in
the
examples
above
.
For
example
,
:
code
:`
nonbondedCutoff
=
1.5
*
nanometers
`
or
:
code
:`
nonbondedCutoff
=
12
*
angstroms
`
are
legal
values
.
When
using
:
code
:`
Ewald
`
or
:
code
:`
PME
`\
,
you
can
optionally
specify
an
error
tolerance
for
the
force
computation
.
For
example
:
::
system
=
prmtop
.
createSystem
(
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
ewaldErrorTolerance
=
0.00001
)
The
error
tolerance
is
roughly
equal
to
the
fractional
error
in
the
forces
due
to
truncating
the
Ewald
summation
.
If
you
do
not
specify
it
,
a
default
value
of
0.0005
is
used
.
Nonbonded
Forces
for
AMOEBA
---------------------------
For
the
AMOEBA
force
field
,
the
valid
values
for
the
:
code
:`
nonbondedMethod
`
are
:
code
:`
NoCutoff
`
and
:
code
:`
PME
`\
.
The
other
nonbonded
methods
,
:
code
:`
CutoffNonPeriodic
`\
,
:
code
:`
CutoffPeriodic
`\
,
and
:
code
:`
Ewald
`
are
unavailable
for
this
force
field
.
For
implicit
solvent
runs
using
AMOEBA
,
only
the
:
code
:`
nonbondedMethod
`
option
:
code
:`
NoCutoff
`
is
available
.
Lennard
-
Jones
Interaction
Cutoff
Value
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In
addition
,
for
the
AMOEBA
force
field
a
cutoff
for
the
Lennard
-
Jones
interaction
independent
of
the
value
used
for
the
electrostatic
interactions
may
be
specified
using
the
keyword
:
code
:`
vdwCutoff
`\
.
::
system
=
forcefield
.
createSystem
(
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
ewaldErrorTolerance
=
0.00001
,
vdwCutoff
=
1.2
*
nanometer
)
If
:
code
:`
vdwCutoff
`
is
not
specified
,
then
the
value
of
:
code
:`
nonbondedCutoff
`
is
used
for
the
Lennard
-
Jones
interactions
.
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.00001
.
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
:
::
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
,
ewaldErrorTolerance
=
0.00001
,
vdwCutoff
=
1.2
*
nanometer
,
polarization
=
'direct'
)
Implicit
Solvent
and
Solute
Dielectrics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For
implicit
solvent
simulations
using
the
AMOEBA
force
field
,
the
'amoeba2009_gk.xml'
file
should
be
included
in
the
initialization
of
the
force
field
:
::
forcefield
=
ForceField
(
'amoeba2009.xml'
,
'amoeba2009_gk.xml'
)
Only
the
:
code
:`
nonbondedMethod
`
option
:
code
:`
NoCutoff
`
is
available
for
implicit
solvent
runs
using
AMOEBA
.
In
addition
,
the
solvent
and
solute
dielectric
values
can
be
specified
for
implicit
solvent
simulations
:
::
system
=
forcefield
.
createSystem
(
nonbondedMethod
=
NoCutoff
,
soluteDielectric
=
2.0
,
solventDielectric
=
80.0
)
The
default
values
are
1.0
for
the
solute
dielectric
and
78.3
for
the
solvent
dielectric
.
Constraints
===========
When
creating
the
system
(
either
from
a
force
field
or
a
prmtop
file
),
you
can
optionally
tell
OpenMM
to
constrain
certain
bond
lengths
and
angles
.
For
example
,
::
system
=
prmtop
.
createSystem
(
nonbondedMethod
=
NoCutoff
,
constraints
=
HBonds
)
The
:
code
:`
constraints
`
parameter
can
have
any
of
the
following
values
:
..
tabularcolumns
::
|
l
|
L
|
========
=============================================================================================================================================
Value
Meaning
========
=============================================================================================================================================
None
No
constraints
are
applied
.
This
is
the
default
value
.
HBonds
The
lengths
of
all
bonds
that
involve
a
hydrogen
atom
are
constrained
.
AllBonds
The
lengths
of
all
bonds
are
constrained
.
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
.
========
=============================================================================================================================================
The
main
reason
to
use
constraints
is
that
it
allows
one
to
use
a
larger
integration
time
step
.
With
no
constraints
,
one
is
typically
limited
to
a
time
step
of
about
1
fs
.
With
:
code
:`
HBonds
`
constraints
,
this
can
be
increased
to
about
2
fs
.
With
:
code
:`
HAngles
`\
,
it
can
be
further
increased
to
3.5
or
4
fs
.
Regardless
of
the
value
of
this
parameter
,
OpenMM
makes
water
molecules
completely
rigid
,
constraining
both
their
bond
lengths
and
angles
.
You
can
disable
this
behavior
with
the
:
code
:`
rigidWater
`
parameter
:
::
system
=
prmtop
.
createSystem
(
nonbondedMethod
=
NoCutoff
,
constraints
=
None
,
rigidWater
=
False
)
Be
aware
that
flexible
water
may
require
you
to
further
reduce
the
integration
step
size
,
typically
to
about
0.5
fs
.
Heavy
Hydrogens
===============
When
creating
the
system
(
either
from
a
force
field
or
a
prmtop
file
),
you
can
optionally
tell
OpenMM
to
increase
the
mass
of
hydrogen
atoms
.
For
example
,
::
system
=
prmtop
.
createSystem
(
hydrogenMass
=
4
*
amu
)
This
applies
only
to
hydrogens
that
are
bonded
to
heavy
atoms
,
and
any
mass
added
to
the
hydrogen
is
subtracted
from
the
heavy
atom
.
This
keeps
their
total
mass
constant
while
slowing
down
the
fast
motions
of
hydrogens
.
When
combined
with
constraints
(
typically
:
code
:`
constraints
=
AllBonds
`\
),
this
allows
a
further
increase
in
integration
step
size
.
Integrators
===========
OpenMM
offers
a
choice
of
several
different
integration
methods
.
You
select
which
one
to
use
by
creating
an
integrator
object
of
the
appropriate
type
.
Langevin
Integrator
-------------------
In
the
examples
of
the
previous
sections
,
we
used
Langevin
integration
:
::
integrator
=
LangevinIntegrator
(
300
*
kelvin
,
1
/
picosecond
,
0.002
*
picoseconds
)
The
three
parameter
values
in
this
line
are
the
simulation
temperature
(
300
K
),
the
friction
coefficient
(
1
ps
\
:
sup
:`-
1
`\
),
and
the
step
size
(
0.002
ps
).
You
are
free
to
change
these
to
whatever
values
you
want
.
Be
sure
to
specify
units
on
all
values
.
For
example
,
the
step
size
could
be
written
either
as
:
code
:`
0.002
*
picoseconds
`
or
:
code
:`
2
*
femtoseconds
`\
.
They
are
exactly
equivalent
.
Leapfrog
Verlet
Integrator
--------------------------
A
leapfrog
Verlet
integrator
can
be
used
for
running
constant
energy
dynamics
.
The
command
for
this
is
:
::
integrator
=
VerletIntegrator
(
0.002
*
picoseconds
)
The
only
option
is
the
step
size
.
Brownian
Integrator
-------------------
Brownian
(
diffusive
)
dynamics
can
be
used
by
specifying
the
following
:
::
integrator
=
BrownianIntegrator
(
300
*
kelvin
,
1
/
picosecond
,
0.002
*
picoseconds
)
The
parameters
are
the
same
as
for
Langevin
dynamics
:
temperature
(
300
K
),
friction
coefficient
(
1
ps
\
:
sup
:`-
1
`\
),
and
step
size
(
0.002
ps
).
Variable
Time
Step
Langevin
Integrator
--------------------------------------
A
variable
time
step
Langevin
integrator
continuously
adjusts
its
step
size
to
keep
the
integration
error
below
a
specified
tolerance
.
In
some
cases
,
this
can
allow
you
to
use
a
larger
average
step
size
than
would
be
possible
with
a
fixed
step
size
integrator
.
It
also
is
very
useful
in
cases
where
you
do
not
know
in
advance
what
step
size
will
be
stable
,
such
as
when
first
equilibrating
a
system
.
You
create
this
integrator
with
the
following
command
:
::
integrator
=
VariableLangevinIntegrator
(
300
*
kelvin
,
1
/
picosecond
,
0.001
)
In
place
of
a
step
size
,
you
specify
an
integration
error
tolerance
(
0.001
in
this
example
).
It
is
best
not
to
think
of
this
value
as
having
any
absolute
meaning
.
Just
think
of
it
as
an
adjustable
parameter
that
affects
the
step
size
and
integration
accuracy
.
Smaller
values
will
produce
a
smaller
average
step
size
.
You
should
try
different
values
to
find
the
largest
one
that
produces
a
trajectory
sufficiently
accurate
for
your
purposes
.
Variable
Time
Step
Leapfrog
Verlet
Integrator
---------------------------------------------
A
variable
time
step
leapfrog
Verlet
integrator
works
similarly
to
the
variable
time
step
Langevin
integrator
in
that
it
continuously
adjusts
its
step
size
to
keep
the
integration
error
below
a
specified
tolerance
.
The
command
for
this
integrator
is
:
::
integrator
=
VariableVerletIntegrator
(
0.001
)
The
parameter
is
the
integration
error
tolerance
(
0.001
),
whose
meaning
is
the
same
as
for
the
Langevin
integrator
.
Temperature
Coupling
====================
If
you
want
to
run
a
simulation
at
constant
temperature
,
using
a
Langevin
integrator
(
as
shown
in
the
examples
above
)
is
usually
the
best
way
to
do
it
.
OpenMM
does
provide
an
alternative
,
however
:
you
can
use
a
Verlet
integrator
,
then
add
an
Andersen
thermostat
to
your
system
to
provide
temperature
coupling
.
To
do
this
,
add
a
single
line
to
the
script
as
shown
below
.
(
The
lines
in
grey
are
just
for
context
.)
::
...
system
=
prmtop
.
createSystem
(
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
constraints
=
HBonds
)
system
.
addForce
(
AndersenThermostat
(
300
*
kelvin
,
1
/
picosecond
))
integrator
=
VerletIntegrator
(
0.002
*
picoseconds
)
...
The
two
parameters
of
the
Andersen
thermostat
are
the
temperature
(
300
K
)
and
collision
frequency
(
1
ps
\
:
sup
:`-
1
`\
).
Pressure
Coupling
=================
All
the
examples
so
far
have
been
constant
volume
simulations
.
If
you
want
to
run
at
constant
pressure
instead
,
add
a
Monte
Carlo
barostat
to
your
system
.
You
do
this
exactly
the
same
way
you
added
the
Andersen
thermostat
in
the
previous
section
:
::
...
system
=
prmtop
.
createSystem
(
nonbondedMethod
=
PME
,
nonbondedCutoff
=
1
*
nanometer
,
constraints
=
HBonds
)
system
.
addForce
(
MonteCarloBarostat
(
1
*
bar
,
300
*
kelvin
))
integrator
=
LangevinIntegrator
(
300
*
kelvin
,
1
/
picosecond
,
0.002
*
picoseconds
)
...
The
parameters
of
the
Monte
Carlo
barostat
are
the
pressure
(
1
bar
)
and
temperature
(
300
K
).
The
barostat
assumes
the
simulation
is
being
run
at
constant
temperature
,
but
it
does
not
itself
do
anything
to
regulate
the
temperature
.
..
warning
::
It
is
therefore
critical
that
you
always
use
it
along
with
a
Langevin
integrator
or
Andersen
thermostat
,
and
that
you
specify
the
same
temperature
for
both
the
barostat
and
the
integrator
or
thermostat
.
Otherwise
,
you
will
get
incorrect
results
.
There
also
is
an
anisotropic
barostat
that
scales
each
axis
of
the
periodic
box
independently
,
allowing
it
to
change
shape
.
When
using
the
anisotropic
barostat
,
you
can
specify
a
different
pressure
for
each
axis
.
The
following
line
applies
a
pressure
of
1
bar
along
the
X
and
Y
axes
,
but
a
pressure
of
2
bar
along
the
Z
axis
:
::
system
.
addForce
(
MonteCarloAnisotropicBarostat
((
1
,
1
,
2
)*
bar
,
300
*
kelvin
))
Another
feature
of
the
anisotropic
barostat
is
that
it
can
be
applied
to
only
certain
axes
of
the
periodic
box
,
keeping
the
size
of
the
other
axes
fixed
.
This
is
done
by
passing
three
additional
parameters
that
specify
whether
the
barostat
should
be
applied
to
each
axis
.
The
following
line
specifies
that
the
X
and
Z
axes
of
the
periodic
box
should
not
be
scaled
,
so
only
the
Y
axis
can
change
size
.
::
system
.
addForce
(
MonteCarloAnisotropicBarostat
((
1
,
1
,
1
)*
bar
,
300
*
kelvin
,
False
,
True
,
False
))
Energy
Minimization
===================
As
seen
in
the
examples
,
performing
a
local
energy
minimization
takes
a
single
line
in
the
script
:
::
simulation
.
minimizeEnergy
()
In
most
cases
,
that
is
all
you
need
.
There
are
two
optional
parameters
you
can
specify
if
you
want
further
control
over
the
minimization
.
First
,
you
can
specify
a
tolerance
for
when
the
energy
should
be
considered
to
have
converged
:
::
simulation
.
minimizeEnergy
(
tolerance
=
10
*
kilojoule
/
mole
)
If
you
do
not
specify
this
parameter
,
a
default
tolerance
of
1
kJ
/
mole
is
used
.
Second
,
you
can
specify
a
maximum
number
of
iterations
:
::
simulation
.
minimizeEnergy
(
maxIterations
=
100
)
The
minimizer
will
exit
once
the
specified
number
of
iterations
is
reached
,
even
if
the
energy
has
not
yet
converged
.
If
you
do
not
specify
this
parameter
,
the
minimizer
will
continue
until
convergence
is
reached
,
no
matter
how
many
iterations
it
takes
.
These
options
are
independent
.
You
can
specify
both
if
you
want
:
::
simulation
.
minimizeEnergy
(
tolerance
=
0.1
*
kilojoule
/
mole
,
maxIterations
=
500
)
Removing
Center
of
Mass
Motion
==============================
By
default
,
OpenMM
removes
all
center
of
mass
motion
at
every
time
step
so
the
system
as
a
whole
does
not
drift
with
time
.
This
is
almost
always
what
you
want
.
In
rare
situations
,
you
may
want
to
allow
the
system
to
drift
with
time
.
You
can
do
this
by
specifying
the
:
code
:`
removeCMMotion
`
parameter
when
you
create
the
System
:
::
system
=
forcefield
.
createSystem
(
pdb
.
topology
,
nonbondedMethod
=
NoCutoff
,
removeCMMotion
=
False
)
Writing
Trajectories
====================
OpenMM
can
save
simulation
trajectories
to
disk
in
two
formats
:
PDB
and
DCD
.
Both
of
these
are
widely
supported
formats
,
so
you
should
be
able
to
read
them
into
most
analysis
and
visualization
programs
.
To
save
a
trajectory
,
just
add
a
“
reporter
”
to
the
simulation
,
as
shown
in
the
example
scripts
above
:
::
simulation
.
reporters
.
append
(
PDBReporter
(
'output.pdb'
,
1000
))
The
two
parameters
of
the
PDBReporter
are
the
output
filename
and
how
often
(
in
number
of
time
steps
)
output
structures
should
be
written
.
To
use
DCD
format
,
just
replace
“
PDBReporter
”
with
“
DCDReporter
”
.
The
parameters
represent
the
same
values
:
::
simulation
.
reporters
.
append
(
DCDReporter
(
'output.dcd'
,
1000
))
Recording
Other
Data
====================
In
addition
to
saving
a
trajectory
,
you
may
want
to
record
other
information
over
the
course
of
a
simulation
,
such
as
the
potential
energy
or
temperature
.
OpenMM
provides
a
reporter
for
this
purpose
also
.
Create
a
StateDataReporter
and
add
it
to
the
simulation
:
::
simulation
.
reporters
.
append
(
StateDataReporter
(
'data.csv'
,
1000
,
time
=
True
,
kineticEnergy
=
True
,
potentialEnergy
=
True
))
The
first
two
parameters
are
the
output
filename
and
how
often
(
in
number
of
time
steps
)
values
should
be
written
.
The
remaining
arguments
specify
what
values
should
be
written
at
each
report
.
The
available
options
are
:
code
:`
step
`
(
the
index
of
the
current
time
step
),
:
code
:`
time
`\
,
:
code
:`
progress
`
(
what
percentage
of
the
simulation
has
completed
),
:
code
:`
remainingTime
`
(
an
estimate
of
how
long
it
will
take
the
simulation
to
complete
),
:
code
:`
potentialEnergy
`\
,
:
code
:`
kineticEnergy
`\
,
:
code
:`
totalEnergy
`\
,
:
code
:`
temperature
`\
,
:
code
:`
volume
`
(
the
volume
of
the
periodic
box
),
:
code
:`
density
`
(
the
total
system
mass
divided
by
the
volume
of
the
periodic
box
),
and
:
code
:`
speed
`
(
an
estimate
of
how
quickly
the
simulation
is
running
).
If
you
include
either
the
:
code
:`
progress
`
or
:
code
:`
remainingTime
`
option
,
you
must
also
include
the
:
code
:`
totalSteps
`
parameter
to
specify
the
total
number
of
time
steps
that
will
be
included
in
the
simulation
.
One
line
is
written
to
the
file
for
each
report
containing
the
requested
values
.
By
default
the
values
are
written
in
comma
-
separated
-
value
(
CSV
)
format
.
You
can
use
the
:
code
:`
separator
`
parameter
to
choose
a
different
separator
.
For
example
,
the
following
line
will
cause
values
to
be
separated
by
spaces
instead
of
commas
:
::
simulation
.
reporters
.
append
(
StateDataReporter
(
'data.txt'
,
1000
,
progress
=
True
,
temperature
=
True
,
totalSteps
=
10000
,
separator
=
' '
))
Model
Building
and
Editing
##########################
Sometimes
you
have
a
PDB
file
that
needs
some
work
before
you
can
simulate
it
.
Maybe
it
doesn
’
t
contain
hydrogen
atoms
(
which
is
common
for
structures
determined
by
x
-
ray
crystallography
),
so
you
need
to
add
them
.
Or
perhaps
you
want
to
simulate
the
system
in
explicit
water
,
but
the
PDB
file
doesn
’
t
contain
water
molecules
.
Or
maybe
it
does
contain
water
molecules
,
but
they
contain
the
wrong
number
of
interaction
sites
for
the
water
model
you
want
to
use
.
OpenMM
’
s
Modeller
class
can
fix
problems
such
as
these
.
To
use
it
,
create
a
Modeller
object
,
providing
the
initial
Topology
and
atom
positions
.
You
then
can
invoke
various
modelling
functions
on
it
.
Each
one
modifies
the
system
in
some
way
,
creating
a
new
Topology
and
list
of
positions
.
When
you
are
all
done
,
you
can
retrieve
them
from
the
Modeller
and
use
them
as
the
starting
point
for
your
simulation
:
..
samepage
::
::
...
pdb
=
PDBFile
(
'input.pdb'
)
modeller
=
Modeller
(
pdb
.
topology
,
pdb
.
positions
)
#
...
Call
some
modelling
functions
here
...
system
=
forcefield
.
createSystem
(
modeller
.
topology
,
nonbondedMethod
=
PME
)
simulation
=
Simulation
(
modeller
.
topology
,
system
,
integrator
)
simulation
.
context
.
setPositions
(
modeller
.
positions
)
..
caption
::
:
autonumber
:`
Example
,
Modeller
outline
`
Now
let
’
s
consider
the
particular
functions
you
can
call
.
Adding
Hydrogens
****************
Call
the
addHydrogens
function
to
add
missing
hydrogen
atoms
:
::
modeller
.
addHydrogens
(
forcefield
)
The
force
field
is
needed
to
determine
the
positions
for
the
hydrogen
atoms
.
If
the
system
already
contains
some
hydrogens
but
is
missing
others
,
that
is
fine
.
The
Modeller
will
recognize
the
existing
ones
and
figure
out
which
ones
need
to
be
added
.
Some
residues
can
exist
in
different
protonation
states
depending
on
the
pH
and
on
details
of
the
local
environment
.
By
default
it
assumes
pH
7
,
but
you
can
specify
a
different
value
:
::
modeller
.
addHydrogens
(
forcefield
,
pH
=
5.0
)
For
each
residue
,
it
selects
the
protonation
state
that
is
most
common
at
the
specified
pH
.
In
the
case
of
Cysteine
residues
,
it
also
checks
whether
the
residue
participates
in
a
disulfide
bond
when
selecting
the
state
to
use
.
Histidine
has
two
different
protonation
states
that
are
equally
likely
at
neutral
pH
.
It
therefore
selects
which
one
to
use
based
on
which
will
form
a
better
hydrogen
bond
.
If
you
want
more
control
,
it
is
possible
to
specify
exactly
which
protonation
state
to
use
for
particular
residues
.
For
details
,
consult
the
API
documentation
for
the
Modeller
class
.
Adding
Solvent
**************
Call
addSolvent
to
create
a
box
of
solvent
(
water
and
ions
)
around
the
model
:
::
modeller
.
addSolvent
(
forcefield
)
This
constructs
a
box
of
water
around
the
solute
,
ensuring
that
no
water
molecule
comes
closer
to
any
solute
atom
than
the
sum
of
their
van
der
Waals
radii
.
It
also
determines
the
charge
of
the
solute
,
and
adds
enough
positive
or
negative
ions
to
make
the
system
neutral
.
When
called
as
shown
above
,
addSolvent
expects
that
periodic
box
dimensions
were
specified
in
the
PDB
file
,
and
it
uses
them
as
the
size
for
the
water
box
.
If
your
PDB
file
does
not
specify
a
box
size
,
or
if
you
want
to
use
a
different
size
,
you
can
specify
one
:
::
modeller
.
addSolvent
(
forcefield
,
boxSize
=
Vec3
(
5.0
,
3.5
,
3.5
)*
nanometers
)
This
requests
a
5
nm
by
3.5
nm
by
3.5
nm
box
.
Another
option
is
to
specify
a
padding
distance
:
::
modeller
.
addSolvent
(
forcefield
,
padding
=
1.0
*
nanometers
)
This
determines
the
largest
size
of
the
solute
along
any
axis
(
x
,
y
,
or
z
).
It
then
creates
a
cubic
box
of
width
(
solute
size
)+
2
*(
padding
).
The
above
line
guarantees
that
no
part
of
the
solute
comes
closer
than
1
nm
to
any
edge
of
the
box
.
By
default
,
addSolvent
creates
TIP3P
water
molecules
,
but
it
also
supports
other
water
models
:
::
modeller
.
addSolvent
(
forcefield
,
model
=
'tip5p'
)
Allowed
values
for
the
:
code
:`
model
`
option
are
'tip3p'
,
'tip3pfb'
,
'spce'
,
'tip4pew'
,
'tip4pfb'
,
and
'tip5p'
.
Be
sure
to
include
the
single
quotes
around
the
value
.
Another
option
is
to
add
extra
ion
pairs
to
give
a
desired
total
ionic
strength
.
For
example
:
::
modeller
.
addSolvent
(
forcefield
,
ionicStrength
=
0.1
*
molar
)
This
solvates
the
system
with
a
salt
solution
whose
ionic
strength
is
0.1
molar
.
Note
that
when
computing
the
ionic
strength
,
it
does
*
not
*
consider
the
ions
that
were
added
to
neutralize
the
solute
.
It
assumes
those
are
bound
to
the
solute
and
do
not
contribute
to
the
bulk
ionic
strength
.
By
default
,
Na
\
:
sup
:`+`
and
Cl
\
:
sup
:`-`
ions
are
used
,
but
you
can
specify
different
ones
using
the
:
code
:`
positiveIon
`
and
:
code
:`
negativeIon
`
options
.
For
example
,
this
creates
a
potassium
chloride
solution
:
::
modeller
.
addSolvent
(
forcefield
,
ionicStrength
=
0.1
*
molar
,
positiveIon
=
'K+'
)
Allowed
values
for
:
code
:`
positiveIon
`
are
'Cs+'
,
'K+'
,
'Li+'
,
'Na+'
,
and
'Rb+'
.
Allowed
values
for
:
code
:`
negativeIon
`
are
'Cl-'
,
'Br-'
,
'F-'
,
and
'I-'
.
Be
sure
to
include
the
single
quotes
around
the
value
.
Also
be
aware
some
force
fields
do
not
include
parameters
for
all
of
these
ion
types
,
so
you
need
to
use
types
that
are
supported
by
your
chosen
force
field
.
Adding
or
Removing
Extra
Particles
**********************************
“
Extra
particles
”
are
particles
that
do
not
represent
ordinary
atoms
.
This
includes
the
virtual
interaction
sites
used
in
many
water
models
,
Drude
particles
,
etc
.
If
you
are
using
a
force
field
that
involves
extra
particles
,
you
must
add
them
to
the
Topology
.
To
do
this
,
call
:
::
modeller
.
addExtraParticles
(
forcefield
)
This
looks
at
the
force
field
to
determine
what
extra
particles
are
needed
,
then
modifies
each
residue
to
include
them
.
This
function
can
remove
extra
particles
as
well
as
adding
them
.
Removing
Water
**************
Call
deleteWater
to
remove
all
water
molecules
from
the
system
:
::
modeller
.
deleteWater
()
This
is
useful
,
for
example
,
if
you
want
to
simulate
it
with
implicit
solvent
.
Be
aware
,
though
,
that
this
only
removes
water
molecules
,
not
ions
or
other
small
molecules
that
might
be
considered
“
solvent
”
.
Saving
The
Results
******************
Once
you
have
finished
editing
your
model
,
you
can
immediately
use
the
resulting
Topology
and
atom
positions
as
the
input
to
a
Simulation
.
If
you
plan
to
simulate
it
many
times
,
though
,
it
is
usually
better
to
save
the
result
to
a
new
PDB
file
,
then
use
that
as
the
input
for
the
simulations
.
This
avoids
the
cost
of
repeating
the
modeling
operations
at
the
start
of
every
simulation
,
and
also
ensures
that
all
your
simulations
are
really
starting
from
exactly
the
same
structure
.
The
following
example
loads
a
PDB
file
,
adds
missing
hydrogens
,
builds
a
solvent
box
around
it
,
performs
an
energy
minimization
,
and
saves
the
result
to
a
new
PDB
file
.
..
samepage
::
::
from
simtk
.
openmm
.
app
import
*
from
simtk
.
openmm
import
*
from
simtk
.
unit
import
*
print
(
'Loading...'
)
pdb
=
PDBFile
(
'input.pdb'
)
forcefield
=
ForceField
(
'amber99sb.xml'
,
'tip3p.xml'
)
modeller
=
Modeller
(
pdb
.
topology
,
pdb
.
positions
)
print
(
'Adding hydrogens...'
)
modeller
.
addHydrogens
(
forcefield
)
print
(
'Adding solvent...'
)
modeller
.
addSolvent
(
forcefield
,
model
=
'tip3p'
,
padding
=
1
*
nanometer
)
print
(
'Minimizing...'
)
system
=
forcefield
.
createSystem
(
modeller
.
topology
,
nonbondedMethod
=
PME
)
integrator
=
VerletIntegrator
(
0.001
*
picoseconds
)
simulation
=
Simulation
(
modeller
.
topology
,
system
,
integrator
)
simulation
.
context
.
setPositions
(
modeller
.
positions
)
simulation
.
minimizeEnergy
(
maxIterations
=
100
)
print
(
'Saving...'
)
positions
=
simulation
.
context
.
getState
(
getPositions
=
True
).
getPositions
()
PDBFile
.
writeFile
(
simulation
.
topology
,
positions
,
open
(
'output.pdb'
,
'w'
))
print
(
'Done'
)
..
caption
::
:
autonumber
:`
Example
,
Modeller
complete
`
Advanced
Simulation
Examples
############################
In
the
previous
chapter
,
we
looked
at
some
basic
scripts
for
running
simulations
and
saw
lots
of
ways
to
customize
them
.
If
that
is
all
you
want
to
do
—
run
straightforward
molecular
simulations
—
you
already
know
everything
you
need
to
know
.
Just
use
the
example
scripts
and
customize
them
in
the
ways
described
in
section
:
ref
:`
simulation
-
parameters
`.
OpenMM
can
do
far
more
than
that
.
Your
script
has
the
full
OpenMM
API
at
its
disposal
,
along
with
all
the
power
of
the
Python
language
and
libraries
.
In
this
chapter
,
we
will
consider
some
examples
that
illustrate
more
advanced
techniques
.
Remember
that
these
are
still
only
examples
;
it
would
be
impossible
to
give
an
exhaustive
list
of
everything
OpenMM
can
do
.
Hopefully
they
will
give
you
a
sense
of
what
is
possible
,
and
inspire
you
to
experiment
further
on
your
own
.
Starting
in
this
section
,
we
will
assume
some
knowledge
of
programming
,
as
well
as
familiarity
with
the
OpenMM
API
.
Consult
the
OpenMM
Users
Guide
and
API
documentation
if
you
are
uncertain
about
how
something
works
.
You
can
also
use
the
Python
“
help
”
command
.
For
example
,
::
help
(
Simulation
)
will
print
detailed
documentation
on
the
Simulation
class
.
Simulated
Annealing
*******************
Here
is
a
very
simple
example
of
how
to
do
simulated
annealing
.
The
following
lines
linearly
reduce
the
temperature
from
300
K
to
0
K
in
100
increments
,
executing
1000
time
steps
at
each
temperature
:
..
samepage
::
::
...
simulation
.
context
.
setPositions
(
pdb
.
positions
)
simulation
.
minimizeEnergy
()
for
i
in
range
(
100
):
integrator
.
setTemperature
(
3
*(
100
-
i
)*
kelvin
)
simulation
.
step
(
1000
)
..
caption
::
:
autonumber
:`
Example
,
simulated
annealing
`
This
code
needs
very
little
explanation
.
The
loop
is
executed
100
times
.
Each
time
through
,
it
adjusts
the
temperature
of
the
LangevinIntegrator
and
then
calls
:
code
:`
step
(
1000
)`
to
take
1000
time
steps
.
Applying
an
External
Force
to
Particles
:
a
Spherical
Container
**************************************************************
In
this
example
,
we
will
simulate
a
non
-
periodic
system
contained
inside
a
spherical
container
with
radius
2
nm
.
We
implement
the
container
by
applying
a
harmonic
potential
to
every
particle
:
..
math
::
\
begin
{
array
}{
lll
}
E
(
r
)
=
&
0
&
r
\
le2
\\
&
100
(
r
-
2
)^
2
&
r
>
2
\
end
{
array
}
where
*
r
*
is
the
distance
of
the
particle
from
the
origin
,
measured
in
nm
.
We
can
easily
do
this
using
OpenMM
’
s
CustomExternalForce
class
.
This
class
applies
a
force
to
some
or
all
of
the
particles
in
the
system
,
where
the
energy
is
an
arbitrary
function
of
each
particle
’
s
(\
*
x
*\
,
*
y
*\
,
*
z
*\
)
coordinates
.
Here
is
the
code
to
do
it
:
..
samepage
::
::
...
system
=
forcefield
.
createSystem
(
pdb
.
topology
,
nonbondedMethod
=
CutoffNonPeriodic
,
nonbondedCutoff
=
1
*
nanometer
,
constraints
=
None
)
force
=
CustomExternalForce
(
'100*max(0, r-2)^2; r=sqrt(x*x+y*y+z*z)'
)
system
.
addForce
(
force
)
for
i
in
range
(
system
.
getNumParticles
()):
force
.
addParticle
(
i
,
[])
integrator
=
LangevinIntegrator
(
300
*
kelvin
,
91
/
picosecond
,
0.002
*
picoseconds
)
...
..
caption
::
:
autonumber
:`
Example
,
spherical
container
`
The
first
thing
it
does
is
create
a
CustomExternalForce
object
and
add
it
to
the
System
.
The
argument
to
CustomExternalForce
is
a
mathematical
expression
specifying
the
energy
of
each
particle
.
This
can
be
any
function
of
*
x
*\
,
*
y
*\
,
and
*
z
*
you
want
.
It
also
can
depend
on
global
or
per
-
particle
parameters
.
A
wide
variety
of
restraints
,
steering
forces
,
shearing
forces
,
etc
.
can
be
implemented
with
this
method
.
Next
it
must
specify
which
particles
to
apply
the
force
to
.
In
this
case
,
we
want
it
to
affect
every
particle
in
the
system
,
so
we
loop
over
them
and
call
:
code
:`
addParticle
()`
once
for
each
one
.
The
two
arguments
are
the
index
of
the
particle
to
affect
,
and
the
list
of
per
-
particle
parameter
values
(
an
empty
list
in
this
case
).
If
we
had
per
-
particle
parameters
,
such
as
to
make
the
force
stronger
for
some
particles
than
for
others
,
this
is
where
we
would
specify
them
.
Notice
that
we
do
all
of
this
immediately
after
creating
the
System
.
That
is
not
an
arbitrary
choice
.
..
warning
::
If
you
add
new
forces
to
a
System
,
you
must
do
so
before
creating
the
Simulation
.
Once
you
create
a
Simulation
,
modifying
the
System
will
have
no
effect
on
that
Simulation
.
Extracting
and
Reporting
Forces
(
and
other
data
)
************************************************
OpenMM
provides
reporters
for
two
output
formats
:
PDB
and
DCD
.
Both
of
those
formats
store
only
positions
,
not
velocities
,
forces
,
or
other
data
.
In
this
section
,
we
create
a
new
reporter
that
outputs
forces
.
This
illustrates
two
important
things
:
how
to
write
a
reporter
,
and
how
to
query
the
simulation
for
forces
or
other
data
.
Here
is
the
definition
of
the
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
:
print
>>
self
.
_out
,
f
[
0
],
f
[
1
],
f
[
2
]
..
caption
::
:
autonumber
:`
Example
,
ForceReporter
`
The
constructor
and
destructor
are
straightforward
.
The
arguments
to
the
constructor
are
the
output
filename
and
the
interval
(
in
time
steps
)
at
which
it
should
generate
reports
.
It
opens
the
output
file
for
writing
and
records
the
reporting
interval
.
The
destructor
closes
the
file
.
We
then
have
two
methods
that
every
reporter
must
implement
:
:
code
:`
describeNextReport
()`
and
:
code
:`
report
()`\
.
A
Simulation
object
periodically
calls
:
code
:`
describeNextReport
()`
on
each
of
its
reporters
to
find
out
when
that
reporter
will
next
generate
a
report
,
and
what
information
will
be
needed
to
generate
it
.
The
return
value
should
be
a
five
element
tuple
,
whose
elements
are
as
follows
:
*
The
number
of
time
steps
until
the
next
report
.
We
calculate
this
as
*(
report
interval
)*\
-\
*(
current
step
)*\
%\
*(
report
interval
)*\
.
For
example
,
if
we
want
a
report
every
100
steps
and
the
simulation
is
currently
on
step
530
,
we
will
return
100
-(
530
%
100
)
=
70.
*
Whether
the
next
report
will
need
particle
positions
.
*
Whether
the
next
report
will
need
particle
velocities
.
*
Whether
the
next
report
will
need
forces
.
*
Whether
the
next
report
will
need
energies
.
When
the
time
comes
for
the
next
scheduled
report
,
the
Simulation
calls
:
code
:`
report
()`
to
generate
the
report
.
The
arguments
are
the
Simulation
object
,
and
a
State
that
is
guaranteed
to
contain
all
the
information
that
was
requested
by
:
code
:`
describeNextReport
()`\
.
A
State
object
contains
a
snapshot
of
information
about
the
simulation
,
such
as
forces
or
particle
positions
.
We
call
:
code
:`
getForces
()`
to
retrieve
the
forces
and
convert
them
to
the
units
we
want
to
output
(
kJ
/
mole
/
nm
).
Then
we
loop
over
each
value
and
write
it
to
the
file
.
To
keep
the
example
simple
,
we
just
print
the
values
in
text
format
,
one
line
per
particle
.
In
a
real
program
,
you
might
choose
a
different
output
format
.
Now
that
we
have
defined
this
class
,
we
can
use
it
exactly
like
any
other
reporter
.
For
example
,
::
simulation
.
reporters
.
append
(
ForceReporter
(
'forces.txt'
,
100
))
will
output
forces
to
a
file
called
“
forces
.
txt
”
every
100
time
steps
.
Computing
Energies
******************
This
example
illustrates
a
different
sort
of
analysis
.
Instead
of
running
a
simulation
,
assume
we
have
already
identified
a
set
of
structures
we
are
interested
in
.
These
structures
are
saved
in
a
set
of
PDB
files
.
We
want
to
loop
over
all
the
files
in
a
directory
,
load
them
in
one
at
a
time
,
and
compute
the
potential
energy
of
each
one
.
Assume
we
have
already
created
our
System
and
Simulation
.
The
following
lines
perform
the
analysis
:
..
samepage
::
::
import
os
for
file
in
os
.
listdir
(
'structures'
):
pdb
=
PDBFile
(
os
.
path
.
join
(
'structures'
,
file
))
simulation
.
context
.
setPositions
(
pdb
.
positions
)
state
=
simulation
.
context
.
getState
(
getEnergy
=
True
)
print
file
,
state
.
getPotentialEnergy
()
..
caption
::
:
autonumber
:`
Example
,
computing
energies
`
We
use
Python
’
s
:
code
:`
listdir
()`
function
to
list
all
the
files
in
the
directory
.
We
create
a
PDBFile
object
for
each
one
and
call
:
code
:`
setPositions
()`
on
the
Context
to
specify
the
particle
positions
loaded
from
the
PDB
file
.
We
then
compute
the
energy
by
calling
:
code
:`
getState
()`
with
the
option
:
code
:`
getEnergy
=
True
`\
,
and
print
it
to
the
console
along
with
the
name
of
the
file
.
..
_creating
-
force
-
fields
:
Creating
Force
Fields
#####################
OpenMM
uses
a
simple
XML
file
format
to
describe
force
fields
.
It
includes
many
common
force
fields
,
but
you
can
also
create
your
own
.
A
force
field
can
use
all
the
standard
OpenMM
force
classes
,
as
well
as
the
very
flexible
custom
force
classes
.
You
can
even
extend
the
ForceField
class
to
add
support
for
completely
new
forces
,
such
as
ones
defined
in
plugins
.
This
makes
it
a
powerful
tool
for
force
field
development
.
Basic
Concepts
**************
Let
’
s
start
by
considering
how
OpenMM
defines
a
force
field
.
There
are
a
small
number
of
basic
concepts
to
understand
.
Atom
Types
and
Atom
Classes
===========================
Force
field
parameters
are
assigned
to
atoms
based
on
their
“
atom
types
”
.
Atom
types
should
be
the
most
specific
identification
of
an
atom
that
will
ever
be
needed
.
Two
atoms
should
have
the
same
type
only
if
the
force
field
will
always
treat
them
identically
in
every
way
.
Multiple
atom
types
can
be
grouped
together
into
“
atom
classes
”
.
In
general
,
two
types
should
be
in
the
same
class
if
the
force
field
usually
(
but
not
necessarily
always
)
treats
them
identically
.
For
example
,
the
:
math
:`\
alpha
`\
-
carbon
of
an
alanine
residue
will
probably
have
a
different
atom
type
than
the
:
math
:`\
alpha
`\
-
carbon
of
a
leucine
residue
,
but
both
of
them
will
probably
have
the
same
atom
class
.
All
force
field
parameters
can
be
specified
either
by
atom
type
or
atom
class
.
Classes
exist
as
a
convenience
to
make
force
field
definitions
more
compact
.
If
necessary
,
you
could
define
everything
in
terms
of
atom
types
,
but
when
many
types
all
share
the
same
parameters
,
it
is
convenient
to
only
have
to
specify
them
once
.
Residue
Templates
=================
Types
are
assigned
to
atoms
by
matching
residues
to
templates
.
A
template
specifies
a
list
of
atoms
,
the
type
of
each
one
,
and
the
bonds
between
them
.
For
each
residue
in
the
PDB
file
,
the
force
field
searches
its
list
of
templates
for
one
that
has
an
identical
set
of
atoms
with
identical
bonds
between
them
.
When
matching
templates
,
neither
the
order
of
the
atoms
nor
their
names
matter
;
it
only
cares
about
their
elements
and
the
set
of
bonds
between
them
.
(
The
PDB
file
reader
does
care
about
names
,
of
course
,
since
it
needs
to
figure
out
which
atom
each
line
of
the
file
corresponds
to
.)
Forces
======
Once
a
force
field
has
defined
its
atom
types
and
residue
templates
,
it
must
define
its
force
field
parameters
.
This
generally
involves
one
block
of
XML
for
each
Force
object
that
will
be
added
to
the
System
.
The
details
are
different
for
each
Force
,
but
it
generally
consists
of
a
set
of
rules
for
adding
interactions
based
on
bonds
and
atom
types
or
classes
.
For
example
,
when
adding
a
HarmonicBondForce
,
the
force
field
will
loop
over
every
pair
of
bonded
atoms
,
check
their
types
and
classes
,
and
see
if
they
match
any
of
its
rules
.
If
so
,
it
will
call
:
code
:`
addBond
()`
on
the
HarmonicBondForce
.
If
none
of
them
match
,
it
simply
ignores
that
pair
and
continues
.
Writing
the
XML
File
********************
The
root
element
of
the
XML
file
must
be
a
:
code
:`<
ForceField
>`
tag
:
..
code
-
block
::
xml
<
ForceField
>
...
</
ForceField
>
The
:
code
:`<
ForceField
>`
tag
contains
the
following
children
:
*
An
:
code
:`<
AtomTypes
>`
tag
containing
the
atom
type
definitions
*
A
:
code
:`<
Residues
>`
tag
containing
the
residue
template
definitions
*
Zero
or
more
tags
defining
specific
forces
The
order
of
these
tags
does
not
matter
.
They
are
described
in
details
below
.
<
AtomTypes
>
===========
The
atom
type
definitions
look
like
this
:
..
code
-
block
::
xml
<
AtomTypes
>
<
Type
name
=
"0"
class
=
"N"
element
=
"N"
mass
=
"14.00672"
/>
<
Type
name
=
"1"
class
=
"H"
element
=
"H"
mass
=
"1.007947"
/>
<
Type
name
=
"2"
class
=
"CT"
element
=
"C"
mass
=
"12.01078"
/>
...
</
AtomTypes
>
There
is
one
:
code
:`<
Type
>`
tag
for
each
atom
type
.
It
specifies
the
name
of
the
type
,
the
name
of
the
class
it
belongs
to
,
the
symbol
for
its
element
,
and
its
mass
in
amu
.
The
names
are
arbitrary
strings
:
they
need
not
be
numbers
,
as
in
this
example
.
The
only
requirement
is
that
all
types
have
unique
names
.
The
classes
are
also
arbitrary
strings
,
and
in
general
will
not
be
unique
.
Two
types
belong
to
the
same
class
if
they
list
the
same
value
for
the
:
code
:`
class
`
attribute
.
<
Residues
>
==========
The
residue
template
definitions
look
like
this
:
..
code
-
block
::
xml
<
Residues
>
<
Residue
name
=
"ACE"
>
<
Atom
name
=
"HH31"
type
=
"710"
/>
<
Atom
name
=
"CH3"
type
=
"711"
/>
<
Atom
name
=
"HH32"
type
=
"710"
/>
<
Atom
name
=
"HH33"
type
=
"710"
/>
<
Atom
name
=
"C"
type
=
"712"
/>
<
Atom
name
=
"O"
type
=
"713"
/>
<
Bond
from
=
"0"
to
=
"1"
/>
<
Bond
from
=
"1"
to
=
"2"
/>
<
Bond
from
=
"1"
to
=
"3"
/>
<
Bond
from
=
"1"
to
=
"4"
/>
<
Bond
from
=
"4"
to
=
"5"
/>
<
ExternalBond
from
=
"4"
/>
</
Residue
>
<
Residue
name
=
"ALA"
>
...
</
Residue
>
...
</
Residues
>
There
is
one
:
code
:`<
Residue
>`
tag
for
each
residue
template
.
That
in
turn
contains
the
following
tags
:
*
An
:
code
:`<
Atom
>`
tag
for
each
atom
in
the
residue
.
This
specifies
the
name
of
the
atom
and
its
atom
type
.
*
A
:
code
:`<
Bond
>`
tag
for
each
pair
of
atoms
that
are
bonded
to
each
other
.
The
:
code
:`
to
`
and
:
code
:`
from
`
attributes
are
the
indices
of
the
two
bonded
atoms
(
starting
from
0
)
in
the
order
they
were
listed
.
For
example
,
:
code
:`<
Bond
from
=
"1"
to
=
"3"
/>`
describes
a
bond
between
atom
CH3
and
atom
HH33
.
*
An
:
code
:`<
ExternalBond
>`
tag
for
each
atom
that
will
be
bonded
to
an
atom
of
a
different
residue
.
The
:
code
:`<
Residue
>`
tag
may
also
contain
:
code
:`<
VirtualSite
>`
tags
,
as
in
the
following
example
:
..
code
-
block
::
xml
<
Residue
name
=
"HOH"
>
<
Atom
name
=
"O"
type
=
"tip4pew-O"
/>
<
Atom
name
=
"H1"
type
=
"tip4pew-H"
/>
<
Atom
name
=
"H2"
type
=
"tip4pew-H"
/>
<
Atom
name
=
"M"
type
=
"tip4pew-M"
/>
<
VirtualSite
type
=
"average3"
index
=
"3"
atom1
=
"0"
atom2
=
"1"
atom3
=
"2"
weight1
=
"0.786646558"
weight2
=
"0.106676721"
weight3
=
"0.106676721"
/>
<
Bond
from
=
"0"
to
=
"1"
/>
<
Bond
from
=
"0"
to
=
"2"
/>
</
Residue
>
Each
:
code
:`<
VirtualSite
>`
tag
indicates
an
atom
in
the
residue
that
should
be
represented
with
a
virtual
site
.
The
:
code
:`
type
`
attribute
may
equal
:
code
:`
"average2"
`\
,
:
code
:`
"average3"
`\
,
or
:
code
:`
"outOfPlane"
`\
,
which
correspond
to
the
TwoParticleAverageSite
,
ThreeParticleAverageSite
,
and
OutOfPlaneSite
classes
respectively
.
The
:
code
:`
index
`
attribute
gives
the
index
(
starting
from
0
)
of
the
atom
to
represent
with
a
virtual
site
.
The
atoms
it
is
calculated
based
on
are
specified
by
:
code
:`
atom1
`\
,
:
code
:`
atom2
`\
,
and
(
for
virtual
site
classes
that
involve
three
atoms
)
:
code
:`
atom3
`\
.
The
remaining
attributes
are
specific
to
the
virtual
site
class
,
and
specify
the
parameters
for
calculating
the
site
position
.
For
a
TwoParticleAverageSite
,
they
are
:
code
:`
weight1
`
and
:
code
:`
weight2
`\
.
For
a
ThreeParticleAverageSite
,
they
are
:
code
:`
weight1
`\
,
:
code
:`
weight2
`\
,
and
\
:
code
:`
weight3
`\
.
For
an
OutOfPlaneSite
,
they
are
:
code
:`
weight12
`\
,
:
code
:`
weight13
`\
,
and
:
code
:`
weightCross
`\
.
<
HarmonicBondForce
>
===================
To
add
a
HarmonicBondForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
HarmonicBondForce
>
<
Bond
class1
=
"C"
class2
=
"C"
length
=
"0.1525"
k
=
"259408.0"
/>
<
Bond
class1
=
"C"
class2
=
"CA"
length
=
"0.1409"
k
=
"392459.2"
/>
<
Bond
class1
=
"C"
class2
=
"CB"
length
=
"0.1419"
k
=
"374049.6"
/>
...
</
HarmonicBondForce
>
Every
:
code
:`<
Bond
>`
tag
defines
a
rule
for
creating
harmonic
bond
interactions
between
atoms
.
Each
tag
may
identify
the
atoms
either
by
type
(
using
the
attributes
:
code
:`
type1
`
and
:
code
:`
type2
`\
)
or
by
class
(
using
the
attributes
:
code
:`
class1
`
and
:
code
:`
class2
`\
).
For
every
pair
of
bonded
atoms
,
the
force
field
searches
for
a
rule
whose
atom
types
or
atom
classes
match
the
two
atoms
.
If
it
finds
one
,
it
calls
:
code
:`
addBond
()`
on
the
HarmonicBondForce
with
the
specified
parameters
.
Otherwise
,
it
ignores
that
pair
and
continues
.
:
code
:`
length
`
is
the
equilibrium
bond
length
in
nm
,
and
:
code
:`
k
`
is
the
spring
constant
in
kJ
/
mol
/
nm
\
:
sup
:`
2
`\
.
<
HarmonicAngleForce
>
====================
To
add
a
HarmonicAngleForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
HarmonicAngleForce
>
<
Angle
class1
=
"C"
class2
=
"C"
class3
=
"O"
angle
=
"2.094"
k
=
"669.44"
/>
<
Angle
class1
=
"C"
class2
=
"C"
class3
=
"OH"
angle
=
"2.094"
k
=
"669.44"
/>
<
Angle
class1
=
"CA"
class2
=
"C"
class3
=
"CA"
angle
=
"2.094"
k
=
"527.184"
/>
...
</
HarmonicAngleForce
>
Every
:
code
:`<
Angle
>`
tag
defines
a
rule
for
creating
harmonic
angle
interactions
between
triplets
of
atoms
.
Each
tag
may
identify
the
atoms
either
by
type
(
using
the
attributes
:
code
:`
type1
`\
,
:
code
:`
type2
`\
,
...)
or
by
class
(
using
the
attributes
:
code
:`
class1
`\
,
:
code
:`
class2
`\
,
...).
The
force
field
identifies
every
set
of
three
atoms
in
the
system
where
the
first
is
bonded
to
the
second
,
and
the
second
to
the
third
.
For
each
one
,
it
searches
for
a
rule
whose
atom
types
or
atom
classes
match
the
three
atoms
.
If
it
finds
one
,
it
calls
:
code
:`
addAngle
()`
on
the
HarmonicAngleForce
with
the
specified
parameters
.
Otherwise
,
it
ignores
that
set
and
continues
.
:
code
:`
angle
`
is
the
equilibrium
angle
in
radians
,
and
:
code
:`
k
`
is
the
spring
constant
in
kJ
/
mol
/
radian
\
:
sup
:`
2
`\
.
<
PeriodicTorsionForce
>
======================
To
add
a
PeriodicTorsionForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
PeriodicTorsionForce
>
<
Proper
class1
=
"HC"
class2
=
"CT"
class3
=
"CT"
class4
=
"CT"
periodicity1
=
"3"
phase1
=
"0.0"
k1
=
"0.66944"
/>
<
Proper
class1
=
"HC"
class2
=
"CT"
class3
=
"CT"
class4
=
"HC"
periodicity1
=
"3"
phase1
=
"0.0"
k1
=
"0.6276"
/>
...
<
Improper
class1
=
"N"
class2
=
"C"
class3
=
"CT"
class4
=
"O"
periodicity1
=
"2"
phase1
=
"3.14159265359"
k1
=
"4.6024"
/>
<
Improper
class1
=
"N"
class2
=
"C"
class3
=
"CT"
class4
=
"H"
periodicity1
=
"2"
phase1
=
"3.14159265359"
k1
=
"4.6024"
/>
...
</
PeriodicTorsionForce
>
Every
child
tag
defines
a
rule
for
creating
periodic
torsion
interactions
between
sets
of
four
atoms
.
Each
tag
may
identify
the
atoms
either
by
type
(
using
the
attributes
:
code
:`
type1
`\
,
:
code
:`
type2
`\
,
...)
or
by
class
(
using
the
attributes
:
code
:`
class1
`\
,
:
code
:`
class2
`\
,
...).
The
force
field
recognizes
two
different
types
of
torsions
:
proper
and
improper
.
A
proper
torsion
involves
four
atoms
that
are
bonded
in
sequence
:
1
to
2
,
2
to
3
,
and
3
to
4.
An
improper
torsion
involves
a
central
atom
and
three
others
that
are
bonded
to
it
:
atoms
2
,
3
,
and
4
are
all
bonded
to
atom
1.
The
force
field
begins
by
identifying
every
set
of
atoms
in
the
system
of
each
of
these
types
.
For
each
one
,
it
searches
for
a
rule
whose
atom
types
or
atom
classes
match
the
four
atoms
.
If
it
finds
one
,
it
calls
:
code
:`
addTorsion
()`
on
the
PeriodicTorsionForce
with
the
specified
parameters
.
Otherwise
,
it
ignores
that
set
and
continues
.
:
code
:`
periodicity1
`
is
the
periodicity
of
the
torsion
,
\
:
code
:`
phase1
`
is
the
phase
offset
in
radians
,
and
:
code
:`
k1
`
is
the
force
constant
in
kJ
/
mol
.
Each
torsion
definition
can
specify
multiple
periodic
torsion
terms
to
add
to
its
atoms
.
To
add
a
second
one
,
just
add
three
more
attributes
:
:
code
:`
periodicity2
`\
,
:
code
:`
phase2
`\
,
and
:
code
:`
k2
`\
.
You
can
have
as
many
terms
as
you
want
.
Here
is
an
example
of
a
rule
that
adds
three
torsion
terms
to
its
atoms
:
..
code
-
block
::
xml
<
Proper
class1
=
"CT"
class2
=
"CT"
class3
=
"CT"
class4
=
"CT"
periodicity1
=
"3"
phase1
=
"0.0"
k1
=
"0.75312"
periodicity2
=
"2"
phase2
=
"3.14159265359"
k2
=
"1.046"
periodicity3
=
"1"
phase3
=
"3.14159265359"
k3
=
"0.8368"
/>
You
can
also
use
wildcards
when
defining
torsions
.
To
do
this
,
simply
leave
the
type
or
class
name
for
an
atom
empty
.
That
will
cause
it
to
match
any
atom
.
For
example
,
the
following
definition
will
match
any
sequence
of
atoms
where
the
second
atom
has
class
OS
and
the
third
has
class
P
:
..
code
-
block
::
xml
<
Proper
class1
=
""
class2
=
"OS"
class3
=
"P"
class4
=
""
periodicity1
=
"3"
phase1
=
"0.0"
k1
=
"1.046"
/>
<
RBTorsionForce
>
================
To
add
an
RBTorsionForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
RBTorsionForce
>
<
Proper
class1
=
"CT"
class2
=
"CT"
class3
=
"OS"
class4
=
"CT"
c0
=
"2.439272"
c1
=
"4.807416"
c2
=
"-0.8368"
c3
=
"-6.409888"
c4
=
"0"
c5
=
"0"
/>
<
Proper
class1
=
"C"
class2
=
"N"
class3
=
"CT"
class4
=
"C"
c0
=
"10.46"
c1
=
"-3.34720"
c2
=
"-7.1128"
c3
=
"0"
c4
=
"0"
c5
=
"0"
/>
...
<
Improper
class1
=
"N"
class2
=
"C"
class3
=
"CT"
class4
=
"O"
c0
=
"0.8368"
c1
=
"0"
c2
=
"-2.76144"
c3
=
"0"
c4
=
"3.3472"
c5
=
"0"
/>
<
Improper
class1
=
"N"
class2
=
"C"
class3
=
"CT"
class4
=
"H"
c0
=
"29.288"
c1
=
"-8.368"
c2
=
"-20.92"
c3
=
"0"
c4
=
"0"
c5
=
"0"
/>
...
</
RBTorsionForce
>
Every
child
tag
defines
a
rule
for
creating
Ryckaert
-
Bellemans
torsion
interactions
between
sets
of
four
atoms
.
Each
tag
may
identify
the
atoms
either
by
type
(
using
the
attributes
:
code
:`
type1
`\
,
:
code
:`
type2
`\
,
...)
or
by
class
(
using
the
attributes
:
code
:`
class1
`\
,
:
code
:`
class2
`\
,
...).
The
force
field
recognizes
two
different
types
of
torsions
:
proper
and
improper
.
A
proper
torsion
involves
four
atoms
that
are
bonded
in
sequence
:
1
to
2
,
2
to
3
,
and
3
to
4.
An
improper
torsion
involves
a
central
atom
and
three
others
that
are
bonded
to
it
:
atoms
2
,
3
,
and
4
are
all
bonded
to
atom
1.
The
force
field
begins
by
identifying
every
set
of
atoms
in
the
system
of
each
of
these
types
.
For
each
one
,
it
searches
for
a
rule
whose
atom
types
or
atom
classes
match
the
four
atoms
.
If
it
finds
one
,
it
calls
:
code
:`
addTorsion
()`
on
the
RBTorsionForce
with
the
specified
parameters
.
Otherwise
,
it
ignores
that
set
and
continues
.
The
attributes
:
code
:`
c0
`
through
:
code
:`
c5
`
are
the
coefficients
of
the
terms
in
the
Ryckaert
-
Bellemans
force
expression
.
You
can
also
use
wildcards
when
defining
torsions
.
To
do
this
,
simply
leave
the
type
or
class
name
for
an
atom
empty
.
That
will
cause
it
to
match
any
atom
.
For
example
,
the
following
definition
will
match
any
sequence
of
atoms
where
the
second
atom
has
class
OS
and
the
third
has
class
P
:
..
code
-
block
::
xml
<
Proper
class1
=
""
class2
=
"OS"
class3
=
"P"
class4
=
""
c0
=
"2.439272"
c1
=
"4.807416"
c2
=
"-0.8368"
c3
=
"-6.409888"
c4
=
"0"
c5
=
"0"
/>
<
CMAPTorsionForce
>
==================
To
add
a
CMAPTorsionForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
CMAPTorsionForce
>
<
Map
>
0.0
0.809
0.951
0.309
-
0.587
-
1.0
-
0.587
0.309
0.951
0.809
0.0
-
0.809
-
0.951
-
0.309
0.587
1.0
</
Map
>
<
Torsion
map
=
"0"
class1
=
"CT"
class2
=
"CT"
class3
=
"C"
class4
=
"N"
class5
=
"CT"
/>
<
Torsion
map
=
"0"
class1
=
"N"
class2
=
"CT"
class3
=
"C"
class4
=
"N"
class5
=
"CT"
/>
...
</
CMAPTorsionForce
>
Each
:
code
:`<
Map
>`
tag
defines
an
energy
correction
map
.
Its
content
is
the
list
of
energy
values
in
kJ
/
mole
,
listed
in
the
correct
order
for
CMAPTorsionForce
’
s
:
code
:`
addMap
()`
method
and
separated
by
white
space
.
See
the
API
documentation
for
details
.
The
size
of
the
map
is
determined
from
the
number
of
energy
values
.
Each
:
code
:`<
Torsion
>`
tag
defines
a
rule
for
creating
CMAP
torsion
interactions
between
sets
of
five
atoms
.
The
tag
may
identify
the
atoms
either
by
type
(
using
the
attributes
:
code
:`
type1
`\
,
:
code
:`
type2
`\
,
...)
or
by
class
(
using
the
attributes
:
code
:`
class1
`\
,
:
code
:`
class2
`\
,
...).
The
force
field
identifies
every
set
of
five
atoms
that
are
bonded
in
sequence
:
1
to
2
,
2
to
3
,
3
to
4
,
and
4
to
5.
For
each
one
,
it
searches
for
a
rule
whose
atom
types
or
atom
classes
match
the
five
atoms
.
If
it
finds
one
,
it
calls
:
code
:`
addTorsion
()`
on
the
CMAPTorsionForce
with
the
specified
parameters
.
Otherwise
,
it
ignores
that
set
and
continues
.
The
first
torsion
is
defined
by
the
sequence
of
atoms
1
-
2
-
3
-
4
,
and
the
second
one
by
atoms
2
-
3
-
4
-
5.
:
code
:`
map
`
is
the
index
of
the
map
to
use
,
starting
from
0
,
in
the
order
they
are
listed
in
the
file
.
You
can
also
use
wildcards
when
defining
torsions
.
To
do
this
,
simply
leave
the
type
or
class
name
for
an
atom
empty
.
That
will
cause
it
to
match
any
atom
.
For
example
,
the
following
definition
will
match
any
sequence
of
five
atoms
where
the
middle
three
have
classes
CT
,
C
,
and
N
respectively
:
..
code
-
block
::
xml
<
Torsion
map
=
"0"
class1
=
""
class2
=
"CT"
class3
=
"C"
class4
=
"N"
class5
=
""
/>
<
NonbondedForce
>
================
To
add
a
NonbondedForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
NonbondedForce
coulomb14scale
=
"0.833333"
lj14scale
=
"0.5"
>
<
Atom
type
=
"0"
charge
=
"-0.4157"
sigma
=
"0.32499"
epsilon
=
"0.71128"
/>
<
Atom
type
=
"1"
charge
=
"0.2719"
sigma
=
"0.10690"
epsilon
=
"0.06568"
/>
<
Atom
type
=
"2"
charge
=
"0.0337"
sigma
=
"0.33996"
epsilon
=
"0.45772"
/>
...
</
NonbondedForce
>
The
:
code
:`<
NonbondedForce
>`
tag
has
two
attributes
:
code
:`
coulomb14scale
`
and
:
code
:`
lj14scale
`
that
specify
the
scale
factors
between
pairs
of
atoms
separated
by
three
bonds
.
After
setting
the
nonbonded
parameters
for
all
atoms
,
the
force
field
calls
:
code
:`
createExceptionsFromBonds
()`
on
the
NonbondedForce
,
passing
in
these
scale
factors
as
arguments
.
Each
:
code
:`<
Atom
>`
tag
specifies
the
nonbonded
parameters
for
one
atom
type
(
specified
with
the
:
code
:`
type
`
attribute
)
or
atom
class
(
specified
with
the
:
code
:`
class
`
attribute
).
It
is
fine
to
mix
these
two
methods
,
having
some
tags
specify
a
type
and
others
specify
a
class
.
However
you
do
it
,
you
must
make
sure
that
a
unique
set
of
parameters
is
defined
for
every
atom
type
.
:
code
:`
charge
`
is
measured
in
units
of
the
proton
charge
,
:
code
:`
sigma
`
is
in
nm
,
and
:
code
:`
epsilon
`
is
in
kJ
/
mole
.
<
GBSAOBCForce
>
==============
To
add
a
GBSAOBCForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
GBSAOBCForce
>
<
Atom
type
=
"0"
charge
=
"-0.4157"
radius
=
"0.1706"
scale
=
"0.79"
/>
<
Atom
type
=
"1"
charge
=
"0.2719"
radius
=
"0.115"
scale
=
"0.85"
/>
<
Atom
type
=
"2"
charge
=
"0.0337"
radius
=
"0.19"
scale
=
"0.72"
/>
...
</
GBSAOBCForce
>
Each
:
code
:`<
Atom
>`
tag
specifies
the
OBC
parameters
for
one
atom
type
(
specified
with
the
:
code
:`
type
`
attribute
)
or
atom
class
(
specified
with
the
:
code
:`
class
`
attribute
).
It
is
fine
to
mix
these
two
methods
,
having
some
tags
specify
a
type
and
others
specify
a
class
.
However
you
do
it
,
you
must
make
sure
that
a
unique
set
of
parameters
is
defined
for
every
atom
type
.
:
code
:`
charge
`
is
measured
in
units
of
the
proton
charge
,
:
code
:`
radius
`
is
the
GBSA
radius
in
nm
,
and
:
code
:`
scale
`
is
the
OBC
scaling
factor
.
<
CustomBondForce
>
=================
To
add
a
CustomBondForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
CustomBondForce
energy
=
"scale*k*(r-r0)^2"
>
<
GlobalParameter
name
=
"scale"
defaultValue
=
"0.5"
/>
<
PerBondParameter
name
=
"k"
/>
<
PerBondParameter
name
=
"r0"
/>
<
Bond
class1
=
"OW"
class2
=
"HW"
r0
=
"0.09572"
k
=
"462750.4"
/>
<
Bond
class1
=
"HW"
class2
=
"HW"
r0
=
"0.15136"
k
=
"462750.4"
/>
<
Bond
class1
=
"C"
class2
=
"C"
r0
=
"0.1525"
k
=
"259408.0"
/>
...
</
CustomBondForce
>
The
energy
expression
for
the
CustomBondForce
is
specified
by
the
:
code
:`
energy
`
attribute
.
This
is
a
mathematical
expression
that
gives
the
energy
of
each
bond
as
a
function
of
its
length
*
r
*\
.
It
also
may
depend
on
an
arbitrary
list
of
global
or
per
-
bond
parameters
.
Use
a
:
code
:`<
GlobalParameter
>`
tag
to
define
a
global
parameter
,
and
a
:
code
:`<
PerBondParameter
>`
tag
to
define
a
per
-
bond
parameter
.
Every
:
code
:`<
Bond
>`
tag
defines
a
rule
for
creating
custom
bond
interactions
between
atoms
.
Each
tag
may
identify
the
atoms
either
by
type
(
using
the
attributes
:
code
:`
type1
`
and
:
code
:`
type2
`\
)
or
by
class
(
using
the
attributes
:
code
:`
class1
`
and
:
code
:`
class2
`\
).
For
every
pair
of
bonded
atoms
,
the
force
field
searches
for
a
rule
whose
atom
types
or
atom
classes
match
the
two
atoms
.
If
it
finds
one
,
it
calls
:
code
:`
addBond
()`
on
the
CustomBondForce
.
Otherwise
,
it
ignores
that
pair
and
continues
.
The
remaining
attributes
are
the
values
to
use
for
the
per
-
bond
parameters
.
All
per
-
bond
parameters
must
be
specified
for
every
:
code
:`<
Bond
>`
tag
,
and
the
attribute
name
must
match
the
name
of
the
parameter
.
For
instance
,
if
there
is
a
per
-
bond
parameter
with
the
name
“
k
”
,
then
every
:
code
:`<
Bond
>`
tag
must
include
an
attribute
called
:
code
:`
k
`\
.
<
CustomAngleForce
>
==================
To
add
a
CustomAngleForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
CustomAngleForce
energy
=
"scale*k*(theta-theta0)^2"
>
<
GlobalParameter
name
=
"scale"
defaultValue
=
"0.5"
/>
<
PerAngleParameter
name
=
"k"
/>
<
PerAngleParameter
name
=
" theta0"
/>
<
Angle
class1
=
"HW"
class2
=
"OW"
class3
=
"HW"
theta0
=
"1.824218"
k
=
"836.8"
/>
<
Angle
class1
=
"HW"
class2
=
"HW"
class3
=
"OW"
theta0
=
"2.229483"
k
=
"0.0"
/>
<
Angle
class1
=
"C"
class2
=
"C"
class3
=
"O"
theta0
=
"2.094395"
k
=
"669.44"
/>
...
</
CustomAngleForce
>
The
energy
expression
for
the
CustomAngleForce
is
specified
by
the
:
code
:`
energy
`
attribute
.
This
is
a
mathematical
expression
that
gives
the
energy
of
each
angle
as
a
function
of
the
angle
*
theta
*\
.
It
also
may
depend
on
an
arbitrary
list
of
global
or
per
-
angle
parameters
.
Use
a
:
code
:`<
GlobalParameter
>`
tag
to
define
a
global
parameter
,
and
a
:
code
:`<
PerAngleParameter
>`
tag
to
define
a
per
-
angle
parameter
.
Every
:
code
:`<
Angle
>`
tag
defines
a
rule
for
creating
custom
angle
interactions
between
triplets
of
atoms
.
Each
tag
may
identify
the
atoms
either
by
type
(
using
the
attributes
:
code
:`
type1
`\
,
:
code
:`
type2
`\
,
...)
or
by
class
(
using
the
attributes
:
code
:`
class1
`\
,
:
code
:`
class2
`\
,
...).
The
force
field
identifies
every
set
of
three
atoms
in
the
system
where
the
first
is
bonded
to
the
second
,
and
the
second
to
the
third
.
For
each
one
,
it
searches
for
a
rule
whose
atom
types
or
atom
classes
match
the
three
atoms
.
If
it
finds
one
,
it
calls
:
code
:`
addAngle
()`
on
the
CustomAngleForce
.
Otherwise
,
it
ignores
that
set
and
continues
.
The
remaining
attributes
are
the
values
to
use
for
the
per
-
angle
parameters
.
All
per
-
angle
parameters
must
be
specified
for
every
:
code
:`<
Angle
>`
tag
,
and
the
attribute
name
must
match
the
name
of
the
parameter
.
For
instance
,
if
there
is
a
per
-
angle
parameter
with
the
name
“
k
”
,
then
every
:
code
:`<
Angle
>`
tag
must
include
an
attribute
called
:
code
:`
k
`\
.
<
CustomTorsionForce
>
====================
To
add
a
CustomTorsionForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
CustomTorsionForce
energy
=
"scale*k*(1+cos(per*theta-phase))"
>
<
GlobalParameter
name
=
"scale"
defaultValue
=
"1"
/>
<
PerTorsionParameter
name
=
"k"
/>
<
PerTorsionParameter
name
=
"per"
/>
<
PerTorsionParameter
name
=
"phase"
/>
<
Proper
class1
=
"HC"
class2
=
"CT"
class3
=
"CT"
class4
=
"CT"
per
=
"3"
phase
=
"0.0"
k
=
"0.66944"
/>
<
Proper
class1
=
"HC"
class2
=
"CT"
class3
=
"CT"
class4
=
"HC"
per
=
"3"
phase
=
"0.0"
k
=
"0.6276"
/>
...
<
Improper
class1
=
"N"
class2
=
"C"
class3
=
"CT"
class4
=
"O"
per
=
"2"
phase
=
"3.14159265359"
k
=
"4.6024"
/>
<
Improper
class1
=
"N"
class2
=
"C"
class3
=
"CT"
class4
=
"H"
per
=
"2"
phase
=
"3.14159265359"
k
=
"4.6024"
/>
...
</
CustomTorsionForce
>
The
energy
expression
for
the
CustomTorsionForce
is
specified
by
the
:
code
:`
energy
`
attribute
.
This
is
a
mathematical
expression
that
gives
the
energy
of
each
torsion
as
a
function
of
the
angle
*
theta
*\
.
It
also
may
depend
on
an
arbitrary
list
of
global
or
per
-
torsion
parameters
.
Use
a
:
code
:`<
GlobalParameter
>`
tag
to
define
a
global
parameter
,
and
a
:
code
:`<
PerTorsionParameter
>`
tag
to
define
a
per
-
torsion
parameter
.
Every
child
tag
defines
a
rule
for
creating
custom
torsion
interactions
between
sets
of
four
atoms
.
Each
tag
may
identify
the
atoms
either
by
type
(
using
the
attributes
:
code
:`
type1
`\
,
:
code
:`
type2
`\
,
...)
or
by
class
(
using
the
attributes
:
code
:`
class1
`\
,
:
code
:`
class2
`\
,
...).
The
force
field
recognizes
two
different
types
of
torsions
:
proper
and
improper
.
A
proper
torsion
involves
four
atoms
that
are
bonded
in
sequence
:
1
to
2
,
2
to
3
,
and
3
to
4.
An
improper
torsion
involves
a
central
atom
and
three
others
that
are
bonded
to
it
:
atoms
2
,
3
,
and
4
are
all
bonded
to
atom
1.
The
force
field
begins
by
identifying
every
set
of
atoms
in
the
system
of
each
of
these
types
.
For
each
one
,
it
searches
for
a
rule
whose
atom
types
or
atom
classes
match
the
four
atoms
.
If
it
finds
one
,
it
calls
:
code
:`
addTorsion
()`
on
the
CustomTorsionForce
with
the
specified
parameters
.
Otherwise
,
it
ignores
that
set
and
continues
.
The
remaining
attributes
are
the
values
to
use
for
the
per
-
torsion
parameters
.
Every
:
code
:`<
Torsion
>`
tag
must
include
one
attribute
for
every
per
-
torsion
parameter
,
and
the
attribute
name
must
match
the
name
of
the
parameter
.
You
can
also
use
wildcards
when
defining
torsions
.
To
do
this
,
simply
leave
the
type
or
class
name
for
an
atom
empty
.
That
will
cause
it
to
match
any
atom
.
For
example
,
the
following
definition
will
match
any
sequence
of
atoms
where
the
second
atom
has
class
OS
and
the
third
has
class
P
:
..
code
-
block
::
xml
<
Proper
class1
=
""
class2
=
"OS"
class3
=
"P"
class4
=
""
per
=
"3"
phase
=
"0.0"
k
=
"0.66944"
/>
<
CustomNonbondedForce
>
======================
To
add
a
CustomNonbondedForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
CustomNonbondedForce
energy
=
"scale*epsilon1*epsilon2*((sigma1+sigma2)/r)^12"
bondCutoff
=
"3"
>
<
GlobalParameter
name
=
"scale"
defaultValue
=
"1"
/>
<
PerParticleParameter
name
=
"sigma"
/>
<
PerParticleParameter
name
=
"epsilon"
/>
<
Atom
type
=
"0"
sigma
=
"0.3249"
epsilon
=
"0.7112"
/>
<
Atom
type
=
"1"
sigma
=
"0.1069"
epsilon
=
"0.0656"
/>
<
Atom
type
=
"2"
sigma
=
"0.3399"
epsilon
=
"0.4577"
/>
...
</
CustomNonbondedForce
>
The
energy
expression
for
the
CustomNonbondedForce
is
specified
by
the
:
code
:`
energy
`
attribute
.
This
is
a
mathematical
expression
that
gives
the
energy
of
each
pairwise
interaction
as
a
function
of
the
distance
*
r
*\
.
It
also
may
depend
on
an
arbitrary
list
of
global
or
per
-
particle
parameters
.
Use
a
:
code
:`<
GlobalParameter
>`
tag
to
define
a
global
parameter
,
and
a
:
code
:`<
PerParticleParameter
>`
tag
to
define
a
per
-
particle
parameter
.
Exclusions
are
created
automatically
based
on
the
:
code
:`
bondCutoff
`
attribute
.
After
setting
the
nonbonded
parameters
for
all
atoms
,
the
force
field
calls
:
code
:`
createExclusionsFromBonds
()`
on
the
CustomNonbondedForce
,
passing
in
this
value
as
its
argument
.
To
avoid
creating
exclusions
,
set
:
code
:`
bondCutoff
`
to
0.
Each
:
code
:`<
Atom
>`
tag
specifies
the
parameters
for
one
atom
type
(
specified
with
the
:
code
:`
type
`
attribute
)
or
atom
class
(
specified
with
the
:
code
:`
class
`
attribute
).
It
is
fine
to
mix
these
two
methods
,
having
some
tags
specify
a
type
and
others
specify
a
class
.
However
you
do
it
,
you
must
make
sure
that
a
unique
set
of
parameters
is
defined
for
every
atom
type
.
The
remaining
attributes
are
the
values
to
use
for
the
per
-
atom
parameters
.
All
per
-
atom
parameters
must
be
specified
for
every
:
code
:`<
Atom
>`
tag
,
and
the
attribute
name
must
match
the
name
of
the
parameter
.
For
instance
,
if
there
is
a
per
-
atom
parameter
with
the
name
“
radius
”
,
then
every
:
code
:`<
Atom
>`
tag
must
include
an
attribute
called
:
code
:`
radius
`\
.
CustomNonbondedForce
also
allows
you
to
define
tabulated
functions
.
See
section
:
ref
:`
tabulated
-
functions
`
for
details
.
<
CustomGBForce
>
===============
To
add
a
CustomGBForce
to
the
System
,
include
a
tag
that
looks
like
this
:
..
code
-
block
::
xml
<
CustomGBForce
>
<
GlobalParameter
name
=
"solventDielectric"
defaultValue
=
"78.3"
/>
<
GlobalParameter
name
=
"soluteDielectric"
defaultValue
=
"1"
/>
<
PerParticleParameter
name
=
"charge"
/>
<
PerParticleParameter
name
=
"radius"
/>
<
PerParticleParameter
name
=
"scale"
/>
<
ComputedValue
name
=
"I"
type
=
"ParticlePairNoExclusions"
>
step
(
r
+
sr2
-
or1
)*
0.5
*(
1
/
L
-
1
/
U
+
0.25
*(
1
/
U
^
2
-
1
/
L
^
2
)*(
r
-
sr2
*
sr2
/
r
)+
0.5
*
log
(
L
/
U
)/
r
+
C
);
U
=
r
+
sr2
;
C
=
2
*(
1
/
or1
-
1
/
L
)*
step
(
sr2
-
r
-
or1
);
L
=
max
(
or1
,
D
);
D
=
abs
(
r
-
sr2
);
sr2
=
scale2
*
or2
;
or1
=
radius1
-
0.009
;
or2
=
radius2
-
0.009
</
ComputedValue
>
<
ComputedValue
name
=
"B"
type
=
"SingleParticle"
>
1
/(
1
/
or
-
tanh
(
1
*
psi
-
0.8
*
psi
^
2
+
4.85
*
psi
^
3
)/
radius
);
psi
=
I
*
or
;
or
=
radius
-
0.009
</
ComputedValue
>
<
EnergyTerm
type
=
"SingleParticle"
>
28.3919551
*(
radius
+
0.14
)^
2
*(
radius
/
B
)^
6
-
0.5
*
138.935456
*
(
1
/
soluteDielectric
-
1
/
solventDielectric
)*
charge
^
2
/
B
</
EnergyTerm
>
<
EnergyTerm
type
=
"ParticlePair"
>
-
138.935456
*(
1
/
soluteDielectric
-
1
/
solventDielectric
)*
charge1
*
charge2
/
f
;
f
=
sqrt
(
r
^
2
+
B1
*
B2
*
exp
(-
r
^
2
/(
4
*
B1
*
B2
)))
</
EnergyTerm
>
<
Atom
type
=
"0"
charge
=
"-0.4157"
radius
=
"0.1706"
scale
=
"0.79"
/>
<
Atom
type
=
"1"
charge
=
"0.2719"
radius
=
"0.115"
scale
=
"0.85"
/>
<
Atom
type
=
"2"
charge
=
"0.0337"
radius
=
"0.19"
scale
=
"0.72"
/>
...
</
CustomGBForce
>
The
above
(
rather
complicated
)
example
defines
a
generalized
Born
model
that
is
equivalent
to
GBSAOBCForce
.
The
definition
consists
of
a
set
of
computed
values
(
defined
by
:
code
:`<
ComputedValue
>`
tags
)
and
energy
terms
(
defined
by
:
code
:`<
EnergyTerm
>`
tags
),
each
of
which
is
evaluated
according
to
a
mathematical
expression
.
See
the
API
documentation
for
details
.
The
expressions
may
depend
on
an
arbitrary
list
of
global
or
per
-
atom
parameters
.
Use
a
:
code
:`<
GlobalParameter
>`
tag
to
define
a
global
parameter
,
and
a
:
code
:`<
PerAtomParameter
>`
tag
to
define
a
per
-
atom
parameter
.
Each
:
code
:`<
Atom
>`
tag
specifies
the
parameters
for
one
atom
type
(
specified
with
the
:
code
:`
type
`
attribute
)
or
atom
class
(
specified
with
the
:
code
:`
class
`
attribute
).
It
is
fine
to
mix
these
two
methods
,
having
some
tags
specify
a
type
and
others
specify
a
class
.
However
you
do
it
,
you
must
make
sure
that
a
unique
set
of
parameters
is
defined
for
every
atom
type
.
The
remaining
attributes
are
the
values
to
use
for
the
per
-
atom
parameters
.
All
per
-
atom
parameters
must
be
specified
for
every
:
code
:`<
Atom
>`
tag
,
and
the
attribute
name
must
match
the
name
of
the
parameter
.
For
instance
,
if
there
is
a
per
-
atom
parameter
with
the
name
“
radius
”
,
then
every
:
code
:`<
Atom
>`
tag
must
include
an
attribute
called
:
code
:`
radius
`\
.
CustomGBForce
also
allows
you
to
define
tabulated
functions
.
See
section
:
ref
:`
tabulated
-
functions
`
for
details
.
Writing
Custom
Expressions
==========================
The
custom
forces
described
in
this
chapter
involve
user
defined
algebraic
expressions
.
These
expressions
are
specified
as
character
strings
,
and
may
involve
a
variety
of
standard
operators
and
mathematical
functions
.
The
following
operators
are
supported
:
+
(
add
),
-
(
subtract
),
*
(
multiply
),
/
(
divide
),
and
^
(
power
).
Parentheses
“
(
“
and
“
)
”
may
be
used
for
grouping
.
The
following
standard
functions
are
supported
:
sqrt
,
exp
,
log
,
sin
,
cos
,
sec
,
csc
,
tan
,
cot
,
asin
,
acos
,
atan
,
sinh
,
cosh
,
tanh
,
erf
,
erfc
,
min
,
max
,
abs
,
step
.
step
(
x
)
=
0
if
x
<
0
,
1
otherwise
.
Some
custom
forces
allow
additional
functions
to
be
defined
from
tabulated
values
.
Numbers
may
be
given
in
either
decimal
or
exponential
form
.
All
of
the
following
are
valid
numbers
:
5
,
-
3.1
,
1e6
,
and
3.12e-2
.
The
variables
that
may
appear
in
expressions
are
specified
in
the
API
documentation
for
each
force
class
.
In
addition
,
an
expression
may
be
followed
by
definitions
for
intermediate
values
that
appear
in
the
expression
.
A
semicolon
“
;
”
is
used
as
a
delimiter
between
value
definitions
.
For
example
,
the
expression
::
a
^
2
+
a
*
b
+
b
^
2
;
a
=
a1
+
a2
;
b
=
b1
+
b2
is
exactly
equivalent
to
::
(
a1
+
a2
)^
2
+(
a1
+
a2
)*(
b1
+
b2
)+(
b1
+
b2
)^
2
The
definition
of
an
intermediate
value
may
itself
involve
other
intermediate
values
.
All
uses
of
a
value
must
appear
*
before
*
that
value
’
s
definition
.
..
_tabulated
-
functions
:
TabulatedFunctions
==================
Some
forces
,
such
as
CustomNonbondedForce
and
CustomGBForce
,
allow
you
to
define
tabulated
functions
.
To
define
a
function
,
include
a
:
code
:`<
Function
>`
tag
inside
the
:
code
:`<
CustomNonbondedForce
>`
or
:
code
:`<
CustomGBForce
>`
tag
:
..
code
-
block
::
xml
<
Function
name
=
"myfn"
type
=
"Continuous1D"
min
=
"-5"
max
=
"5"
>
0.983674857694
-
0.980096396266
-
0.975743130031
-
0.970451936613
-
0.964027580076
-
0.956237458128
-
0.946806012846
-
0.935409070603
-
0.921668554406
-
0.905148253645
-
0.885351648202
-
0.861723159313
-
0.833654607012
-
0.800499021761
-
0.761594155956
-
0.716297870199
-
0.664036770268
-
0.604367777117
-
0.537049566998
-
0.46211715726
-
0.379948962255
-
0.291312612452
-
0.197375320225
-
0.099667994625
0.0
0.099667994625
0.197375320225
0.291312612452
0.379948962255
0.46211715726
0.537049566998
0.604367777117
0.664036770268
0.716297870199
0.761594155956
0.800499021761
0.833654607012
0.861723159313
0.885351648202
0.905148253645
0.921668554406
0.935409070603
0.946806012846
0.956237458128
0.964027580076
0.970451936613
0.975743130031
0.980096396266
0.983674857694
0.986614298151
0.989027402201
</
Function
>
The
tag
’
s
attributes
define
the
name
of
the
function
,
the
type
of
function
,
and
the
range
of
values
for
which
it
is
defined
.
The
required
set
of
attributed
depends
on
the
function
type
:
..
tabularcolumns
::
|
l
|
L
|
============
=======================================================
Type
Required
Attributes
============
=======================================================
Continuous1D
min
,
max
Continuous2D
xmin
,
ymin
,
xmax
,
ymax
,
xsize
,
ysize
Continuous3D
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
,
xsize
,
ysize
,
zsize
Discrete1D
Discrete2D
xsize
,
ysize
Discrete3D
xsize
,
ysize
,
zsize
============
=======================================================
The
"min"
and
"max"
attributes
define
the
range
of
the
independent
variables
for
a
continuous
function
.
The
"size"
attributes
define
the
size
of
the
table
along
each
axis
.
The
tabulated
values
are
listed
inside
the
body
of
the
tag
,
with
successive
values
separated
by
white
space
.
See
the
API
documentation
for
more
details
.
Using
Multiple
Files
********************
If
multiple
XML
files
are
specified
when
a
ForceField
is
created
,
their
definitions
are
combined
as
follows
.
*
A
file
may
refer
to
atom
types
and
classes
that
it
defines
,
as
well
as
those
defined
in
previous
files
.
It
may
not
refer
to
ones
defined
in
later
files
.
This
means
that
the
order
in
which
files
are
listed
when
calling
the
ForceField
constructor
is
potentially
significant
.
*
Forces
that
involve
per
-
atom
parameters
(
such
as
NonbondedForce
or
GBSAOBCForce
)
require
parameter
values
to
be
defined
for
every
atom
type
.
It
does
not
matter
which
file
those
types
are
defined
in
.
For
example
,
files
that
define
explicit
water
models
generally
define
a
small
number
of
atom
types
,
as
well
as
nonbonded
parameters
for
those
types
.
In
contrast
,
files
that
define
implicit
solvent
models
do
not
define
any
new
atom
types
,
but
provide
parameters
for
all
the
atom
types
that
were
defined
in
the
main
force
field
file
.
*
For
other
forces
,
the
files
are
effectively
independent
.
For
example
,
if
two
files
each
include
a
:
code
:`<
HarmonicBondForce
>`
tag
,
bonds
will
be
created
based
on
the
rules
in
the
first
file
,
and
then
more
bonds
will
be
created
based
on
the
rules
in
the
second
file
.
This
means
you
could
potentially
end
up
with
multiple
bonds
between
a
single
pair
of
atoms
.
Extending
ForceField
********************
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
.
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
is
created
,
it
scans
through
the
XML
files
,
looks
up
the
generator
class
for
each
tag
,
and
asks
that
class
to
create
a
generator
object
based
on
it
.
Then
,
when
you
call
:
code
:`
createSystem
()`\
,
it
loops
over
each
of
its
generators
and
asks
each
one
to
create
its
Force
object
.
Adding
a
new
Force
type
therefore
is
simply
a
matter
of
creating
a
new
generator
class
and
adding
it
to
ForceField
’
s
map
.
The
generator
class
must
define
two
methods
.
First
,
it
needs
a
static
method
with
the
following
signature
to
parse
the
XML
tag
and
create
the
generator
:
::
@
staticmethod
def
parseElement
(
element
,
forcefield
):
:
code
:`
element
`
is
the
XML
tag
(
an
xml
.
etree
.
ElementTree
.
Element
object
)
and
:
code
:`
forcefield
`
is
the
ForceField
being
created
.
This
method
should
create
a
generator
and
add
it
to
the
ForceField
:
generator
=
MyForceGenerator
()
forcefield
.
_forces
.
append
(
generator
)
It
then
should
parse
the
information
contained
in
the
XML
tag
and
configure
the
generator
based
on
it
.
Second
,
it
must
define
a
method
with
the
following
signature
:
::
def
createForce
(
self
,
system
,
data
,
nonbondedMethod
,
nonbondedCutoff
,
args
):
When
:
code
:`
createSystem
()`
is
called
on
the
ForceField
,
it
first
creates
the
System
object
,
then
loops
over
each
of
its
generators
and
calls
:
code
:`
createForce
()`
on
each
one
.
This
method
should
create
the
Force
object
and
add
it
to
the
System
.
:
code
:`
data
`
is
a
ForceField
.
_SystemData
object
containing
information
about
the
System
being
created
(
atom
types
,
bonds
,
angles
,
etc
.),
:
code
:`
system
`
is
the
System
object
,
and
the
remaining
arguments
are
values
that
were
passed
to
:
code
:`
createSystem
()`\
.
To
get
a
better
idea
of
how
this
works
,
look
at
the
existing
generator
classes
in
forcefield
.
py
.
The
generator
class
may
optionally
also
define
a
method
with
the
following
signature
:
::
def
postprocessSystem
(
self
,
system
,
data
,
args
):
If
this
method
exists
,
it
will
be
called
after
all
Forces
have
been
created
.
This
gives
generators
a
chance
to
make
additional
changes
to
the
System
.
Finally
,
you
need
to
register
your
class
by
adding
it
to
ForceField
’
s
map
:
::
forcefield
.
parsers
[
'MyForce'
]
=
MyForceGenerator
.
parseElement
The
key
is
the
XML
tag
name
,
and
the
value
is
the
static
method
to
use
for
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
.
docs/usersguide/conf.py
deleted
100644 → 0
View file @
37246338
# -*- coding: utf-8 -*-
#
# OpenMM Developer Guide documentation build configuration file, created by
# sphinx-quickstart on Fri Feb 7 12:42:06 2014.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import
sys
,
os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys
.
path
.
insert
(
0
,
os
.
path
.
abspath
(
'.'
))
sys
.
path
.
append
(
os
.
path
.
abspath
(
'../sphinx'
))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions
=
[
'sphinx.ext.pngmath'
,
'sphinx.ext.mathjax'
,
'sphinxcontrib.bibtex'
,
'autonumber'
,
'samepage'
,
'caption'
,
'numsec'
]
# Add any paths that contain templates here, relative to this directory.
templates_path
=
[
'_templates'
]
# The suffix of source filenames.
source_suffix
=
'.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc
=
'index'
# General information about the project.
project
=
u
'OpenMM Users Guide'
copyright
=
u
'2008-2014, Stanford University'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version
=
os
.
getenv
(
'OPENMM_VERSION'
)
# The full version, including alpha/beta/rc tags.
release
=
os
.
getenv
(
'OPENMM_VERSION'
)
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns
=
[
'_build'
]
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style
=
'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme
=
'agogo'
# 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
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path
=
[
'_static'
]
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename
=
'OpenMMUsersGuidedoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements
=
{
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
'preamble'
:
"""
\\
usepackage[none]{hyphenat}
\\
usepackage{xstring}
\\
usepackage{color}
\\
usepackage{caption}
\\
setcounter{tocdepth}{3}
\\
captionsetup[figure]{labelformat=empty}
\\
renewcommand{\DUspan}[2]{%
\\
IfEqCase{#1}{%
{code}{
\\
small{}
\\
texttt{#2}
\\
normalsize{}}%
}[
\\
PackageError{DUspan}{Unrecognized option passed to DUspan: #1}{}]%
}%"""
,
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents
=
[
(
'index'
,
'OpenMMUsersGuide.tex'
,
u
'OpenMM Users Guide'
,
u
'Peter Eastman'
,
'manual'
),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages
=
[
(
'index'
,
'openmmusersguide'
,
u
'OpenMM Users Guide'
,
[
u
'Peter Eastman'
],
1
)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents
=
[
(
'index'
,
'OpenMMUsersGuide'
,
u
'OpenMM Users Guide'
,
u
'Peter Eastman'
,
'OpenMMUsersGuide'
,
'One line description of project.'
,
'Miscellaneous'
),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
docs/usersguide/header.rst
deleted
100644 → 0
View file @
37246338
.. role:: code
.. raw:: html
<style> .code {font-family:monospace;} </style>
<style> .caption {text-align:center;} </style>
.. |--| replace:: :option:`--`
docs/usersguide/index.rst
deleted
100644 → 0
View file @
37246338
.. include:: header.rst
####################################
OpenMM Users Manual and Theory Guide
####################################
Portions copyright (c) 2008-2014 Stanford University and the Authors
Contributors: Kyle Beauchamp, Christopher Bruns, Peter Eastman, Mark
Friedrichs, Joy P. Ku, Vijay Pande, Randy Radmer, Michael Sherman, Tom Markland
Permission is hereby granted, free of charge, to any person obtaining a copy of
this document (the "Document"), to deal in the Document without restriction,
including without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Document, and to permit
persons to whom the Document is furnished to do so, subject to the following
conditions:
This copyright and permission notice shall be included in all copies or
substantial portions of the Document.
THE DOCUMENT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS,
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE DOCUMENT OR THE USE OR OTHER DEALINGS IN THE
DOCUMENT.
.. toctree::
:numbered:
:maxdepth: 3
introduction
application
library
theory
zbibliography
docs/usersguide/introduction.rst
deleted
100644 → 0
View file @
37246338
.. include:: header.rst
Introduction
############
OpenMM consists of two parts:
#. A set of libraries that lets programmers easily add molecular simulation
features to their programs
#. An “application layer” that exposes those features to end users who just want
to run simulations
This guide is divided into three sections:
* Part I (Chapters :ref:`the-openmm-application-layer-introduction`\ -\ :ref:`creating-force-fields`\ )
describes the application layer. It is relevant to all users, but especially relevant to people
who want to use OpenMM as a stand-alone application for running simulations.
* Part II (Chapters :ref:`the-openmm-library-introduction`\ -\ :ref:`drude-plugin`\ )
describes how to use the OpenMM libraries within your own applications. It is primarily
relevant to programmers who want to write simulation applications.
* Part III (Chapters :ref:`the-theory-behind-openmm-introduction`\ -\ :ref:`other-features`\ )
describes the mathematical theory behind the features found in OpenMM. It is relevant to all users.
Online Resources
****************
You can find more documentation and other material at our website
http://simtk.org/home/openmm. Among other things there is a discussion forum,
a wiki, and videos of lectures on using OpenMM.
Referencing OpenMM
******************
Any work that uses OpenMM should cite the following publication:
P. Eastman, M. S. Friedrichs, J. D. Chodera, R. J. Radmer, C. M. Bruns, J. P.
Ku, K. A. Beauchamp, T. J. Lane, L.-P. Wang, D. Shukla, T. Tye, M. Houston, T.
Stich, C. Klein, M. R. Shirts, and V. S. Pande. "OpenMM 4: A Reusable,
Extensible, Hardware Independent Library for High Performance Molecular
Simulation." J. Chem. Theor. Comput. 9(1): 461-469. (2013).
We depend on academic research grants to fund the OpenMM development efforts;
citations of our publication will help demonstrate the value of OpenMM.
Acknowledgments
***************
OpenMM software and all related activities, such as this manual, are funded by
the Simbios National Center for Biomedical Computing through the National
Institutes of Health Roadmap for Medical Research, Grant U54 GM072970.
Information on the National Centers can be found at
http://nihroadmap.nih.gov/bioinformatics.
docs/usersguide/library.rst
deleted
100644 → 0
View file @
37246338
..
include
::
header
.
rst
..
_the
-
openmm
-
library
-
introduction
:
The
OpenMM
Library
:
Introduction
################################
What
Is
the
OpenMM
Library
?
***************************
OpenMM
consists
of
two
parts
.
First
,
there
is
a
set
of
libraries
for
performing
many
types
of
computations
needed
for
molecular
simulations
:
force
evaluation
,
numerical
integration
,
energy
minimization
,
etc
.
These
libraries
provide
an
interface
targeted
at
developers
of
simulation
software
,
allowing
them
to
easily
add
simulation
features
to
their
programs
.
Second
,
there
is
an
“
application
layer
”
,
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
.
Part
I
of
this
guide
focused
on
the
application
layer
and
described
how
to
run
simulations
with
it
.
We
now
turn
to
the
lower
level
libraries
.
We
will
assume
you
are
a
programmer
,
that
you
are
writing
your
own
applications
,
and
that
you
want
to
add
simulation
features
to
those
applications
.
Part
II
of
this
guide
describes
how
to
do
that
with
OpenMM
.
How
to
get
started
==================
We
have
provided
a
number
of
files
that
make
it
easy
to
get
started
with
OpenMM
.
Pre
-
compiled
binaries
are
provided
for
quickly
getting
OpenMM
onto
your
computer
(
See
Chapter
:
ref
:`
installing
-
openmm
`
for
set
-
up
instructions
).
We
recommend
that
you
then
compile
and
run
some
of
the
tutorial
examples
,
described
in
Chapter
:
ref
:`
openmm
-
tutorials
`.
These
highlight
key
functions
within
OpenMM
and
teach
you
the
basic
programming
concepts
for
using
OpenMM
.
Once
you
are
ready
to
begin
integrating
OpenMM
into
a
specific
software
package
,
read
through
Chapter
:
ref
:`
examples
-
of
-
openmm
-
integration
`
to
see
how
other
software
developers
have
done
this
.
License
========
Two
different
licenses
are
used
for
different
parts
of
OpenMM
.
The
public
API
,
the
low
level
API
,
and
the
reference
platform
are
all
distributed
under
the
MIT
license
.
This
is
a
very
permissive
license
which
allows
them
to
be
used
in
almost
any
way
,
requiring
only
that
you
retain
the
copyright
notice
and
disclaimer
when
distributing
them
.
The
CUDA
and
OpenCL
platforms
are
distributed
under
the
GNU
Lesser
General
Public
License
(
LGPL
).
This
also
allows
you
to
use
,
modify
,
and
distribute
them
in
any
way
you
want
,
but
it
requires
you
to
also
distribute
the
source
code
for
your
modifications
.
This
restriction
applies
only
to
modifications
to
OpenMM
itself
;
you
need
not
distribute
the
source
code
to
applications
that
use
it
.
OpenMM
also
uses
several
pieces
of
code
that
were
written
by
other
people
and
are
covered
by
other
licenses
.
All
of
these
licenses
are
similar
in
their
terms
to
the
MIT
license
,
and
do
not
significantly
restrict
how
OpenMM
can
be
used
.
All
of
these
licenses
may
be
found
in
the
“
licenses
”
directory
included
with
OpenMM
.
Design
Principles
*****************
The
design
of
the
OpenMM
API
is
guided
by
the
following
principles
.
1.
The
API
must
support
efficient
implementations
on
a
variety
of
architectures
.
The
most
important
consequence
of
this
goal
is
that
the
API
cannot
provide
direct
access
to
state
information
(
particle
positions
,
velocities
,
etc
.)
at
all
times
.
On
some
architectures
,
accessing
this
information
is
expensive
.
With
a
GPU
,
for
example
,
it
will
be
stored
in
video
memory
,
and
must
be
transferred
to
main
memory
before
outside
code
can
access
it
.
On
a
distributed
architecture
,
it
might
not
even
be
present
on
the
local
computer
.
OpenMM
therefore
only
allows
state
information
to
be
accessed
in
bulk
,
with
the
understanding
that
doing
so
may
be
a
slow
operation
.
2.
The
API
should
be
easy
to
understand
and
easy
to
use
.
This
seems
obvious
,
but
it
is
worth
stating
as
an
explicit
goal
.
We
are
creating
OpenMM
with
the
hope
that
many
other
people
will
use
it
.
To
achieve
that
goal
,
it
should
be
possible
for
someone
to
learn
it
without
an
enormous
amount
of
effort
.
An
equally
important
aspect
of
being
“
easy
to
use
”
is
being
easy
to
use
*
correctly
*\
.
A
well
designed
API
should
minimize
the
opportunities
for
a
programmer
to
make
mistakes
.
For
both
of
these
reasons
,
clarity
and
simplicity
are
essential
.
3.
It
should
be
modular
and
extensible
.
We
cannot
hope
to
provide
every
feature
any
user
will
ever
want
.
For
that
reason
,
it
is
important
that
OpenMM
be
easy
to
extend
.
If
a
user
wants
to
add
a
new
molecular
force
field
,
a
new
thermostat
algorithm
,
or
a
new
hardware
platform
,
the
API
should
make
that
easy
to
do
.
4.
The
API
should
be
hardware
independent
.
Computer
architectures
are
changing
rapidly
,
and
it
is
impossible
to
predict
what
hardware
platforms
might
be
important
to
support
in
the
future
.
One
of
the
goals
of
OpenMM
is
to
separate
the
API
from
the
hardware
.
The
developers
of
a
simulation
application
should
be
able
to
write
their
code
once
,
and
have
it
automatically
take
advantage
of
any
architecture
that
OpenMM
supports
,
even
architectures
that
do
not
yet
exist
when
they
write
it
.
Choice
of
Language
******************
Molecular
modeling
and
simulation
tools
are
written
in
a
variety
of
languages
:
C
,
C
++,
Fortran
,
Python
,
TCL
,
etc
.
It
is
important
that
any
of
these
tools
be
able
to
use
OpenMM
.
There
are
two
possible
approaches
to
achieving
this
goal
.
One
option
is
to
provide
a
separate
version
of
the
API
for
each
language
.
These
could
be
created
by
hand
,
or
generated
automatically
with
a
wrapper
generator
such
as
SWIG
.
This
would
require
the
API
to
use
only
“
lowest
common
denominator
”
features
that
can
be
reasonably
supported
in
all
languages
.
For
example
,
an
object
oriented
API
would
not
be
an
option
,
since
it
could
not
be
cleanly
expressed
in
C
or
Fortran
.
The
other
option
is
to
provide
a
single
version
of
the
API
written
in
a
single
language
.
This
would
permit
a
cleaner
,
simpler
API
,
but
also
restrict
the
languages
it
could
be
directly
called
from
.
For
example
,
a
C
++
API
could
not
be
invoked
directly
from
Fortran
or
Python
.
We
have
chosen
to
use
a
hybrid
of
these
two
approaches
.
OpenMM
is
based
on
an
object
oriented
C
++
API
.
This
is
the
primary
way
to
invoke
OpenMM
,
and
is
the
only
API
that
fully
exposes
all
features
of
the
library
.
We
believe
this
will
ultimately
produce
the
best
,
easiest
to
use
API
and
create
the
least
work
for
developers
who
use
it
.
It
does
require
that
any
code
which
directly
invokes
this
API
must
itself
be
written
in
C
++,
but
this
should
not
be
a
significant
burden
.
Regardless
of
what
language
we
had
chosen
,
developers
would
need
to
write
a
thin
layer
for
translating
between
their
own
application
’
s
data
model
and
OpenMM
.
That
layer
is
the
only
part
which
needs
to
be
written
in
C
++.
In
addition
,
we
have
created
wrapper
APIs
that
allow
OpenMM
to
be
invoked
from
other
languages
.
The
current
release
includes
wrappers
for
C
,
Fortran
,
and
Python
.
These
wrappers
support
as
many
features
as
reasonably
possible
given
the
constraints
of
the
particular
languages
,
but
some
features
cannot
be
fully
supported
.
In
particular
,
writing
plug
-
ins
to
extend
the
OpenMM
API
can
only
be
done
in
C
++.
We
are
also
aware
that
some
features
of
C
++
can
easily
lead
to
compatibility
and
portability
problems
,
and
we
have
tried
to
avoid
those
features
.
In
particular
,
we
make
minimal
use
of
templates
and
avoid
multiple
inheritance
altogether
.
Our
goal
is
to
support
OpenMM
on
all
major
compilers
and
operating
systems
.
Architectural
Overview
**********************
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
the
only
layer
that
many
users
will
ever
need
to
look
at
.
The
public
API
is
implemented
by
a
layer
of
platform
independent
code
.
It
serves
as
the
interface
to
the
lower
level
,
platform
specific
code
.
Most
users
will
never
need
to
look
at
it
.
The
next
level
down
is
the
OpenMM
Low
Level
API
(
OLLA
).
This
acts
as
an
abstraction
layer
to
hide
the
details
of
each
hardware
platform
.
It
consists
of
a
set
of
C
++
interfaces
that
each
platform
must
implement
.
Users
who
want
to
extend
OpenMM
will
need
to
write
classes
at
the
OLLA
level
.
Note
the
different
roles
played
by
the
public
API
and
the
low
level
API
:
the
public
API
defines
an
interface
for
users
to
invoke
in
their
own
code
,
while
OLLA
defines
an
interface
that
users
must
implement
,
and
that
is
invoked
by
the
OpenMM
implementation
layer
.
At
the
lowest
level
is
hardware
specific
code
that
actually
performs
computations
.
This
code
may
be
written
in
any
language
and
use
any
technologies
that
are
appropriate
.
For
example
,
code
for
GPUs
will
be
written
in
stream
processing
languages
such
as
OpenCL
or
CUDA
,
code
written
to
run
on
clusters
will
use
MPI
or
other
distributed
computing
tools
,
code
written
for
multicore
processors
will
use
threading
tools
such
as
Pthreads
or
OpenMP
,
etc
.
OpenMM
sets
no
restrictions
on
how
these
computational
kernels
are
written
.
As
long
as
they
are
wrapped
in
the
appropriate
OLLA
interfaces
,
OpenMM
can
use
them
.
..
_the
-
openmm
-
public
-
api
:
The
OpenMM
Public
API
*********************
The
public
API
is
based
on
a
small
number
of
classes
:
**
System
**\
:
A
System
specifies
generic
properties
of
the
system
to
be
simulated
:
the
number
of
particles
it
contains
,
the
mass
of
each
one
,
the
size
of
the
periodic
box
,
etc
.
The
interactions
between
the
particles
are
specified
through
a
set
of
Force
objects
(
see
below
)
that
are
added
to
the
System
.
Force
field
specific
parameters
,
such
as
particle
charges
,
are
not
direct
properties
of
the
System
.
They
are
properties
of
the
Force
objects
contained
within
the
System
.
**
Force
**\
:
The
Force
objects
added
to
a
System
define
the
behavior
of
the
particles
.
Force
is
an
abstract
class
;
subclasses
implement
specific
behaviors
.
The
Force
class
is
actually
slightly
more
general
than
its
name
suggests
.
A
Force
can
,
indeed
,
apply
forces
to
particles
,
but
it
can
also
directly
modify
particle
positions
and
velocities
in
arbitrary
ways
.
Some
thermostats
and
barostats
,
for
example
,
can
be
implemented
as
Force
classes
.
Examples
of
Force
subclasses
include
HarmonicBondForce
,
NonbondedForce
,
and
MonteCarloBarostat
.
**
Context
**\
:
This
stores
all
of
the
state
information
for
a
simulation
:
particle
positions
and
velocities
,
as
well
as
arbitrary
parameters
defined
by
the
Forces
in
the
System
.
It
is
possible
to
create
multiple
Contexts
for
a
single
System
,
and
thus
have
multiple
simulations
of
that
System
in
progress
at
the
same
time
.
**
Integrator
**\
:
This
implements
an
algorithm
for
advancing
the
simulation
through
time
.
It
is
an
abstract
class
;
subclasses
implement
specific
algorithms
.
Examples
of
Integrator
subclasses
include
LangevinIntegrator
,
VerletIntegrator
,
and
BrownianIntegrator
.
**
State
**\
:
A
State
stores
a
snapshot
of
the
simulation
at
a
particular
point
in
time
.
It
is
created
by
calling
a
method
on
a
Context
.
As
discussed
earlier
,
this
is
a
potentially
expensive
operation
.
This
is
the
only
way
to
query
the
values
of
state
variables
,
such
as
particle
positions
and
velocities
;
Context
does
not
provide
methods
for
accessing
them
directly
.
Here
is
an
example
of
what
the
source
code
to
create
a
System
and
run
a
simulation
might
look
like
:
..
code
-
block
::
c
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
system
.
addParticle
(
particle
[
i
].
mass
);
HarmonicBondForce
*
bonds
=
new
HarmonicBondForce
();
system
.
addForce
(
bonds
);
for
(
int
i
=
0
;
i
<
numBonds
;
++
i
)
bonds
->
addBond
(
bond
[
i
].
particle1
,
bond
[
i
].
particle2
,
bond
[
i
].
length
,
bond
[
i
].
k
);
HarmonicAngleForce
*
angles
=
new
HarmonicAngleForce
();
system
.
addForce
(
angles
);
for
(
int
i
=
0
;
i
<
numAngles
;
++
i
)
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
);
Context
context
(
system
,
integrator
);
context
.
setPositions
(
initialPositions
);
context
.
setVelocities
(
initialVelocities
);
integrator
.
step
(
10000
);
We
create
a
System
,
add
various
Forces
to
it
,
and
set
parameters
on
both
the
System
and
the
Forces
.
We
then
create
a
LangevinIntegrator
,
initialize
a
Context
in
which
to
run
a
simulation
,
and
instruct
the
Integrator
to
advance
the
simulation
for
10
,
000
time
steps
.
The
OpenMM
Low
Level
API
************************
The
OpenMM
Low
Level
API
(
OLLA
)
defines
a
set
of
interfaces
that
users
must
implement
in
their
own
code
if
they
want
to
extend
OpenMM
,
such
as
to
create
a
new
Force
subclass
or
support
a
new
hardware
platform
.
It
is
based
on
the
concept
of
“
kernels
”
that
define
particular
computations
to
be
performed
.
More
specifically
,
there
is
an
abstract
class
called
**
KernelImpl
**\
.
Instances
of
this
class
(
or
rather
,
of
its
subclasses
)
are
created
by
**
KernelFactory
**
objects
.
These
classes
provide
the
concrete
implementations
of
kernels
for
a
particular
platform
.
For
example
,
to
perform
calculations
on
a
GPU
,
one
would
create
one
or
more
KernelImpl
subclasses
that
implemented
the
computations
with
GPU
kernels
,
and
one
or
more
KernelFactory
subclasses
to
instantiate
the
KernelImpl
objects
.
All
of
these
objects
are
encapsulated
in
a
single
object
that
extends
**
Platform
**\
.
KernelFactory
objects
are
registered
with
the
Platform
to
be
used
for
creating
specific
named
kernels
.
The
choice
of
what
implementation
to
use
(
a
GPU
implementation
,
a
multithreaded
CPU
implementation
,
an
MPI
-
based
distributed
implementation
,
etc
.)
consists
entirely
of
choosing
what
Platform
to
use
.
As
discussed
so
far
,
the
low
level
API
is
not
in
any
way
specific
to
molecular
simulation
;
it
is
a
fairly
generic
computational
API
.
In
addition
to
defining
the
generic
classes
,
OpenMM
also
defines
abstract
subclasses
of
KernelImpl
corresponding
to
specific
calculations
.
For
example
,
there
is
a
class
called
CalcHarmonicBondForceKernel
to
implement
HarmonicBondForce
and
a
class
called
IntegrateLangevinStepKernel
to
implement
LangevinIntegrator
.
It
is
these
classes
for
which
each
Platform
must
provide
a
concrete
subclass
.
This
architecture
is
designed
to
allow
easy
extensibility
.
To
support
a
new
hardware
platform
,
for
example
,
you
create
concrete
subclasses
of
all
the
abstract
kernel
classes
,
then
create
appropriate
factories
and
a
Platform
subclass
to
bind
everything
together
.
Any
program
that
uses
OpenMM
can
then
use
your
implementation
simply
by
specifying
your
Platform
subclass
as
the
platform
to
use
.
Alternatively
,
you
might
want
to
create
a
new
Force
subclass
to
implement
a
new
type
of
interaction
.
To
do
this
,
define
an
abstract
KernelImpl
subclass
corresponding
to
the
new
force
,
then
write
the
Force
class
to
use
it
.
Any
Platform
can
support
the
new
Force
by
providing
a
concrete
implementation
of
your
KernelImpl
subclass
.
Furthermore
,
you
can
easily
provide
that
implementation
yourself
,
even
for
existing
Platforms
created
by
other
people
.
Simply
create
a
new
KernelFactory
subclass
for
your
kernel
and
register
it
with
the
Platform
object
.
The
goal
is
to
have
a
completely
modular
system
.
Each
module
,
which
might
be
distributed
as
an
independent
library
,
can
either
add
new
features
to
existing
platforms
or
support
existing
features
on
new
platforms
.
In
fact
,
there
is
nothing
“
special
”
about
the
kernel
classes
defined
by
OpenMM
.
They
are
simply
KernelImpl
subclasses
that
happen
to
be
used
by
Forces
and
Integrators
that
happen
to
be
bundled
with
OpenMM
.
They
are
treated
exactly
like
any
other
KernelImpl
,
including
the
ones
you
define
yourself
.
It
is
important
to
understand
that
OLLA
defines
an
interface
,
not
an
implementation
.
It
would
be
easy
to
assume
a
one
-
to
-
one
correspondence
between
KernelImpl
objects
and
the
pieces
of
code
that
actually
perform
calculations
,
but
that
need
not
be
the
case
.
For
a
GPU
implementation
,
for
example
,
a
single
KernelImpl
might
invoke
several
GPU
kernels
.
Alternatively
,
a
single
GPU
kernel
might
perform
the
calculations
of
several
KernelImpl
subclasses
.
..
_platforms
:
Platforms
*********
This
release
of
OpenMM
contains
the
following
Platform
subclasses
:
**
ReferencePlatform
**\
:
This
is
designed
to
serve
as
reference
code
for
writing
other
platforms
.
It
is
written
with
simplicity
and
clarity
in
mind
,
not
performance
.
**
CpuPlatform
**\
:
This
platform
provides
high
performance
when
running
on
conventional
CPUs
.
**
CudaPlatform
**\
:
This
platform
is
implemented
using
the
CUDA
language
,
and
performs
calculations
on
Nvidia
GPUs
.
**
OpenCLPlatform
**\
:
This
platform
is
implemented
using
the
OpenCL
language
,
and
performs
calculations
on
a
variety
of
types
of
GPUs
and
CPUs
.
The
choice
of
which
platform
to
use
for
a
simulation
depends
on
various
factors
:
#.
The
Reference
platform
is
much
slower
than
the
others
,
and
therefore
is
rarely
used
for
production
simulations
.
#.
The
CPU
platform
is
usually
the
fastest
choice
when
a
fast
GPU
is
not
available
.
However
,
it
requires
the
CPU
to
support
SSE
4.1
.
That
includes
most
CPUs
made
in
the
last
several
years
,
but
this
platform
may
not
be
available
on
some
older
computers
.
Also
,
for
simulations
that
use
certain
features
(
primarily
the
various
“
custom
”
force
classes
),
it
may
be
faster
to
use
the
OpenCL
platform
running
on
the
CPU
.
#.
The
CUDA
platform
can
only
be
used
with
NVIDIA
GPUs
.
For
using
an
AMD
or
Intel
GPU
,
use
the
OpenCL
platform
.
#.
When
running
on
recent
NVIDIA
GPUs
(
Fermi
and
Kepler
generations
),
the
CUDA
platform
is
usually
faster
and
should
be
used
.
On
older
GPUs
,
the
OpenCL
platform
is
likely
to
be
faster
.
Also
,
some
very
old
GPUs
(
GeForce
8000
and
9000
series
)
are
only
supported
by
the
OpenCL
platform
,
not
by
the
CUDA
platform
.
#.
The
AMOEBA
force
field
only
works
with
the
CUDA
platform
,
not
with
the
OpenCL
platform
.
It
also
works
with
the
Reference
and
CPU
platforms
,
but
the
performance
is
usually
too
slow
to
be
useful
on
those
platforms
.
..
_compiling
-
openmm
-
from
-
source
-
code
:
Compiling
OpenMM
from
Source
Code
#################################
This
chapter
describes
the
procedure
for
building
and
installing
OpenMM
libraries
from
source
code
.
It
is
recommended
that
you
use
binary
OpenMM
libraries
,
if
possible
.
If
there
are
not
suitable
binary
libraries
for
your
system
,
consider
building
OpenMM
from
source
code
by
following
these
instructions
.
Prerequisites
*************
Before
building
OpenMM
from
source
,
you
will
need
the
following
:
*
A
C
++
compiler
*
CMake
*
OpenMM
source
code
See
the
sections
below
for
specific
instructions
for
the
different
platforms
.
Get
a
C
++
compiler
==================
You
must
have
a
C
++
compiler
installed
before
attempting
to
build
OpenMM
from
source
.
Mac
and
Linux
:
clang
or
gcc
---------------------------
Use
clang
or
gcc
on
Mac
/
Linux
.
OpenMM
should
compile
correctly
with
all
recent
versions
of
these
compilers
.
We
recommend
clang
since
it
produces
faster
code
,
especially
when
using
the
CPU
platform
.
If
you
do
not
already
have
a
compiler
installed
,
you
will
need
to
download
and
install
it
.
On
Mac
OS
X
,
this
means
downloading
the
Xcode
Tools
from
the
App
Store
.
(
With
Xcode
4.3
,
you
must
then
launch
Xcode
,
open
the
Preferences
window
,
go
to
the
Downloads
tab
,
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
.)
Windows
:
Visual
Studio
----------------------
On
Windows
systems
,
use
the
C
++
compiler
in
Visual
Studio
version
10
(
2010
)
or
later
.
You
can
download
a
free
version
of
Visual
C
++
Express
Edition
from
http
://
www
.
microsoft
.
com
/
express
/
vc
/.
If
you
plan
to
use
use
OpenMM
from
Python
,
it
is
critical
that
both
OpenMM
and
Python
be
compiled
with
the
same
version
of
Visual
Studio
.
Install
CMake
=============
CMake
is
the
build
system
used
for
OpenMM
.
You
must
install
CMake
version
2.8
or
higher
before
attempting
to
build
OpenMM
from
source
.
You
can
get
CMake
from
http
://
www
.
cmake
.
org
/.
If
you
choose
to
build
CMake
from
source
on
Linux
,
make
sure
you
have
the
curses
library
installed
beforehand
,
so
that
you
will
be
able
to
build
the
CCMake
visual
CMake
tool
.
Get
the
OpenMM
source
code
==========================
You
will
also
need
the
OpenMM
source
code
before
building
OpenMM
from
source
.
To
download
and
unpack
OpenMM
source
code
:
#.
Browse
to
https
://
simtk
.
org
/
home
/
openmm
/.
#.
Click
the
"Downloads"
link
in
the
navigation
bar
on
the
left
side
.
#.
Download
OpenMM
<
Version
>-
Source
.
zip
,
choosing
the
latest
version
.
#.
Unpack
the
zip
file
.
Note
the
location
where
you
unpacked
the
OpenMM
source
code
.
Other
Required
Software
=======================
There
are
several
other
pieces
of
software
you
must
install
to
compile
certain
parts
of
OpenMM
.
Which
of
these
you
need
depends
on
the
options
you
select
in
CMake
.
*
For
compiling
the
CUDA
Platform
,
you
need
:
*
CUDA
(
See
Chapter
:
ref
:`
installing
-
openmm
`
for
installation
instructions
.)
*
For
compiling
the
OpenCL
Platform
,
you
need
:
*
OpenCL
(
See
Chapter
:
ref
:`
installing
-
openmm
`
for
installation
instructions
.)
*
For
compiling
C
and
Fortran
API
wrappers
,
you
need
:
*
Python
2.6
or
later
(
http
://
www
.
python
.
org
)
*
Doxygen
(
http
://
www
.
doxygen
.
org
)
*
A
Fortran
compiler
*
For
compiling
the
Python
API
wrappers
,
you
need
:
*
Python
2.6
or
later
(
http
://
www
.
python
.
org
)
*
SWIG
(
http
://
www
.
swig
.
org
)
*
Doxygen
(
http
://
www
.
doxygen
.
org
)
*
For
compiling
the
CPU
platform
,
you
need
:
*
FFTW
,
single
precision
multithreaded
version
(
http
://
www
.
fftw
.
org
)
*
To
generate
API
documentation
,
you
need
:
*
Doxygen
(
http
://
www
.
doxygen
.
org
)
Step
1
:
Configure
with
CMake
****************************
Build
and
source
directories
============================
First
,
create
a
directory
in
which
to
build
OpenMM
.
A
good
name
for
this
directory
is
build_openmm
.
We
will
refer
to
this
as
the
“
build_openmm
directory
”
in
the
instructions
below
.
This
directory
will
contain
the
temporary
files
used
by
the
OpenMM
CMake
build
system
.
Do
not
create
this
build
directory
within
the
OpenMM
source
code
directory
.
This
is
what
is
called
an
“
out
of
source
”
build
,
because
the
build
files
will
not
be
mixed
with
the
source
files
.
Also
note
the
location
of
the
OpenMM
source
directory
(
i
.
e
.,
where
you
unpacked
the
source
code
zip
file
).
It
should
contain
a
file
called
CMakeLists
.
txt
.
This
directory
is
what
we
will
call
the
“
OpenMM
source
directory
”
in
the
following
instructions
.
Starting
CMake
==============
Configuration
is
the
first
step
of
the
CMake
build
process
.
In
the
configuration
step
,
the
values
of
important
build
variables
will
be
established
.
Mac
and
Linux
-------------
On
Mac
and
Linux
machines
,
type
the
following
two
lines
:
::
cd
build_openmm
ccmake
-
i
<
path
to
OpenMM
src
directory
>
That
is
not
a
typo
.
:
code
:`
ccmake
`
has
two
c
’
s
.
CCMake
is
the
visual
CMake
configuration
tool
.
Press
“
\
:
code
:`
c
`\
”
within
the
CCMake
interface
to
configure
CMake
.
Follow
the
instructions
in
the
“
All
Platforms
”
section
below
.
Windows
-------
On
Windows
,
perform
the
following
steps
:
#.
Click
Start
->
All
Programs
->
CMake
2.8
->
CMake
#.
In
the
box
labeled
"Where is the source code:"
browse
to
OpenMM
src
directory
(
containing
top
CMakeLists
.
txt
)
#.
In
the
box
labeled
"Where to build the binaries"
browse
to
your
build_openmm
directory
.
#.
Click
the
"Configure"
button
at
the
bottom
of
the
CMake
screen
.
#.
Select
"Visual Studio 10 2010"
from
the
list
of
Generators
(
or
whichever
version
you
have
installed
)
#.
Follow
the
instructions
in
the
“
All
Platforms
”
section
below
.
All
platforms
-------------
There
are
several
variables
that
can
be
adjusted
in
the
CMake
interface
:
*
If
you
intend
to
use
CUDA
(
NVIDIA
)
or
OpenCL
acceleration
,
set
the
variable
OPENMM_BUILD_CUDA_LIB
or
OPENMM_BUILD_OPENCL_LIB
,
respectively
,
to
ON
.
Before
doing
so
,
be
certain
that
you
have
installed
and
tested
the
drivers
for
the
platform
you
have
selected
(
see
Chapter
:
ref
:`
installing
-
openmm
`
for
information
on
installing
GPU
software
).
*
There
are
lots
of
other
options
starting
with
OPENMM_BUILD
that
control
whether
to
build
particular
features
of
OpenMM
,
such
as
plugins
,
API
wrappers
,
and
documentation
.
*
Set
the
variable
CMAKE_INSTALL_PREFIX
to
the
location
where
you
want
to
install
OpenMM
.
Configure
(
press
“
\
:
code
:`
c
`\
”
)
again
.
Adjust
any
variables
that
cause
an
error
.
Continue
to
configure
(
press
“
\
:
code
:`
c
`\
”
)
until
no
starred
/
red
CMake
variables
are
displayed
.
Congratulations
,
you
have
completed
the
configuration
step
.
Step
2
:
Generate
Build
Files
with
CMake
***************************************
Once
the
configuration
is
done
,
the
next
step
is
generation
.
The
generate
“
g
”
or
“
OK
”
or
“
Generate
”
option
will
not
be
available
until
configuration
has
completely
converged
.
Windows
=======
*
Press
the
"OK"
or
“
Generate
”
button
to
generate
Visual
Studio
project
files
.
*
If
CMake
does
not
exit
automatically
,
press
the
close
button
in
the
upper
-
right
corner
of
the
CMake
title
bar
to
exit
.
Mac
and
Linux
=============
*
Press
:
code
:`
g
`
to
generate
the
Makefile
.
*
If
CMake
does
not
exit
automatically
,
press
“
q
”
to
exit
.
That
’
s
it
! Generation is the easy part. Now it’s time to build.
Step
3
:
Build
OpenMM
********************
Windows
=======
#.
Open
the
file
OpenMM
.
sln
in
your
openmm_build
directory
in
Visual
Studio
.
#.
Set
the
configuration
type
to
"Release"
(
not
"Debug"
)
in
the
toolbar
.
#.
From
the
Build
menu
,
click
Build
->
Build
Solution
#.
The
OpenMM
libraries
and
test
programs
will
be
created
.
This
takes
some
time
.
#.
The
test
program
TestCudaRandom
might
not
build
on
Windows
.
This
is
OK
.
Mac
and
Linux
=============
*
Type
:
code
:`
make
`
in
the
openmm_build
directory
.
The
OpenMM
libraries
and
test
programs
will
be
created
.
This
takes
some
time
.
Step
4
:
Install
OpenMM
**********************
Windows
=======
In
the
Solution
Explorer
Panel
,
far
-
click
/
right
-
click
INSTALL
->
build
.
Mac
and
Linux
=============
Type
:
::
make
install
If
you
are
installing
to
a
system
area
,
such
as
/
usr
/
local
/
openmm
/,
you
will
need
to
type
:
::
sudo
make
install
Step
5
:
Install
the
Python
API
******************************
Windows
=======
In
the
Solution
Explorer
Panel
,
right
-
click
PythonInstall
->
build
.
Mac
and
Linux
=============
Type
:
::
make
PythonInstall
If
you
are
installing
into
the
system
Python
,
such
as
/
usr
/
bin
/
python
,
you
will
need
to
type
:
::
sudo
make
PythonInstall
..
_test
-
your
-
build
:
Step
6
:
Test
your
build
***********************
After
OpenMM
has
been
built
,
you
should
run
the
unit
tests
to
make
sure
it
works
.
Windows
=======
In
Visual
Studio
,
far
-
click
/
right
-
click
RUN_TESTS
in
the
Solution
Explorer
Panel
.
Select
RUN_TESTS
->
build
to
begin
testing
.
Ignore
any
failures
for
TestCudaRandom
.
Mac
and
Linux
=============
Type
:
::
make
test
You
should
see
a
series
of
test
results
like
this
:
::
Start
1
:
TestReferenceAndersenThermostat
1
/
317
Test
#
1
:
TestReferenceAndersenThermostat
..............
Passed
0.26
sec
Start
2
:
TestReferenceBrownianIntegrator
2
/
317
Test
#
2
:
TestReferenceBrownianIntegrator
..............
Passed
0.13
sec
Start
3
:
TestReferenceCheckpoints
3
/
317
Test
#
3
:
TestReferenceCheckpoints
.....................
Passed
0.02
sec
...
<
many
other
tests
>
...
:
code
:`
Passed
`
is
good
.
:
code
:`
FAILED
`
is
bad
.
If
any
tests
fail
,
you
can
run
them
individually
to
get
more
detailed
error
information
.
Note
that
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
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.
..
_openmm
-
tutorials
:
OpenMM
Tutorials
#################
Example
Files
Overview
**********************
Four
example
files
are
provided
in
the
examples
folder
,
each
designed
with
a
specific
objective
.
*
**
HelloArgon
:**
A
very
simple
example
intended
for
verifying
that
you
have
installed
OpenMM
correctly
.
It
also
introduces
you
to
the
basic
classes
within
OpenMM
.
*
**
HelloSodiumChloride
:**
This
example
shows
you
our
recommended
strategy
for
integrating
OpenMM
into
an
existing
molecular
dynamics
code
.
*
**
HelloEthane
:**
The
main
purpose
of
this
example
is
to
demonstrate
how
to
tell
OpenMM
about
bonded
forces
(
bond
stretch
,
bond
angle
bend
,
dihedral
torsion
).
*
**
HelloWaterBox
:**
This
example
shows
you
how
to
use
OpenMM
to
model
explicit
solvation
,
including
setting
up
periodic
boundary
conditions
.
It
runs
extremely
fast
on
a
GPU
but
very
,
very
slowly
on
a
CPU
,
so
it
is
an
excellent
example
to
use
to
compare
performance
on
the
GPU
versus
the
CPU
.
The
other
examples
provided
use
systems
where
the
performance
difference
would
be
too
small
to
notice
.
The
two
fundamental
examples
—
HelloArgon
and
HelloSodiumChloride
—
are
provided
in
C
++,
C
,
and
Fortran
,
as
indicated
in
the
table
below
.
The
other
two
examples
—
HelloEthane
and
HelloWaterBox
—
follow
the
same
structure
as
HelloSodiumChloride
but
demonstrate
more
calls
within
the
OpenMM
API
.
They
are
only
provided
in
C
++
but
can
be
adapted
to
run
in
C
and
Fortran
by
following
the
mappings
described
in
Chapter
:
ref
:`
using
-
openmm
-
with
-
software
-
written
-
in
-
languages
-
other
-
than
-
c
++`\
.
HelloArgon
and
HelloSodiumChloride
also
serve
as
examples
of
how
to
do
these
mappings
.
The
sections
below
describe
the
HelloArgon
,
HelloSodiumChloride
,
and
HelloEthane
programs
in
more
detail
.
===============
==============
==========
========
========================================
===============
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
++
===============
==============
==========
========
========================================
===============
\*
van
der
Waals
and
Coulomb
forces
..
_running
-
example
-
files
:
Running
Example
Files
**********************
The
instructions
below
are
for
running
the
HelloArgon
program
.
A
similar
process
would
be
used
to
run
the
other
examples
.
Visual
Studio
=============
Navigate
to
wherever
you
saved
the
example
files
.
Descend
into
the
directory
folder
VisualStudio
.
Double
-
click
the
file
HelloArgon
.
sln
(
a
Microsoft
Visual
Studio
Solution
file
).
Visual
Studio
will
launch
.
Note
:
These
files
were
created
using
Visual
Studio
8.
If
you
are
using
a
more
recent
version
,
it
will
ask
if
you
want
to
convert
the
files
to
the
new
version
.
Agree
and
continue
through
the
conversion
process
.
In
Visual
Studio
,
make
sure
the
"Solution Configuration"
is
set
to
"Release"
and
not
"Debug"
.
The
“
Solution
Configuration
”
can
be
set
using
the
drop
-
down
menu
in
the
top
toolbar
,
next
to
the
green
arrow
(
see
:
numref
:`
Figure
,
Visual
Studio
configuration
`
below
).
Due
to
incompatibilities
among
Visual
Studio
versions
,
we
do
not
provide
pre
-
compiled
debug
binaries
.
..
figure
::
../
images
/
VisualStudioSetConfiguration
.
jpg
:
align
:
center
:
width
:
100
%
:
autonumber
:`
Figure
,
Visual
Studio
configuration
`:
Setting
"Solution Configuration"
to
"Release"
mode
in
Visual
Studio
From
the
command
options
select
Debug
->
Start
Without
Debugging
(
or
CTRL
-
F5
).
See
:
numref
:`
Figure
,
run
in
Visual
Studio
`.
This
will
also
compile
the
program
,
if
it
has
not
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
:
::
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
ATOM
3
AR
AR
1
9.678
0.000
0.000
1.00
0.00
ENDMDL
MODEL
251
ATOM
1
AR
AR
1
0.198
0.000
0.000
1.00
0.00
ATOM
2
AR
AR
1
5.082
0.000
0.000
1.00
0.00
ATOM
3
AR
AR
1
9.698
0.000
0.000
1.00
0.00
ENDMDL
MODEL
252
ATOM
1
AR
AR
1
0.165
0.000
0.000
1.00
0.00
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
-----------------------------------
The
very
first
line
of
the
output
will
indicate
whether
you
are
running
on
the
CPU
(
Reference
platform
)
or
a
GPU
(
CUDA
or
OpenCL
platform
).
It
will
say
one
of
the
following
:
::
REMARK
Using
OpenMM
platform
Reference
REMARK
Using
OpenMM
platform
Cuda
REMARK
Using
OpenMM
platform
OpenCL
If
you
have
a
supported
GPU
,
the
program
should
,
by
default
,
run
on
the
GPU
.
Visualizing
the
results
------------------------
You
can
output
the
results
to
a
PDB
file
that
could
be
visualized
using
programs
like
VMD
(
http
://
www
.
ks
.
uiuc
.
edu
/
Research
/
vmd
/)
or
PyMol
(
http
://
pymol
.
sourceforge
.
net
/).
To
do
this
within
Visual
Studios
:
#.
Right
-
click
on
the
project
name
HelloArgon
(
not
one
of
the
files
)
and
select
the
“
Properties
”
option
.
#.
On
the
“
Property
Pages
”
form
,
select
“
Debugging
”
under
the
“
Configuration
Properties
”
node
.
#.
In
the
“
Command
Arguments
”
field
,
type
:
::
>
argon
.
pdb
This
will
save
the
output
to
a
file
called
argon
.
pdb
in
the
current
working
directory
(
default
is
the
VisualStudio
directory
).
If
you
want
to
save
it
to
another
directory
,
you
will
need
to
specify
the
full
path
.
#.
Select
“
OK
”
Now
,
when
you
run
the
program
in
Visual
Studio
,
no
text
will
appear
.
After
a
short
time
,
you
should
see
the
message
“
\
:
code
:`
Press
any
key
to
continue
…
`\
,
”
indicating
that
the
program
is
complete
and
that
the
PDB
file
has
been
completely
written
.
Mac
OS
X
/
Linux
==============
Navigate
to
wherever
you
saved
the
example
files
.
Verify
your
makefile
by
consulting
the
MakefileNotes
file
in
this
directory
,
if
necessary
.
Type
:::
make
Then
run
the
program
by
typing
:
::
./
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
ATOM
3
AR
AR
1
9.678
0.000
0.000
1.00
0.00
ENDMDL
MODEL
251
ATOM
1
AR
AR
1
0.198
0.000
0.000
1.00
0.00
ATOM
2
AR
AR
1
5.082
0.000
0.000
1.00
0.00
ATOM
3
AR
AR
1
9.698
0.000
0.000
1.00
0.00
ENDMDL
MODEL
252
ATOM
1
AR
AR
1
0.165
0.000
0.000
1.00
0.00
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
-----------------------------------
The
very
first
line
of
the
output
will
indicate
whether
you
are
running
on
the
CPU
(
Reference
platform
)
or
a
GPU
(
CUDA
or
OpenCL
platform
).
It
will
say
one
of
the
following
:
::
REMARK
Using
OpenMM
platform
Reference
REMARK
Using
OpenMM
platform
Cuda
REMARK
Using
OpenMM
platform
OpenCL
If
you
have
a
supported
GPU
,
the
program
should
,
by
default
,
run
on
the
GPU
.
Visualizing
the
results
------------------------
You
can
output
the
results
to
a
PDB
file
that
could
be
visualized
using
programs
like
VMD
(
http
://
www
.
ks
.
uiuc
.
edu
/
Research
/
vmd
/)
or
PyMol
(
http
://
pymol
.
sourceforge
.
net
/)
by
typing
:
::
./
HelloArgon
>
argon
.
pdb
Compiling
Fortran
and
C
examples
--------------------------------
The
Makefile
provided
with
the
examples
can
also
be
used
to
compile
the
Fortran
and
C
examples
.
The
Fortran
compiler
needs
to
load
a
version
of
the
libstdc
++.
dylib
library
that
is
compatible
with
the
version
of
gcc
used
to
build
OpenMM
;
OpenMM
for
Mac
is
compiled
using
gcc
4.2
.
If
you
are
compiling
with
a
different
version
,
edit
the
Makefile
and
add
the
following
flag
to
FCPPLIBS
:
:
code
:`
–
L
/
usr
/
lib
/
gcc
/
i686
-
apple
-
darwin10
/
4.2.1
`\
.
When
the
Makefile
has
been
updated
,
type
:
::
make
all
HelloArgon
Program
******************
The
HelloArgon
program
simulates
three
argon
atoms
in
a
vacuum
.
It
is
a
simple
program
primarily
intended
for
you
to
verify
that
you
are
able
to
compile
,
link
,
and
run
with
OpenMM
.
It
also
demonstrates
the
basic
calls
needed
to
run
a
simulation
using
OpenMM
.
Including
OpenMM
-
defined
functions
==================================
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
==================================
By
default
,
a
program
will
run
on
the
Reference
platform
.
In
order
to
run
a
program
on
another
platform
(
e
.
g
.,
an
NVIDIA
or
AMD
GPU
),
you
need
to
load
the
required
shared
libraries
for
that
other
platform
(
e
.
g
.,
Cuda
,
OpenCL
).
The
easy
way
to
do
this
is
to
call
:
..
code
-
block
::
c
OpenMM
::
Platform
::
loadPluginsFromDirectory
(
OpenMM
::
Platform
::
getDefaultPluginsDirectory
());
This
will
load
all
the
shared
libraries
(
plug
-
ins
)
that
can
be
found
,
so
you
do
not
need
to
explicitly
know
which
libraries
are
available
on
a
given
machine
.
In
this
way
,
the
program
will
be
able
to
run
on
another
platform
,
if
it
is
available
.
Running
a
simulation
using
the
OpenMM
public
API
================================================
The
OpenMM
public
API
was
described
in
Section
:
ref
:`
the
-
openmm
-
public
-
api
`\
.
Here
you
will
see
how
to
use
those
classes
to
create
a
simple
system
of
three
argon
atoms
and
run
a
short
simulation
.
The
main
components
of
the
simulation
are
within
the
function
:
code
:`
simulateArgon
()`\
:
#.
**
System
**
–
We
first
establish
a
system
and
add
a
non
-
bonded
force
to
it
.
At
this
point
,
there
are
no
particles
in
the
system
.
..
code
-
block
::
c
//
Create
a
system
with
nonbonded
forces
.
OpenMM
::
System
system
;
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
for
the
particles
are
hard
-
coded
into
the
program
.
While
not
a
realistic
scenario
,
it
makes
the
example
simpler
and
clearer
.
The
:
code
:`
std
::
vector
<
OpenMM
::
Vec3
>`
is
an
array
of
vectors
of
3.
..
code
-
block
::
c
//
Create
three
atoms
.
std
::
vector
<
OpenMM
::
Vec3
>
initPosInNm
(
3
);
for
(
int
a
=
0
;
a
<
3
;
++
a
)
{
initPosInNm
[
a
]
=
OpenMM
::
Vec3
(
0.5
*
a
,
0
,
0
);
//
location
,
nm
system
.
addParticle
(
39.95
);
//
mass
of
Ar
,
grams
per
mole
//
charge
,
L
-
J
sigma
(
nm
),
well
depth
(
kJ
)
nonbond
->
addParticle
(
0.0
,
0.3350
,
0.996
);
//
vdWRad
(
Ar
)=
.188
nm
}
**
Units
:**
Be
very
careful
with
the
units
in
your
program
.
It
is
very
easy
to
make
mistakes
with
the
units
,
so
we
recommend
including
them
in
your
variable
names
,
as
we
have
done
here
:
code
:`
initPosInNm
`
(
position
in
nanometers
).
OpenMM
provides
conversion
constants
that
should
be
used
whenever
there
are
conversions
to
be
done
;
for
simplicity
,
we
did
not
do
that
in
HelloArgon
,
but
all
the
other
examples
show
the
use
of
these
constants
.
It
is
hard
to
overemphasize
the
importance
of
careful
units
handling
—
it
is
very
easy
to
make
a
mistake
despite
,
or
perhaps
because
of
,
the
trivial
nature
of
units
conversion
.
For
more
information
about
the
units
used
in
OpenMM
,
see
Section
:
ref
:`
units
`.
**
Adding
Particle
Information
:**
Both
the
system
and
the
non
-
bonded
force
require
information
about
the
particles
.
The
system
just
needs
to
know
the
mass
of
the
particle
.
The
non
-
bonded
force
requires
information
about
the
charge
(
in
this
case
,
argon
is
uncharged
),
and
the
Lennard
-
Jones
parameters
sigma
(
zero
-
energy
separation
distance
)
and
well
depth
(
see
Section
:
ref
:`
lennard
-
jones
-
interaction
`
for
more
details
).
Note
that
the
van
der
Waals
radius
for
argon
is
0.188
nm
and
that
it
has
already
been
converted
to
sigma
(
0.335
nm
)
in
the
example
above
where
it
is
added
to
the
non
-
bonded
force
;
in
your
code
,
you
should
make
use
of
the
appropriate
conversion
factor
supplied
with
OpenMM
as
discussed
in
Section
:
ref
:`
units
`\
.
#.
**
Integrator
**
–
We
next
specify
the
integrator
to
use
to
perform
the
calculations
.
In
this
case
,
we
choose
a
Verlet
integrator
to
run
a
constant
energy
simulation
.
The
only
argument
required
is
the
step
size
in
picoseconds
.
..
code
-
block
::
c
OpenMM
::
VerletIntegrator
integrator
(
0.004
);
//
step
size
in
ps
We
have
chosen
to
use
0.004
picoseconds
,
or
4
femtoseconds
,
which
is
larger
than
that
used
in
a
typical
molecular
dynamics
simulation
.
However
,
since
this
example
does
not
have
any
bonds
with
higher
frequency
components
,
like
most
molecular
dynamics
simulations
do
,
this
is
an
acceptable
value
.
#.
**
Context
**
–
The
context
is
an
object
that
consists
of
an
integrator
and
a
system
.
It
manages
the
state
of
the
simulation
.
The
code
below
initializes
the
context
.
We
then
let
the
context
select
the
best
platform
available
to
run
on
,
since
this
is
not
specifically
specified
,
and
print
out
the
chosen
platform
.
This
is
useful
information
,
especially
when
debugging
.
..
code
-
block
::
c
//
Let
OpenMM
Context
choose
best
platform
.
OpenMM
::
Context
context
(
system
,
integrator
);
printf
(
"REMARK Using OpenMM platform %s
\n
"
,
context
.
getPlatform
().
getName
().
c_str
());
We
then
initialize
the
system
,
setting
the
initial
time
,
as
well
as
the
initial
positions
and
velocities
of
the
atoms
.
In
this
example
,
we
leave
time
and
velocity
at
their
default
values
of
zero
.
..
code
-
block
::
c
//
Set
starting
positions
of
the
atoms
.
Leave
time
and
velocity
zero
.
context
.
setPositions
(
initPosInNm
);
#.
**
Initialize
and
run
the
simulation
**
–
The
next
block
of
code
runs
the
simulation
and
saves
its
output
.
For
each
frame
of
the
simulation
(
in
this
example
,
a
frame
is
defined
by
the
advancement
interval
of
the
integrator
;
see
below
),
the
current
state
of
the
simulation
is
obtained
and
written
out
to
a
PDB
-
formatted
file
.
..
code
-
block
::
c
//
Simulate
.
for
(
int
frameNum
=
1
;
;++
frameNum
)
{
//
Output
current
state
information
.
OpenMM
::
State
state
=
context
.
getState
(
OpenMM
::
State
::
Positions
);
const
double
timeInPs
=
state
.
getTime
();
writePdbFrame
(
frameNum
,
state
);
//
output
coordinates
*
Getting
state
information
has
to
be
done
in
bulk
,
asking
for
information
for
all
the
particles
at
once
.*
This
is
computationally
expensive
since
this
information
can
reside
on
the
GPUs
and
requires
communication
overhead
to
retrieve
,
so
you
do
not
want
to
do
it
very
often
.
In
the
above
code
,
we
only
request
the
positions
,
since
that
is
all
that
is
needed
,
and
time
from
the
state
.
The
simulation
stops
after
10
ps
;
otherwise
we
ask
the
integrator
to
take
10
steps
(
so
one
frame
is
equivalent
to
10
time
steps
).
Normally
,
we
would
want
to
take
more
than
10
steps
at
a
time
,
but
to
get
a
reasonable
-
looking
animation
,
we
use
10.
..
code
-
block
::
c
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
)
Error
handling
for
OpenMM
=========================
Error
handling
for
OpenMM
is
explicitly
designed
so
you
do
not
have
to
check
the
status
after
every
call
.
If
anything
goes
wrong
,
OpenMM
throws
an
exception
.
It
uses
standard
exceptions
,
so
on
many
platforms
,
you
will
get
the
exception
message
automatically
.
However
,
we
recommend
using
:
code
:`
try
-
catch
`
blocks
to
ensure
you
do
catch
the
exception
.
..
code
-
block
::
c
int
main
()
{
try
{
simulateArgon
();
return
0
;
//
success
!
}
//
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
;
//
failure
!
}
}
Writing
out
PDB
files
=====================
For
the
HelloArgon
program
,
we
provide
a
simple
PDB
file
writing
function
:
code
:`
writePdbFrame
`
that
*
only
*
writes
out
argon
atoms
.
The
function
has
nothing
to
do
with
OpenMM
except
for
using
the
OpenMM
State
.
The
function
extracts
the
positions
from
the
State
in
nanometers
(
10
\
:
sup
:`-
9
`
m
)
and
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
)
{
//
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
)
{
printf
(
"ATOM %5d AR AR 1 "
,
a
+
1
);
//
atom
number
printf
(
"%8.3f%8.3f%8.3f 1.00 0.00
\n
"
,
//
coordinates
//
"*10"
converts
nanometers
to
Angstroms
posInNm
[
a
][
0
]*
10
,
posInNm
[
a
][
1
]*
10
,
posInNm
[
a
][
2
]*
10
);
}
printf
(
"ENDMDL
\n
"
);
//
end
of
frame
}
:
code
:`
MODEL
`
and
:
code
:`
ENDMDL
`
are
used
to
mark
the
beginning
and
end
of
a
frame
,
respectively
.
By
including
multiple
frames
in
a
PDB
file
,
you
can
visualize
the
simulation
trajectory
.
HelloArgon
output
=================
The
output
of
the
HelloArgon
program
can
be
saved
to
a
*.
pdb
*
file
and
visualized
using
programs
like
VMD
or
PyMol
(
see
Section
:
ref
:`
running
-
example
-
files
`).
You
should
see
three
atoms
moving
linearly
away
and
towards
one
another
:
..
figure
::
../
images
/
Argon
.
png
:
align
:
center
You
may
need
to
adjust
the
van
der
Waals
radius
in
your
visualization
program
to
see
the
atoms
colliding
.
HelloSodiumChloride
Program
***************************
The
HelloSodiumChloride
models
several
sodium
(
Na
\
:
sup
:`+`\
)
and
chloride
(
Cl
\
:
sup
:`-`\
)
ions
in
implicit
solvent
(
using
a
Generalized
Born
/
Surface
Area
,
or
GBSA
,
OBC
model
).
As
with
the
HelloArgon
program
,
only
non
-
bonded
forces
are
simulated
.
The
main
purpose
of
this
example
is
to
illustrate
our
recommended
strategy
for
integrating
OpenMM
into
an
existing
molecular
dynamics
(
MD
)
code
:
#.
**
Write
a
few
,
high
-
level
interface
routines
containing
all
your
OpenMM
calls
**\
:
Rather
than
make
OpenMM
calls
throughout
your
program
,
we
recommend
writing
a
handful
of
interface
routines
that
understand
both
your
MD
code
’
s
data
structures
and
OpenMM
.
Organize
these
routines
into
a
separate
compilation
unit
so
you
do
not
have
to
make
huge
changes
to
your
existing
MD
code
.
These
routines
could
be
written
in
any
language
that
is
callable
from
the
existing
MD
code
.
We
recommend
writing
them
in
C
++
since
that
is
what
OpenMM
is
written
in
,
but
you
can
also
write
them
in
C
or
Fortran
;
see
Chapter
:
ref
:`
using
-
openmm
-
with
-
software
-
written
-
in
-
languages
-
other
-
than
-
c
++`\
.
#.
**
Call
only
these
high
-
level
interface
routines
from
your
existing
MD
code
:**
This
provides
a
clean
separation
between
the
existing
MD
code
and
OpenMM
,
so
that
changes
to
OpenMM
will
not
directly
impact
the
existing
MD
code
.
One
way
to
implement
this
is
to
use
opaque
handles
,
a
standard
trick
used
(
for
example
)
for
opening
files
in
Linux
.
An
existing
MD
code
can
communicate
with
OpenMM
via
the
handle
,
but
knows
none
of
the
details
of
the
handle
.
It
only
has
to
hold
on
to
the
handle
and
give
it
back
to
OpenMM
.
In
the
example
described
below
,
you
will
see
how
this
strategy
can
be
implemented
for
a
very
simple
MD
code
.
Chapter
:
ref
:`
examples
-
of
-
openmm
-
integration
`
describes
the
strategies
used
in
integrating
OpenMM
into
real
MD
codes
.
..
_simple
-
molecular
-
dynamics
-
system
:
Simple
molecular
dynamics
system
================================
The
initial
sections
of
HelloSodiumChloride
.
cpp
represent
a
very
simple
molecular
dynamics
system
.
The
system
includes
modeling
and
simulation
parameters
and
the
atom
and
force
field
data
.
It
also
provides
a
data
structure
\
:
code
:`
posInAng
[
3
]`
for
storing
the
current
state
.
These
sections
represent
(
in
highly
simplified
form
)
information
that
would
be
available
from
an
existing
MD
code
,
and
will
be
used
to
demonstrate
how
to
integrate
OpenMM
with
an
existing
MD
program
.
..
code
-
block
::
c
//
-----------------------------------------------------------------
//
MODELING
AND
SIMULATION
PARAMETERS
//
-----------------------------------------------------------------
static
const
double
Temperature
=
300
;
//
Kelvins
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
// system which uses nanometers and kilojoules.
static struct MyAtomInfo {
const char* pdb;
double mass, charge, vdwRadiusInAng, vdwEnergyInKcal,
gbsaRadiusInAng, gbsaScaleFactor;
double initPosInAng[3];
double posInAng[3]; // leave room for runtime state info
} atoms[] = {
// pdb mass charge vdwRad vdwEnergy gbsaRad gbsaScale initPos
{" NA ", 22.99, 1, 1.8680, 0.00277, 1.992, 0.8, 8, 0, 0},
{" CL ", 35.45, -1, 2.4700, 0.1000, 1.735, 0.8, -8, 0, 0},
{" NA ", 22.99, 1, 1.8680, 0.00277, 1.992, 0.8, 0, 9, 0},
{" CL ", 35.45, -1, 2.4700, 0.1000, 1.735, 0.8, 0,-9, 0},
{" NA ", 22.99, 1, 1.8680, 0.00277, 1.992, 0.8, 0, 0,-10},
{" CL ", 35.45, -1, 2.4700, 0.1000, 1.735, 0.8, 0, 0, 10},
{""} // end of list
};
Interface routines
==================
The key to our recommended integration strategy is the interface routines. You
will need to decide what interface routines are required for effective
communication between your existing MD program and OpenMM, but typically there
will only be six or seven. In our example, the following four routines suffice:
* **Initialize:** Data structures that already exist in your MD program
(i.e., force fields, constraints, atoms in the system) are passed to the
:code:`Initialize` routine, which makes appropriate calls to OpenMM and then
returns a handle to the OpenMM object that can be used by the existing MD
program.
* **Terminate:** Clean up the heap space allocated by :code:`Initialize`
by passing the handle to the :code:`Terminate` routine.
* **Advance State:** The :code:`AdvanceState` routine advances the
simulation. It requires that the calling function, the existing MD code, gives
it a handle.
* **Retrieve State:** When you want to do an analysis or generate some kind
of report, you call the :code:`RetrieveState` routine. You have to give it
a handle. It then fills in a data structure that is defined in the existing MD
code, allowing the MD program to use it in its existing routines without further
modification.
Note that these are just descriptions of the routines’ functions—you can call
them anything you like and implement them in whatever way makes sense for your
MD code.
In the example code, the four routines performing these functions, plus an
opaque data structure (the handle), would be declared, as shown below. Then,
the main program, which sets up, runs, and reports on the simulation, accesses
these routines and the opaque data structure (in this case, the variable
:code:`omm`\ ). As you can see, it does not have access to any OpenMM
declarations, only to the interface routines that you write so there is no need
to change the build environment.
.. code-block:: c
struct MyOpenMMData;
static MyOpenMMData* myInitializeOpenMM(const MyAtomInfo atoms[],
double temperature,
double frictionInPs,
double solventDielectric,
double soluteDielectric,
double stepSizeInFs,
std::string& platformName);
static void myStepWithOpenMM(MyOpenMMData*, int numSteps);
static void myGetOpenMMState(MyOpenMMData*, bool
wantEnergy,double& time, 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.
// (3) Write a PDB frame when the time comes.
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.
Units
-----
The simple molecular dynamics system described in Section :ref:`simple-molecular-dynamics-system`
employs the commonly used units of angstroms and kcals. These differ from the units and
parameters used within OpenMM (see Section :ref:`units`\ ): nanometers and kilojoules.
These differences may be small but they are critical and must be carefully
accounted for in the interface routines.
Lennard-Jones potential
-----------------------
The Lennard-Jones potential describes the energy between two identical atoms as
the distance between them varies.
The van der Waals “size” parameter is used to identify the distance at which the
energy between these two atoms is at a minimum (that is, where the van der Waals
force is most attractive). There are several ways to specify this parameter,
typically, either as the van der Waals radius r\ :sub:`vdw` or as the actual
distance between the two atoms d\ :sub:`min` (also called r\ :sub:`min`\ ),
which is twice the van der Waals radius r\ :sub:`vdw`\ . A third way to
describe the potential is through sigma :math:`\sigma`, which identifies the distance at
which the energy function crosses zero as the atoms move closer together than
d\ :sub:`min`\ . (See Section :ref:`lennard-jones-interaction` for more details about the
relationship between these).
:math:`\sigma` turns out to be about 0.89*d\ :sub:`min`\ , which is close enough to
d\ :sub:`min` that it makes it hard to distinguish the two. Be very careful that
you use the correct value. In the example below, we will show you how to use
the built-in OpenMM conversion constants to avoid errors.
Lennard-Jones parameters are defined for pairs of identical atoms, but must also
be applied to pairs of dissimilar atoms. That is done by “combining rules” that
differ among popular MD codes. Two of the most common are:
* Lorentz-Berthelot (used by AMBER, CHARMM):
.. math::
r=\frac{r_i+r_j}{2}, \epsilon=\sqrt{\epsilon_i \epsilon_j}
* Jorgensen (used by OPLS):
.. math::
r=\sqrt{r_i r_j}, \epsilon=\sqrt{\epsilon_i \epsilon_j}
where *r* = the effective van der Waals “size” parameter (minimum radius,
minimum distance, or zero crossing (sigma)), and :math:`\epsilon` = the effective van
der Waals energy well depth parameter, for the dissimilar pair of atoms *i*
and *j*\ .
OpenMM only implements Lorentz-Berthelot directly, but others can be implemented
using the CustomNonbondedForce class. (See Section :ref:`customnonbondedforce` for details.)
Opaque handle MyOpenMMData
--------------------------
In this example, the handle used by the interface to OpenMM is a pointer to a
struct called :code:`MyOpenMMData.` The pointer itself is opaque, meaning
the calling program has no knowledge of what the layout of the object it points
to is, or how to use it to directly interface with OpenMM. The calling program
will simply pass this opaque handle from one interface routine to another.
There are many different ways to implement the handle. The code below shows
just one example. A simulation requires three OpenMM objects (a System, a
Context, and an Integrator) and so these must exist within the handle. If other
objects were required for a simulation, you would just add them to your handle;
there would be no change in the main program using the handle.
.. code-block:: c
struct MyOpenMMData {
MyOpenMMData() : system(0), context(0), integrator(0) {}
~MyOpenMMData() {delete system; delete context; delete integrator;}
OpenMM::System* system;
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
:code:`~MyOpenMMData()` that (in C++) gives the heap space back. This was
done in-line in the HelloArgon program, but we recommend you use something like
the method here instead.
myInitializeOpenMM
-------------------
The :code:`myInitializeOpenMM` function takes the data structures and
simulation parameters from the existing MD code and returns a new handle that
can be used to do efficient computations with OpenMM. It also returns the
:code:`platformName` so the calling program knows what platform (e.g., CUDA,
OpenCL, Reference) was used.
.. code-block:: c
static MyOpenMMData*
myInitializeOpenMM( const MyAtomInfo atoms[],
double temperature,
double frictionInPs,
double solventDielectric,
double soluteDielectric,
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
the program will run on the best performing platform that is available. Then,
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.
omm->system = new OpenMM::System();
OpenMM::NonbondedForce* nonbond = new OpenMM::NonbondedForce();
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
HelloArgon program, both the System and the forces need information about the
atoms. For those unfamiliar with the C++ Standard Template Library, the
:code:`push_back` function called at the end of this code snippet just adds
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!).
// (3) GBSA needs charge, radius, and scale factor.
// (4) Collect default positions for initializing the simulation later.
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
* OpenMM::SigmaPerVdwRadius,
atom.vdwEnergyInKcal * OpenMM::KJPerKcal);
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
of angstroms and kcals, but OpenMM uses nanometers and kilojoules. So the
initialization routine will need to convert the values from the existing MD code
into the OpenMM units before assigning them to the OpenMM objects.
In the code above, we have used the unit conversion constants that come with
OpenMM (e.g., :code:`OpenMM::NmPerAngstrom`\ ) to perform these conversions.
Combined with the naming convention of including the units in the variable name
(e.g., :code:`initPosInAng`\ ), the unit conversion constants are useful
reminders to pay attention to units and minimize errors.
Finally, the initialization routine creates the Integrator and Context for the
simulation. Again, note the change in units for the arguments! The routine
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,
stepSizeInFs * OpenMM::PsPerFs);
omm->context = new OpenMM::Context(*omm->system, *omm->integrator);
omm->context->setPositions(initialPosInNm);
platformName = omm->context->getPlatform().getName();
return omm;
myGetOpenMMState
----------------
The :code:`myGetOpenMMState` function takes the handle and returns the time,
energy, and data structure for the atoms in a way that the existing MD code can
use them without modification.
.. code-block:: c
static void
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
your units! Note the conversion from the OpenMM units back to the units used in
the existing MD code.
.. code-block:: c
int infoMask = 0;
infoMask = OpenMM::State::Positions;
if (wantEnergy) {
infoMask += OpenMM::State::Velocities; // for kinetic energy (cheap)
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)
energyInKcal = (state.getPotentialEnergy() + state.getKineticEnergy())
* OpenMM::KcalPerKJ;
myStepWithOpenMM
----------------
The :code:`myStepWithOpenMM` routine takes the handle, uses it to find the
Integrator, and then sets the number of steps for the Integrator to take. It
does not return any values.
.. code-block:: c
static void
myStepWithOpenMM(MyOpenMMData* omm, int numSteps) {
omm->integrator->step(numSteps);
}
myTerminateOpenMM
-----------------
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
myTerminateOpenMM(MyOpenMMData* omm) {
delete omm;
}
HelloEthane Program
*******************
The HelloEthane program simulates ethane (H3-C-C-H3) in a vacuum. It is
structured similarly to the HelloSodiumChloride example, but includes bonded
forces (bond stretch, bond angle bend, dihedral torsion). In setting up these
bonded forces, the program illustrates some of the other inconsistencies in
definitions and units that you should watch out for.
The bonded forces are added to the system within the initialization interface
routine, similar to how the non-bonded forces were added in the
HelloSodiumChloride example:
.. code-block:: c
// 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 System owns
// the force objects and will take care of deleting them; don'
t
do
it
yourself
!
OpenMM
::
System
&
system
=
*(
omm
->
system
=
new
OpenMM
::
System
());
OpenMM
::
NonbondedForce
&
nonbond
=
*
new
OpenMM
::
NonbondedForce
();
OpenMM
::
HarmonicBondForce
&
bondStretch
=
*
new
OpenMM
::
HarmonicBondForce
();
OpenMM
::
HarmonicAngleForce
&
bondBend
=
*
new
OpenMM
::
HarmonicAngleForce
();
OpenMM
::
PeriodicTorsionForce
&
bondTorsion
=
*
new
OpenMM
::
PeriodicTorsionForce
();
system
.
addForce
(&
nonbond
);
system
.
addForce
(&
bondStretch
);
system
.
addForce
(&
bondBend
);
system
.
addForce
(&
bondTorsion
);
\
**
Constrainable
and
non
-
constrainable
bonds
:**
In
the
initialization
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
;
const
BondType
&
bond
=
bondType
[
bonds
[
i
].
type
];
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
.
\
**
Warning
**\
*:*
The
constant
used
to
specify
the
stiffness
may
be
defined
differently
between
the
existing
MD
code
and
OpenMM
.
For
instance
,
AMBER
uses
the
constant
,
as
given
in
the
harmonic
*
energy
*
term
kx
\
:
sup
:`
2
`\
,
where
the
force
is
2
kx
(
k
=
constant
and
x
=
distance
).
OpenMM
wants
the
constant
,
as
used
in
the
*
force
*
term
kx
(
with
energy
0.5
*
kx
\
:
sup
:`
2
`\
).
So
a
factor
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
in
a
molecule
.
For
atoms
that
close
,
normal
non
-
bonded
forces
do
not
apply
or
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
;
and
(
2
)
for
atoms
connected
by
three
bonds
(
1
-
4
),
Coulomb
and
van
der
Waals
terms
apply
but
are
reduced
by
a
force
-
field
dependent
scale
factor
.
In
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
*
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
,
torsion
.
phaseInDegrees
*
OpenMM
::
RadiansPerDegree
,
torsion
.
amplitudeInKcal
*
OpenMM
::
KJPerKcal
);
}
The
rest
of
the
code
is
similar
to
the
HelloSodiumChloride
example
and
will
not
be
covered
in
detail
here
.
Please
refer
to
the
program
HelloEthane
.
cpp
itself
,
which
is
well
-
commented
,
for
additional
details
.
..
_platform
-
specific
-
properties
:
Platform
-
Specific
Properties
############################
When
creating
a
Context
,
you
can
specify
values
for
properties
specific
to
a
particular
Platform
.
This
is
used
to
control
how
calculations
are
done
in
ways
that
are
outside
the
scope
of
the
generic
OpenMM
API
.
To
do
this
,
pass
both
the
Platform
object
and
a
map
of
property
values
to
the
Context
constructor
:
..
code
-
block
::
c
Platform
&
platform
=
Platform
::
getPlatformByName
(
"OpenCL"
);
map
<
string
,
string
>
properties
;
properties
[
"OpenCLDeviceIndex"
]
=
"1"
;
Context
context
(
system
,
integrator
,
platform
,
properties
);
After
a
Context
is
created
,
you
can
use
the
Platform
’
s
\
:
code
:`
getPropertyValue
()`
method
to
query
the
values
of
properties
.
OpenCL
Platform
***************
The
OpenCL
Platform
recognizes
the
following
Platform
-
specific
properties
:
*
OpenCLPrecision
:
This
selects
what
numeric
precision
to
use
for
calculations
.
The
allowed
values
are
“
single
”
,
“
mixed
”
,
and
“
double
”
.
If
it
is
set
to
“
single
”
,
nearly
all
calculations
are
done
in
single
precision
.
This
is
the
fastest
option
but
also
the
least
accurate
.
If
it
is
set
to
“
mixed
”
,
forces
are
computed
in
single
precision
but
integration
is
done
in
double
precision
.
This
gives
much
better
energy
conservation
with
only
a
slightly
decrease
in
speed
.
If
it
is
set
to
“
double
”
,
all
calculations
are
done
in
double
precision
.
This
is
the
most
accurate
option
,
but
is
usually
much
slower
than
the
others
.
*
OpenCLUseCpuPme
:
This
selects
whether
to
use
the
CPU
based
PME
implementation
.
The
allowed
values
are
“
true
”
or
“
false
”
.
Depending
on
your
hardware
,
this
might
(
or
might
not
)
improve
performance
.
To
use
this
option
,
you
must
have
FFTW
(
single
precision
,
multithreaded
)
installed
,
and
your
CPU
must
support
SSE
4.1
.
*
OpenCLPlatformIndex
:
When
multiple
OpenCL
implementations
are
installed
on
your
computer
,
this
is
used
to
select
which
one
to
use
.
The
value
is
the
zero
-
based
index
of
the
platform
(
in
the
OpenCL
sense
,
not
the
OpenMM
sense
)
to
use
,
in
the
order
they
are
returned
by
the
OpenCL
platform
API
.
This
is
useful
,
for
example
,
in
selecting
whether
to
use
a
GPU
or
CPU
based
OpenCL
implementation
.
*
OpenCLDeviceIndex
:
When
multiple
OpenCL
devices
are
available
on
your
computer
,
this
is
used
to
select
which
one
to
use
.
The
value
is
the
zero
-
based
index
of
the
device
to
use
,
in
the
order
they
are
returned
by
the
OpenCL
device
API
.
The
OpenCL
Platform
also
supports
parallelizing
a
simulation
across
multiple
GPUs
.
To
do
that
,
set
the
OpenCLDeviceIndex
property
to
a
comma
separated
list
of
values
.
For
example
,
..
code
-
block
::
c
properties
[
"OpenCLDeviceIndex"
]
=
"0,1"
;
This
tells
it
to
use
both
devices
0
and
1
,
splitting
the
work
between
them
.
CUDA
Platform
*************
The
CUDA
Platform
recognizes
the
following
Platform
-
specific
properties
:
*
CudaPrecision
:
This
selects
what
numeric
precision
to
use
for
calculations
.
The
allowed
values
are
“
single
”
,
“
mixed
”
,
and
“
double
”
.
If
it
is
set
to
“
single
”
,
nearly
all
calculations
are
done
in
single
precision
.
This
is
the
fastest
option
but
also
the
least
accurate
.
If
it
is
set
to
“
mixed
”
,
forces
are
computed
in
single
precision
but
integration
is
done
in
double
precision
.
This
gives
much
better
energy
conservation
with
only
a
slightly
decrease
in
speed
.
If
it
is
set
to
“
double
”
,
all
calculations
are
done
in
double
precision
.
This
is
the
most
accurate
option
,
but
is
usually
much
slower
than
the
others
.
*
CudaUseCpuPme
:
This
selects
whether
to
use
the
CPU
based
PME
implementation
.
The
allowed
values
are
“
true
”
or
“
false
”
.
Depending
on
your
hardware
,
this
might
(
or
might
not
)
improve
performance
.
To
use
this
option
,
you
must
have
FFTW
(
single
precision
,
multithreaded
)
installed
,
and
your
CPU
must
support
SSE
4.1
.
*
CudaCompiler
:
This
specifies
the
path
to
the
CUDA
kernel
compiler
.
If
you
do
not
specify
this
,
OpenMM
will
try
to
locate
the
compiler
itself
.
Specify
this
only
when
you
want
to
override
the
default
location
.
The
logic
used
to
pick
the
default
location
depends
on
the
operating
system
:
*
Mac
/
Linux
:
It
first
looks
for
an
environment
variable
called
OPENMM_CUDA_COMPILER
.
If
that
is
set
,
its
value
is
used
.
Otherwise
,
the
default
location
is
set
to
/
usr
/
local
/
cuda
/
bin
/
nvcc
.
*
Windows
:
It
looks
for
an
environment
variable
called
CUDA_BIN_PATH
,
then
appends
\
nvcc
.
exe
to
it
.
That
environment
variable
is
set
by
the
CUDA
installer
,
so
it
usually
is
present
.
*
CudaTempDirectory
:
This
specifies
a
directory
where
temporary
files
can
be
written
while
compiling
kernels
.
OpenMM
usually
can
locate
your
operating
system
’
s
temp
directory
automatically
(
for
example
,
by
looking
for
the
TEMP
environment
variable
),
so
you
rarely
need
to
specify
this
.
*
CudaDeviceIndex
:
When
multiple
CUDA
devices
are
available
on
your
computer
,
this
is
used
to
select
which
one
to
use
.
The
value
is
the
zero
-
based
index
of
the
device
to
use
,
in
the
order
they
are
returned
by
the
CUDA
API
.
*
CudaUseBlockingSync
:
This
is
used
to
control
how
the
CUDA
runtime
synchronizes
between
the
CPU
and
GPU
.
If
this
is
set
to
“
true
”
(
the
default
),
CUDA
will
allow
the
calling
thread
to
sleep
while
the
GPU
is
performing
a
computation
,
allowing
the
CPU
to
do
other
work
.
If
it
is
set
to
“
false
”
,
CUDA
will
spin
-
lock
while
the
GPU
is
working
.
This
can
improve
performance
slightly
,
but
also
prevents
the
CPU
from
doing
anything
else
while
the
GPU
is
working
.
The
CUDA
Platform
also
supports
parallelizing
a
simulation
across
multiple
GPUs
.
To
do
that
,
set
the
CudaDeviceIndex
property
to
a
comma
separated
list
of
values
.
For
example
,
..
code
-
block
::
c
properties
[
"CudaDeviceIndex"
]
=
"0,1"
;
This
tells
it
to
use
both
devices
0
and
1
,
splitting
the
work
between
them
.
CPU
Platform
************
The
CPU
Platform
recognizes
the
following
Platform
-
specific
properties
:
*
CpuThreads
:
This
specifies
the
number
of
CPU
threads
to
use
.
If
you
do
not
specify
this
,
OpenMM
will
select
a
default
number
of
threads
as
follows
:
*
If
an
environment
variable
called
OPENMM_CPU_THREADS
is
set
,
its
value
is
used
as
the
number
of
threads
.
*
Otherwise
,
the
number
of
threads
is
set
to
the
number
of
logical
CPU
cores
in
the
computer
it
is
running
on
.
Usually
the
default
value
works
well
.
This
is
mainly
useful
when
you
are
running
something
else
on
the
computer
at
the
same
time
,
and
you
want
to
prevent
OpenMM
from
monopolizing
all
available
cores
.
..
_using
-
openmm
-
with
-
software
-
written
-
in
-
languages
-
other
-
than
-
c
++:
Using
OpenMM
with
Software
Written
in
Languages
Other
than
C
++
##############################################################
Although
the
native
OpenMM
API
is
object
-
oriented
C
++
code
,
it
is
possible
to
directly
translate
the
interface
so
that
it
is
callable
from
C
,
Fortran
95
,
and
Python
with
no
substantial
conceptual
changes
.
We
have
developed
a
straightforward
mapping
for
these
languages
that
,
while
perhaps
not
the
most
elegant
possible
,
has
several
advantages
:
*
Almost
all
documentation
,
training
,
forum
discussions
,
and
so
on
are
equally
useful
to
users
of
all
these
languages
.
There
are
syntactic
differences
of
course
,
but
all
the
important
concepts
remain
unchanged
.
*
We
are
able
to
generate
the
C
,
Fortran
,
and
Python
APIs
from
the
C
++
API
.
Obviously
,
this
reduces
development
effort
,
but
more
importantly
it
means
that
the
APIs
are
likely
to
be
error
-
free
and
are
always
available
immediately
when
the
native
API
is
updated
.
*
Because
OpenMM
performs
expensive
operations
“
in
bulk
”
there
is
no
noticeable
overhead
in
accessing
these
operations
through
the
C
,
Fortran
,
or
Python
APIs
.
*
All
symbols
introduced
to
a
C
or
Fortran
program
begin
with
the
prefix
“
\
:
code
:`
OpenMM_
`\
”
so
will
not
interfere
with
symbols
already
in
use
.
*
Availability
of
APIs
in
other
languages
:*
All
necessary
C
and
Fortran
bindings
are
built
in
to
the
main
OpenMM
library
;
no
separate
library
is
required
.
The
Python
wrappers
are
contained
in
a
module
that
is
distributed
with
OpenMM
and
that
can
be
installed
by
executing
its
setup
.
py
script
in
the
standard
way
.
(
This
doesn
’
t
apply
to
most
users
:
if
you
are
building
your
own
OpenMM
from
source
using
CMake
and
want
the
API
bindings
generated
,
be
sure
to
enable
the
:
code
:`
OPENMM_BUILD_C_AND_FORTRAN_WRAPPERS
`
option
for
C
and
Fortran
,
or
:
code
:`
OPENMM_BUILD_PYTHON_WRAPPERS
`
option
for
Python
.
The
Python
module
will
be
placed
in
a
subdirectory
of
your
main
build
directory
called
“
python
”
)
*
Documentation
for
APIs
in
other
languages
:*
While
there
is
extensive
Doxygen
documentation
available
for
the
C
++
and
Python
APIs
,
there
is
no
separate
on
-
line
documentation
for
the
C
and
Fortran
API
.
Instead
,
you
should
use
the
C
++
documentation
,
employing
the
mappings
described
here
to
figure
out
the
equivalent
syntax
in
C
or
Fortran
.
C
API
*****
Before
you
start
writing
your
own
C
program
that
calls
OpenMM
,
be
sure
you
can
build
and
run
the
two
C
examples
that
are
supplied
with
OpenMM
(
see
Chapter
:
ref
:`
openmm
-
tutorials
`\
).
These
can
be
built
from
the
supplied
:
code
:`
Makefile
`
on
Linux
and
Mac
,
or
supplied
:
code
:`
NMakefile
`
and
Visual
Studio
solution
files
on
Windows
.
The
example
programs
are
:
code
:`
HelloArgonInC
`
and
:
code
:`
HelloSodiumChlorideInC
`\
.
The
argon
example
serves
as
a
quick
check
that
your
installation
is
set
up
properly
and
you
know
how
to
build
a
C
program
that
is
linked
with
OpenMM
.
It
will
also
tell
you
whether
OpenMM
is
executing
on
the
GPU
or
is
running
(
slowly
)
on
the
Reference
platform
.
However
,
the
argon
example
is
not
a
good
template
to
follow
for
your
own
programs
.
The
sodium
chloride
example
,
though
necessarily
simplified
,
is
structured
roughly
in
the
way
we
recommended
you
set
up
your
own
programs
to
call
OpenMM
.
Please
be
sure
you
have
both
of
these
programs
executing
successfully
on
your
machine
before
continuing
.
Mechanics
of
using
the
C
API
============================
The
C
API
is
generated
automatically
from
the
C
++
API
when
OpenMM
is
built
.
There
are
two
resulting
components
:
C
bindings
(
functions
to
call
),
and
C
declarations
(
in
a
header
file
).
The
C
bindings
are
small
:
code
:`
extern
`
(
global
)
interface
functions
,
one
for
every
method
of
every
OpenMM
class
,
whose
signatures
(
name
and
arguments
)
are
predictable
from
the
class
name
and
method
signatures
.
There
are
also
“
helper
”
types
and
functions
provided
for
the
few
cases
in
which
the
C
++
behavior
cannot
be
directly
mapped
into
C
.
These
interface
and
helper
functions
are
compiled
in
to
the
main
OpenMM
library
so
there
is
nothing
special
you
have
to
do
to
get
access
to
them
.
In
the
/\
:
code
:`
include
`
subdirectory
of
your
OpenMM
installation
directory
,
there
is
a
machine
-
generated
header
file
:
code
:`
OpenMMCWrapper
.
h
`
that
should
be
#
included
in
any
C
program
that
is
to
make
calls
to
OpenMM
functions
.
That
header
contains
declarations
for
all
the
OpenMM
C
interface
functions
and
related
types
.
Note
that
if
you
follow
our
suggested
structure
,
you
will
not
need
to
include
this
file
in
your
:
code
:`
main
()`
compilation
unit
but
can
instead
use
it
only
in
a
local
file
that
you
write
to
provide
a
simple
interface
to
your
existing
code
(
see
Chapter
:
ref
:`
openmm
-
tutorials
`).
Mapping
from
the
C
++
API
to
the
C
API
=====================================
The
automated
generator
of
the
C
“
wrappers
”
follows
the
translation
strategy
shown
in
:
numref
:`
Table
,
C
API
`\
.
The
idea
is
that
if
you
see
the
construct
on
the
left
in
the
C
++
API
documentation
,
you
should
interpret
it
as
the
corresponding
construct
on
the
right
in
C
.
Please
look
at
the
supplied
example
programs
to
see
how
this
is
done
in
practice
.
==========================
=========================================
===================================================
Construct
C
++
API
declaration
Equivalent
in
C
API
==========================
=========================================
===================================================
namespace
OpenMM
\::
OpenMM
\
_
(
prefix
)
class
class
OpenMM
::
ClassName
typedef
OpenMM_ClassName
constant
OpenMM
::
RadiansPerDeg
OpenMM_RadiansPerDeg
(
static
constant
)
class
enum
OpenMM
::
State
::
Positions
OpenMM_State_Positions
constructor
new
OpenMM
::
ClassName
()
|
OpenMM_ClassName
*
OpenMM_ClassName_create
()
|
(
additional
constructors
are
_create_2
(),
etc
.)
destructor
|
OpenMM
::
ClassName
*
thing
;
|
OpenMM_ClassName
*
thing
;
|
delete
thing
;
|
OpenMM_ClassName_destroy
(
thing
);
class
method
|
OpenMM
::
ClassName
*
thing
;
|
OpenMM_ClassName
*
thing
;
|
thing
->
someName
(
args
);
|
OpenMM_ClassName_someName
(
thing
,
args
)
Boolean
(
type
&
constants
)
|
bool
|
OpenMM_Boolean
|
true
,
false
|
OpenMM_True
(
1
),
OpenMM_False
(
0
)
string
std
::
string
char
*
3
-
vector
OpenMM
::
Vec3
typedef
OpenMM_Vec3
arrays
|
std
::
vector
<
std
::
string
>
|
typedef
OpenMM_StringArray
|
std
::
vector
<
double
>
|
typedef
OpenMM_DoubleArray
|
std
::
vector
<
Vec3
>
|
typedef
OpenMM_Vec3Array
|
std
::
vector
<
std
::
pair
<
int
,
int
>>
|
typedef
OpenMM_BondArray
|
std
::
map
<
std
::
string
,
double
>
|
typedef
OpenMM_ParameterArray
==========================
=========================================
===================================================
:
autonumber
:`
Table
,
C
API
`\
:
Default
mapping
of
objects
from
the
C
++
API
to
the
C
API
There
are
some
exceptions
to
the
generic
translation
rules
shown
in
the
table
;
they
are
enumerated
in
the
next
section
.
And
because
there
are
no
C
++
API
equivalents
to
the
array
types
,
they
are
described
in
detail
below
.
Exceptions
==========
These
two
methods
are
handled
somewhat
differently
in
the
C
API
than
in
the
C
++
API
:
*
**
OpenMM
::
Context
::
getState
()**
The
C
version
,
:
code
:`
OpenMM_Context_getState
()`\
,
returns
a
pointer
to
a
heap
allocated
:
code
:`
OpenMM_State
`
object
.
You
must
then
explicitly
destroy
this
:
code
:`
State
`
object
when
you
are
done
with
it
,
by
calling
:
code
:`
OpenMM_State_destroy
()`\
.
*
**
OpenMM
::
Platform
::
loadPluginsFromDirectory
()**
The
C
version
:
code
:`
OpenMM_Platform_loadPluginsFromDirectory
()`
returns
a
heap
-
allocated
:
code
:`
OpenMM_StringArray
`
object
containing
a
list
of
all
the
file
names
that
were
successfully
loaded
.
You
must
then
explicitly
destroy
this
:
code
:`
StringArray
`
object
when
you
are
done
with
it
.
Do
not
ignore
the
return
value
;
if
you
do
you
’
ll
have
a
memory
leak
since
the
:
code
:`
StringArray
`
will
still
be
allocated
.
(
In
the
C
++
API
,
the
equivalent
methods
return
references
into
existing
memory
rather
than
new
heap
-
allocated
memory
,
so
the
returned
objects
do
not
need
to
be
destroyed
.)
OpenMM_Vec3
helper
type
=======================
Unlike
the
other
OpenMM
objects
which
are
opaque
and
manipulated
via
pointers
,
the
C
API
provides
an
explicit
definition
for
the
C
:
code
:`
OpenMM_Vec3
`
type
that
is
compatible
with
the
:
code
:`
OpenMM
::
Vec3
`
type
.
The
definition
of
:
code
:`
OpenMM_Vec3
`
is
:
..
code
-
block
::
c
typedef
struct
{
double
x
,
y
,
z
;}
OpenMM_Vec3
;
You
can
work
directly
with
the
individual
fields
of
this
type
from
your
C
program
if
you
want
.
For
convenience
,
a
scale
()
function
is
provided
that
creates
a
new
OpenMM_Vec3
from
an
old
one
and
a
scale
factor
:
..
code
-
block
::
c
OpenMM_Vec3
OpenMM_Vec3_scale
(
const
OpenMM_Vec3
vec
,
double
scale
);
Array
helper
types
==================
C
++
has
built
-
in
container
types
:
code
:`
std
::
vector
`
and
:
code
:`
std
::
map
`
which
OpenMM
uses
to
manipulate
arrays
of
objects
.
These
don
’
t
have
direct
equivalents
in
C
,
so
we
supply
special
array
types
for
each
kind
of
object
for
which
OpenMM
creates
containers
.
These
are
:
string
,
double
,
Vec3
,
bond
,
and
parameter
map
.
See
:
numref
:`
Table
,
C
arrays
`
for
the
names
of
the
C
types
for
each
of
these
object
arrays
.
Each
of
the
array
types
provides
these
functions
(
prefixed
by
:
code
:`
OpenMM_
`
and
the
actual
*
Thing
*
name
),
with
the
syntax
shown
conceptually
since
it
differs
slightly
for
each
kind
of
object
.
..
tabularcolumns
::
|
l
|
L
|
=======================================================
=========================================================================================================================================================================================================
Function
Operation
=======================================================
=========================================================================================================================================================================================================
*
Thing
*\
Array
\*
create
(
int
size
)
Create
a
heap
-
allocated
array
of
*
Things
*\
,
with
space
pre
-
allocated
to
hold
:
code
:`
size
`
of
them
.
You
can
start
at
:
code
:`
size
`\
==
0
if
you
want
since
these
arrays
are
dynamically
resizeable
.
void
destroy
(\
*
Thing
*\
Array
\*)
Free
the
heap
space
that
is
currently
in
use
for
the
passed
-
in
array
of
*
Things
*\
.
int
getSize
(\
*
Thing
*\
Array
\*)
Return
the
current
number
of
*
Things
*
in
this
array
.
This
means
you
can
:
code
:`
get
()`
and
:
code
:`
set
()`
elements
up
to
:
code
:`
getSize
()`\
-
1.
void
resize
(\
*
Thing
*\
Array
\*,
int
size
)
Change
the
size
of
this
array
to
the
indicated
value
which
may
be
smaller
or
larger
than
the
current
size
.
Existing
elements
remain
in
their
same
locations
as
long
as
they
still
fit
.
void
append
(\
*
Thing
*\
Array
\*,
*
Thing
*\
)
Add
a
*
Thing
*
to
the
end
of
the
array
,
increasing
the
array
size
by
one
.
The
precise
syntax
depends
on
the
actual
type
of
*
Thing
*\
;
see
below
.
void
set
(\
*
Thing
*\
Array
\*,
int
index
,
*
Thing
*\
)
Store
a
copy
of
*
Thing
*
in
the
indicated
element
of
the
array
(
indexed
from
0
).
The
array
must
be
of
length
at
least
:
code
:`
index
`\
+
1
;
you
can
’
t
grow
the
array
with
this
function
.
*
Thing
*
get
(\
*
Thing
*\
Array
\*,
int
index
)
Retrieve
a
particular
element
from
the
array
(
indexed
from
0
).
(
For
some
Things
the
value
is
returned
in
arguments
rather
than
as
the
function
return
.)
=======================================================
=========================================================================================================================================================================================================
:
autonumber
:`
Table
,
C
arrays
`\
:
Generic
description
of
array
helper
types
Here
are
the
exact
declarations
with
deviations
from
the
generic
description
noted
,
for
each
of
the
array
types
.
OpenMM_DoubleArray
------------------
..
code
-
block
::
c
OpenMM_DoubleArray
*
OpenMM_DoubleArray_create
(
int
size
);
void
OpenMM_DoubleArray_destroy
(
OpenMM_DoubleArray
*);
int
OpenMM_DoubleArray_getSize
(
const
OpenMM_DoubleArray
*);
void
OpenMM_DoubleArray_resize
(
OpenMM_DoubleArray
*,
int
size
);
void
OpenMM_DoubleArray_append
(
OpenMM_DoubleArray
*,
double
value
);
void
OpenMM_DoubleArray_set
(
OpenMM_DoubleArray
*,
int
index
,
double
value
);
double
OpenMM_DoubleArray_get
(
const
OpenMM_DoubleArray
*,
int
index
);
OpenMM_StringArray
------------------
..
code
-
block
::
c
OpenMM_StringArray
*
OpenMM_StringArray_create
(
int
size
);
void
OpenMM_StringArray_destroy
(
OpenMM_StringArray
*);
int
OpenMM_StringArray_getSize
(
const
OpenMM_StringArray
*);
void
OpenMM_StringArray_resize
(
OpenMM_StringArray
*,
int
size
);
void
OpenMM_StringArray_append
(
OpenMM_StringArray
*,
const
char
*
string
);
void
OpenMM_StringArray_set
(
OpenMM_StringArray
*,
int
index
,
const
char
*
string
);
const
char
*
OpenMM_StringArray_get
(
const
OpenMM_StringArray
*,
int
index
);
OpenMM_Vec3Array
----------------
..
code
-
block
::
c
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
*
OpenMM_Vec3Array_get
(
const
OpenMM_Vec3Array
*,
int
index
);
OpenMM_BondArray
----------------
Note
that
bonds
are
specified
by
pairs
of
integers
(
the
atom
indices
).
The
:
code
:`
get
()`
method
returns
those
in
a
pair
of
final
arguments
rather
than
as
its
functional
return
.
..
code
-
block
::
c
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
,
int
*
particle1
,
int
*
particle2
);
OpenMM_ParameterArray
---------------------
OpenMM
returns
references
to
internal
:
code
:`
ParameterArrays
`
but
does
not
support
user
-
created
:
code
:`
ParameterArrays
`\
,
so
only
the
:
code
:`
get
()`
and
:
code
:`
getSize
()`
functions
are
available
.
Also
,
note
that
since
this
is
actually
a
map
rather
than
an
array
,
the
“
index
”
is
the
*
name
*
of
the
parameter
rather
than
its
ordinal
.
..
code
-
block
::
c
int
OpenMM_ParameterArray_getSize
(
const
OpenMM_ParameterArray
*);
double
OpenMM_ParameterArray_get
(
const
OpenMM_ParameterArray
*,
const
char
*
name
);
Fortran
95
API
*****************
Before
you
start
writing
your
own
Fortran
program
that
calls
OpenMM
,
be
sure
you
can
build
and
run
the
two
Fortran
examples
that
are
supplied
with
OpenMM
(
see
Chapter
:
ref
:`
openmm
-
tutorials
`).
These
can
be
built
from
the
supplied
:
code
:`
Makefile
`
on
Linux
and
Mac
,
or
supplied
:
code
:`
NMakefile
`
and
Visual
Studio
solution
files
on
Windows
.
The
example
programs
are
:
code
:`
HelloArgonInFortran
`
and
:
code
:`
HelloSodiumChlorideInFortran
`\
.
The
argon
example
serves
as
a
quick
check
that
your
installation
is
set
up
properly
and
you
know
how
to
build
a
Fortran
program
that
is
linked
with
OpenMM
.
It
will
also
tell
you
whether
OpenMM
is
executing
on
the
GPU
or
is
running
(
slowly
)
on
the
Reference
platform
.
However
,
the
argon
example
is
not
a
good
template
to
follow
for
your
own
programs
.
The
sodium
chloride
example
,
though
necessarily
simplified
,
is
structured
roughly
in
the
way
we
recommended
you
set
up
your
own
programs
to
call
OpenMM
.
Please
be
sure
you
have
both
of
these
programs
executing
successfully
on
your
machine
before
continuing
.
Mechanics
of
using
the
Fortran
API
==================================
The
Fortran
API
is
generated
automatically
from
the
C
++
API
when
OpenMM
is
built
.
There
are
two
resulting
components
:
Fortran
bindings
(
subroutines
to
call
),
and
Fortran
declarations
of
types
and
subroutines
(
in
the
form
of
a
Fortran
95
module
file
).
The
Fortran
bindings
are
small
interface
subroutines
,
one
for
every
method
of
every
OpenMM
class
,
whose
signatures
(
name
and
arguments
)
are
predictable
from
the
class
name
and
method
signatures
.
There
are
also
“
helper
”
types
and
subroutines
provided
for
the
few
cases
in
which
the
C
++
behavior
cannot
be
directly
mapped
into
Fortran
.
These
interface
and
helper
subroutines
are
compiled
in
to
the
main
OpenMM
library
so
there
is
nothing
special
you
have
to
do
to
get
access
to
them
.
Because
Fortran
is
case
-
insensitive
,
calls
to
Fortran
subroutines
(
however
capitalized
)
are
mapped
by
the
compiler
into
all
-
lowercase
or
all
-
uppercase
names
,
and
different
compilers
use
different
conventions
.
The
automatically
-
generated
OpenMM
Fortran
“
wrapper
”
subroutines
,
which
are
generated
in
C
and
thus
case
-
sensitive
,
are
provided
in
two
forms
for
compatibility
with
the
majority
of
Fortran
compilers
,
including
Intel
Fortran
and
gfortran
.
The
two
forms
are
:
(
1
)
all
-
lowercase
with
a
trailing
underscore
,
and
(
2
)
all
-
uppercase
without
a
trailing
underscore
.
So
regardless
of
the
Fortran
compiler
you
are
using
,
it
should
find
a
suitable
subroutine
to
call
in
the
main
OpenMM
library
.
In
the
:
code
:`/
include
`
subdirectory
of
your
OpenMM
installation
directory
,
there
is
a
machine
-
generated
module
file
:
code
:`
OpenMMFortranModule
.
f90
`
that
must
be
compiled
along
with
any
Fortran
program
that
is
to
make
calls
to
OpenMM
functions
.
(
You
can
look
at
the
:
code
:`
Makefile
`
or
Visual
Studio
solution
file
provided
with
the
OpenMM
examples
to
see
how
to
build
a
program
that
uses
this
module
file
.)
This
module
file
contains
definitions
for
two
modules
:
:
code
:`
MODULE
OpenMM_Types
`
and
:
code
:`
MODULE
OpenMM
`\
;
however
,
only
the
:
code
:`
OpenMM
`
module
will
appear
in
user
programs
(
it
references
the
other
module
internally
).
The
modules
contain
declarations
for
all
the
OpenMM
Fortran
interface
subroutines
,
related
types
,
and
parameters
(
constants
).
Note
that
if
you
follow
our
suggested
structure
,
you
will
not
need
to
:
code
:`
use
`
the
:
code
:`
OpenMM
`
module
in
your
:
code
:`
main
()`
compilation
unit
but
can
instead
use
it
only
in
a
local
file
that
you
write
to
provide
a
simple
interface
to
your
existing
code
(
see
Chapter
:
ref
:`
openmm
-
tutorials
`).
Mapping
from
the
C
++
API
to
the
Fortran
API
===========================================
The
automated
generator
of
the
Fortran
“
wrappers
”
follows
the
translation
strategy
shown
in
:
numref
:`
Table
,
Fortran
API
`\
.
The
idea
is
that
if
you
see
the
construct
on
the
left
in
the
C
++
API
documentation
,
you
should
interpret
it
as
the
corresponding
construct
on
the
right
in
Fortran
.
Please
look
at
the
supplied
example
programs
to
see
how
this
is
done
in
practice
.
Note
that
all
subroutines
and
modules
are
declared
with
“
\
:
code
:`
implicit
none
`\
”
,
meaning
that
the
type
of
every
symbol
is
declared
explicitly
and
should
not
be
inferred
from
the
first
letter
of
the
symbol
name
.
==========================
===================================
========================================================
Construct
C
++
API
declaration
Equivalent
in
Fortran
API
==========================
===================================
========================================================
namespace
OpenMM
\::
OpenMM
\
_
(
prefix
)
class
class
OpenMM
::
ClassName
type
(
OpenMM_ClassName
)
constant
OpenMM
::
RadiansPerDeg
parameter
(
OpenMM_RadiansPerDeg
)
class
enum
OpenMM
::
State
::
Positions
parameter
(
OpenMM_State_Positions
)
constructor
new
OpenMM
::
ClassName
()
|
type
(
OpenMM_ClassName
)
thing
|
call
OpenMM_ClassName_create
(
thing
)
|
(
additional
constructors
are
\
_create_2
(),
etc
.)
destructor
|
OpenMM
::
ClassName
*
thing
;
|
type
(
OpenMM_ClassName
)
thing
|
delete
thing
;
|
call
OpenMM_ClassName_destroy
(
thing
)
class
method
|
OpenMM
::
ClassName
*
thing
;
|
type
(
OpenMM_ClassName
)
thing
|
thing
->
someName
(
args
*)
|
call
OpenMM_ClassName_someName
(
thing
,
args
)
Boolean
(
type
&
constants
)
|
bool
|
integer
*
4
|
true
|
parameter
(
OpenMM_True
=
1
)
|
false
|
parameter
(
OpenMM_False
=
0
)
string
std
::
string
character
(*)
3
-
vector
OpenMM
::
Vec3
real
*
8
vec
(
3
)
arrays
std
::
vector
<
std
::
string
>
|
type
(
OpenMM_StringArray
)
std
::
vector
<
double
>
|
type
(
OpenMM_DoubleArray
)
std
::
vector
<
Vec3
>
|
type
(
OpenMM_Vec3Array
)
std
::
vector
<
std
::
pair
<
int
,
int
>>
|
type
(
OpenMM_BondArray
)
std
::
map
<
std
::
string
,
double
>
|
type
(
OpenMM_ParameterArray
)
==========================
===================================
========================================================
:
autonumber
:`
Table
,
Fortran
API
`\
:
Default
mapping
of
objects
from
the
C
++
API
to
the
Fortran
API
Because
there
are
no
C
++
API
equivalents
to
the
array
types
,
they
are
described
in
detail
below
.
OpenMM_Vec3
helper
type
=======================
Unlike
the
other
OpenMM
objects
which
are
opaque
and
manipulated
via
pointers
,
the
Fortran
API
uses
an
ordinary
:
code
:`
real
`\
:
code
:`*
8
(
3
)`
array
in
place
of
the
:
code
:`
OpenMM
::
Vec3
`
type
.
The
You
can
work
directly
with
the
individual
elements
of
this
type
from
your
Fortran
program
if
you
want
.
For
convenience
,
a
:
code
:`
scale
()`
function
is
provided
that
creates
a
new
Vec3
from
an
old
one
and
a
scale
factor
:
..
code
-
block
::
fortran
subroutine
OpenMM_Vec3_scale
(
vec
,
scale
,
result
)
real
*
8
vec
(
3
),
scale
,
result
(
3
)
No
explicit
:
code
:`
type
`\
:
code
:`(
OpenMM_Vec3
)`
is
provided
in
the
Fortran
API
since
it
is
not
needed
.
Array
helper
types
==================
C
++
has
built
-
in
container
types
:
code
:`
std
::
vector
`
and
:
code
:`
std
::
map
`
which
OpenMM
uses
to
manipulate
arrays
of
objects
.
These
don
’
t
have
direct
equivalents
in
Fortran
,
so
we
supply
special
array
types
for
each
kind
of
object
for
which
OpenMM
creates
containers
.
These
are
:
string
,
double
,
Vec3
,
bond
,
and
parameter
map
.
See
:
numref
:`
Table
,
Fortran
arrays
`
for
the
names
of
the
Fortran
types
for
each
of
these
object
arrays
.
Each
of
the
array
types
provides
these
functions
(
prefixed
by
:
code
:`
OpenMM_
`
and
the
actual
*
Thing
*
name
),
with
the
syntax
shown
conceptually
since
it
differs
slightly
for
each
kind
of
object
.
+-------------------------------------------+--------------------------------------------------------------------------------------------------------+
|
Function
|
Operation
|
+===========================================+========================================================================================================+
|
|
subroutine
create
(
array
,
size
)
|
Create
a
heap
-
allocated
array
of
*
Things
*\
,
with
space
pre
-
allocated
to
hold
:
code
:`
size
`
of
them
.
|
|
|
type
(
OpenMM
\
_
\
*
Thing
*\
Array
)
array
|
You
can
start
at
:
code
:`
size
`\
==
0
if
you
want
since
these
arrays
are
dynamically
resizeable
.
|
|
|
integer
*
4
size
|
|
+-------------------------------------------+--------------------------------------------------------------------------------------------------------+
|
|
subroutine
destroy
(
array
)
|
Free
the
heap
space
that
is
currently
in
use
for
the
passed
-
in
array
of
*
Things
*\
.
|
|
|
type
(
OpenMM
\
_
\
*
Thing
*\
Array
)
array
|
|
+-------------------------------------------+--------------------------------------------------------------------------------------------------------+
|
|
function
getSize
(
array
)
|
Return
the
current
number
of
*
Things
*
in
this
array
.
This
means
you
can
:
code
:`
get
()`
and
|
|
|
type
(
OpenMM
\
_
\
*
Thing
*\
Array
)
array
|
:
code
:`
set
()`
elements
up
to
:
code
:`
getSize
()`\
.
|
|
|
integer
*
4
size
|
|
+-------------------------------------------+--------------------------------------------------------------------------------------------------------+
|
|
subroutine
resize
(
array
,
size
)
|
Change
the
size
of
this
array
to
the
indicated
value
which
may
be
smaller
or
larger
than
the
|
|
|
type
(
OpenMM
\
_
\
*
Thing
*\
Array
)
array
|
current
size
.
Existing
elements
remain
in
their
same
locations
as
long
as
they
still
fit
.
|
|
|
integer
*
4
size
|
|
+-------------------------------------------+--------------------------------------------------------------------------------------------------------+
|
|
subroutine
append
(
array
,
elt
)
|
Add
a
*
Thing
*
to
the
end
of
the
array
,
increasing
the
array
size
by
one
.
The
precise
syntax
depends
|
|
|
type
(
OpenMM
\
_
\
*
Thing
*\
Array
)
array
|
on
the
actual
type
of
*
Thing
*\
;
see
below
.
|
|
|
*
Thing
*
elt
|
|
+-------------------------------------------+--------------------------------------------------------------------------------------------------------+
|
|
subroutine
set
(
array
,
index
,
elt
)
|
Store
a
copy
of
:
code
:`
elt
`
in
the
indicated
element
of
the
array
(
indexed
from
1
).
The
array
must
|
|
|
type
(
OpenMM
\
_
\
*
Thing
*\
Array
)
array
|
be
of
length
at
least
:
code
:`
index
`\
;
you
can
’
t
grow
the
array
with
this
function
.
|
|
|
integer
*
4
size
|
|
|
|
*
Thing
*
elt
|
|
+-------------------------------------------+--------------------------------------------------------------------------------------------------------+
|
|
subroutine
get
(
array
,
index
,
elt
)
|
Retrieve
a
particular
element
from
the
array
(
indexed
from
1
).
Some
*
Things
*
require
more
than
one
|
|
|
type
(
OpenMM
\
_
\
*
Thing
*\
Array
)
array
|
argument
to
return
.
|
|
|
integer
*
4
size
|
|
|
|
*
Thing
*
elt
|
|
+-------------------------------------------+--------------------------------------------------------------------------------------------------------+
:
autonumber
:`
Table
,
Fortran
arrays
`\
:
Generic
description
of
array
helper
types
Here
are
the
exact
declarations
with
deviations
from
the
generic
description
noted
,
for
each
of
the
array
types
.
OpenMM_DoubleArray
------------------
..
code
-
block
::
fortran
subroutine
OpenMM_DoubleArray_create
(
array
,
size
)
integer
*
4
size
type
(
OpenMM_DoubleArray
)
array
subroutine
OpenMM_DoubleArray_destroy
(
array
)
type
(
OpenMM_DoubleArray
)
array
function
OpenMM_DoubleArray_getSize
(
array
)
type
(
OpenMM_DoubleArray
)
array
integer
*
4
OpenMM_DoubleArray_getSize
subroutine
OpenMM_DoubleArray_resize
(
array
,
size
)
type
(
OpenMM_DoubleArray
)
array
integer
*
4
size
subroutine
OpenMM_DoubleArray_append
(
array
,
value
)
type
(
OpenMM_DoubleArray
)
array
real
*
8
value
subroutine
OpenMM_DoubleArray_set
(
array
,
index
,
value
)
type
(
OpenMM_DoubleArray
)
array
integer
*
4
index
real
*
8
value
subroutine
OpenMM_DoubleArray_get
(
array
,
index
,
value
)
type
(
OpenMM_DoubleArray
)
array
integer
*
4
index
real
*
8
value
OpenMM_StringArray
------------------
..
code
-
block
::
fortran
subroutine
OpenMM_StringArray_create
(
array
,
size
)
integer
*
4
size
type
(
OpenMM_StringArray
)
array
subroutine
OpenMM_StringArray_destroy
(
array
)
type
(
OpenMM_StringArray
)
array
function
OpenMM_StringArray_getSize
(
array
)
type
(
OpenMM_StringArray
)
array
integer
*
4
OpenMM_StringArray_getSize
subroutine
OpenMM_StringArray_resize
(
array
,
size
)
type
(
OpenMM_StringArray
)
array
integer
*
4
size
subroutine
OpenMM_StringArray_append
(
array
,
str
)
type
(
OpenMM_StringArray
)
array
character
(*)
str
subroutine
OpenMM_StringArray_set
(
array
,
index
,
str
)
type
(
OpenMM_StringArray
)
array
integer
*
4
index
character
(*)
str
subroutine
OpenMM_StringArray_get
(
array
,
index
,
str
)
type
(
OpenMM_StringArray
)
array
integer
*
4
index
character
(*)
str
OpenMM_Vec3Array
----------------
..
code
-
block
::
fortran
subroutine
OpenMM_Vec3Array_create
(
array
,
size
)
integer
*
4
size
type
(
OpenMM_Vec3Array
)
array
subroutine
OpenMM_Vec3Array_destroy
(
array
)
type
(
OpenMM_Vec3Array
)
array
function
OpenMM_Vec3Array_getSize
(
array
)
type
(
OpenMM_Vec3Array
)
array
integer
*
4
OpenMM_Vec3Array_getSize
subroutine
OpenMM_Vec3Array_resize
(
array
,
size
)
type
(
OpenMM_Vec3Array
)
array
integer
*
4
size
subroutine
OpenMM_Vec3Array_append
(
array
,
vec
)
type
(
OpenMM_Vec3Array
)
array
real
*
8
vec
(
3
)
subroutine
OpenMM_Vec3Array_set
(
array
,
index
,
vec
)
type
(
OpenMM_Vec3Array
)
array
integer
*
4
index
real
*
8
vec
(
3
)
subroutine
OpenMM_Vec3Array_get
(
array
,
index
,
vec
)
type
(
OpenMM_Vec3Array
)
array
integer
*
4
index
real
*
8
vec
(
3
)
OpenMM_BondArray
----------------
Note
that
bonds
are
specified
by
pairs
of
integers
(
the
atom
indices
).
The
:
code
:`
get
()`
method
returns
those
in
a
pair
of
final
arguments
rather
than
as
its
functional
return
.
..
code
-
block
::
fortran
subroutine
OpenMM_BondArray_create
(
array
,
size
)
integer
*
4
size
type
(
OpenMM_BondArray
)
array
subroutine
OpenMM_BondArray_destroy
(
array
)
type
(
OpenMM_BondArray
)
array
function
OpenMM_BondArray_getSize
(
array
)
type
(
OpenMM_BondArray
)
array
integer
*
4
OpenMM_BondArray_getSize
subroutine
OpenMM_BondArray_resize
(
array
,
size
)
type
(
OpenMM_BondArray
)
array
integer
*
4
size
subroutine
OpenMM_BondArray_append
(
array
,
particle1
,
particle2
)
type
(
OpenMM_BondArray
)
array
integer
*
4
particle1
,
particle2
subroutine
OpenMM_BondArray_set
(
array
,
index
,
particle1
,
particle2
)
type
(
OpenMM_BondArray
)
array
integer
*
4
index
,
particle1
,
particle2
subroutine
OpenMM_BondArray_get
(
array
,
index
,
particle1
,
particle2
)
type
(
OpenMM_BondArray
)
array
integer
*
4
index
,
particle1
,
particle2
OpenMM_ParameterArray
---------------------
OpenMM
returns
references
to
internal
:
code
:`
ParameterArrays
`
but
does
not
support
user
-
created
:
code
:`
ParameterArrays
`\
,
so
only
the
:
code
:`
get
()`
and
:
code
:`
getSize
()`
functions
are
available
.
Also
,
note
that
since
this
is
actually
a
map
rather
than
an
array
,
the
“
index
”
is
the
*
name
*
of
the
parameter
rather
than
its
ordinal
.
..
code
-
block
::
fortran
function
OpenMM_ParameterArray_getSize
(
array
)
type
(
OpenMM_ParameterArray
)
array
integer
*
4
OpenMM_ParameterArray_getSize
subroutine
OpenMM_ParameterArray_get
(
array
,
name
,
param
)
type
(
OpenMM_ParameterArray
)
array
character
(*)
name
character
(*)
param
Python
API
**********
Installing
the
Python
API
=========================
There
are
currently
two
types
of
packages
for
installing
the
Python
API
.
One
contains
wrapper
source
code
for
Unix
-
type
machines
(
including
Linux
and
Mac
operating
systems
).
You
will
need
a
C
++
compiler
to
install
it
using
this
type
of
package
.
The
other
type
of
installation
package
is
a
binary
package
which
contains
compiled
wrapper
code
for
Windows
machines
(
no
compilers
are
needed
to
install
binary
packages
).
Installing
on
Windows
---------------------
OpenMM
on
Windows
only
works
with
Python
3.3
,
so
make
sure
that
version
is
installed
before
you
try
installing
.
For
Python
installation
packages
and
instructions
,
go
to
http
://
python
.
org
.
Note
that
if
you
have
a
64
-
bit
machine
,
you
should
still
install
the
32
-
bit
version
of
Python
since
the
OpenMM
Python
API
binary
is
32
-
bit
.
We
suggest
that
you
install
Python
using
the
default
options
.
Double
click
on
the
Python
API
Installer
icon
,
located
in
the
top
level
directory
for
the
OpenMM
installation
(
by
default
,
this
is
C
:\
Program
Files
\
OpenMM
).
This
will
install
the
OpenMM
package
into
the
Python
installation
area
.
If
you
have
more
than
one
Python
installation
,
you
will
be
asked
which
Python
to
use
—
make
sure
to
select
Python
3.3
.
Installing
on
Linux
and
Mac
---------------------------
Make
sure
you
have
Python
2.6
or
later
installed
.
For
Python
installation
packages
and
instructions
,
go
to
http
://
python
.
org
.
If
you
do
not
have
the
correct
Python
version
,
install
a
valid
version
using
the
default
options
.
Most
versions
of
Linux
and
Mac
OS
X
have
a
suitable
Python
preinstalled
.
You
can
check
by
typing
“
\
:
code
:`
python
`
|--|\
:
code
:`
version
`\
”
in
a
terminal
window
.
You
must
have
a
C
++
compiler
to
install
the
OpenMM
Python
API
.
If
you
are
using
a
Mac
,
install
Apple
's Xcode development tools
(http://developer.apple.com/TOOLS/Xcode) to get the needed compiler. On other
Unix-type systems, install gcc or clang.
The install.sh script installs the Python API automatically as part of the
installation process, so you probably already have it installed. If for some
reason you need to install it manually, you can do that with the
:code:`setup.py` script included with OpenMM. Before executing this script,
you must set two environment variables: :code:`OPENMM_INCLUDE_PATH` must
point to the directory containing OpenMM header files, and
:code:`OPENMM_LIB_PATH` must point to the directory containing OpenMM library
files. Assuming OpenMM is installed in the default location
(\ :code:`/usr/local/openmm`\ ), you would type the following commands.
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
python setup.py install
If you are compiling OpenMM from source, you can also install by building the
“PythonInstall” target:
:code:`make PythonInstall` OR :code:`sudo make PythonInstall`
Mapping from the C++ API to the Python API
==========================================
The Python API follows the C++ API as closely as possible. There are three
notable differences:
#. The :code:`getState()` method in the :code:`Context` class takes
Pythonic-type arguments to indicate which state variables should be made
available. For example:
::
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 bond’s parameters as follows:
::
int particle1, particle2;
double length, k;
f.getBondParameters(i, particle1, particle2, length, k);
In Python, the equivalent code is:
::
[particle1, particle2, length, k] = f.getBondParameters(i)
#. Unlike C++, the Python API accepts and returns quantities with units attached
to most values (see the “Units and dimensional analysis” section below for
details). In short, this means that while values in C++ have *implicit*\
units, the Python API returns objects that have values and *explicit* units.
Mechanics of using the Python API
=================================
When using the Python API, be sure to include the GPU support
libraries in your library path, just as you would for a C++ application. This
is set with the :code:`LD_LIBRARY_PATH` environment variable on Linux,
:code:`DYLD_LIBRARY_PATH` on Mac, or :code:`PATH` on Windows. See
Chapter :ref:`installing-openmm` for details.
The Python API is contained in the simtk.openmm package, while the units code is
contained in the simtk.units package. (The application layer, described in the
Application Guide, is contained in the simtk.openmm.app package.) A program
using it will therefore typically begin
::
import simtk.openmm as mm
import simtk.unit as unit
Creating and using OpenMM objects is then done exactly as in C++:
::
system = mm.System()
nb = mm.NonbondedForce()
nb.setNonbondedMethod(mm.NonbondedForce.CutoffNonPeriodic)
nb.setCutoffDistance(1.2*unit.nanometer)
system.addForce(nb)
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.
Units and dimensional analysis
==============================
Why does the Python API include units?
--------------------------------------
The C++ API for OpenMM uses an *implicit* set of units for physical
quantities such as lengths, masses, energies, etc. These units are based on
daltons, nanometers, and picoseconds for the mass, length, and time dimensions,
respectively. When using the C++ API, it is very important to ensure that
quantities being manipulated are always expressed in terms of these units. For
example, if you read in a distance in Angstroms, you must multiply that distance
by a conversion factor to turn it into nanometers before using it in the C++
API. Such conversions can be a source of tedium and errors. This is true in
many areas of scientific programming. Units confusion was blamed for the loss
of the Mars Climate Orbiter spacecraft in 1999, at a cost of more than $100
million. Units were introduced in the Python API to minimize the chance of such
errors.
The Python API addresses the potential problem of conversion errors by using
quantities with explicit units. If a particular distance is expressed in
Angstroms, the Python API will know that it is in Angstroms. When the time
comes to call the C++ API, it will understand that the quantity must be
converted to nanometers. You, the programmer, must declare upfront that the
quantity is in Angstrom units, and the API will take care of the details from
then on. Using explicit units is a bit like brushing your teeth: it requires
some effort upfront, but it probably saves you trouble in the long run.
Quantities, units, and dimensions
---------------------------------
The explicit unit system is based on three concepts: Dimensions, Units, and
Quantities.
Dimensions are measurable physical concepts such as mass, length, time, and
energy. Energy is actually a composite dimension based on mass, length, and
time.
A Unit defines a linear scale used to measure amounts of a particular physical
Dimension. Examples of units include meters, seconds, joules, inches, and
grams.
A Quantity is a specific amount of a physical Dimension. An example of a
quantity is “0.63 kilograms”. A Quantity is expressed as a combination of a
value (e.g., 0.63), and a Unit (e.g., kilogram). The same Quantity can be
expressed in different Units.
The set of BaseDimensions defined in the simtk.unit module includes:
* mass
* length
* time
* temperature
* amount
* charge
* luminous intensity
These are not precisely the same list of base dimensions used in the SI unit
system. SI defines “current” (charge per time) as a base unit, while simtk.unit
uses “charge”. And simtk.unit treats angle as a dimension, even though angle
quantities are often considered dimensionless. In this case, we choose to err
on the side of explicitness, particularly because interconversion of degrees and
radians is a frequent source of unit headaches.
Units examples
--------------
Many common units are defined in the simtk.unit module.
::
from simtk.unit import nanometer, angstrom, dalton
Sometimes you don’t want to type the full unit name every time, so you can
assign it a shorter name using the :code:`as` functionality:
::
from simtk.unit import nanometer as nm
New quantities can be created from a value and a unit. You can use either the
multiply operator (‘*’) or the explicit Quantity constructor:
::
from simk.unit import nanometer, Quantity
# construct a Quantity using the multiply operator
bond_length = 1.53 * nanometer
# equivalently using the explicit Quantity constructor
bond_length = Quantity(1.53, nanometer)
# or more verbosely
bond_length = Quantity(value=1.53, unit=nanometer)
Arithmetic with units
---------------------
Addition and subtraction of quantities is only permitted between quantities that
share the same dimension. It makes no sense to add a mass to a distance. If
you attempt to add or subtract two quantities with different dimensions, an
exception will be raised. This is a good thing; it helps you avoid errors.
::
x = 5.0*dalton + 4.3*nanometer; # error
Addition or subtraction of quantities with the same dimension, but different
units, is fine, and results in a new quantity created using the correct
conversion factor between the units used.
::
x = 1.3*nanometer + 5.6*angstrom; # OK, result in nanometers
Quantities can be added and subtracted. Naked Units cannot.
Multiplying or dividing two quantities creates a new quantity with a composite
dimension. For example, dividing a distance by a time results in a velocity.
::
from simtk.unit import kilogram, meter, second
a = 9.8 * meter / second**2; # acceleration
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.
::
mps = meter / second
Unlike amount (moles), angle (radians) is arguably dimensionless. But simtk.unit
treats angle as another dimension. Use the trigonometric functions from the
simtk.unit module (not those from the Python math module!) when dealing with
Units and Quantities.
::
from simtk.unit import sin, cos, acos
x = sin(90.0*degrees)
angle = acos(0.68); # returns an angle quantity (in radians)
The method :code:`pow()` is a built-in Python method that works with
Quantities and Units.
::
area = pow(3.0*meter, 2)
# or, equivalently
area = (3.0*meter)**2
# or
area = 9.0*(meter**2)
The method :code:`sqrt()` is not as built-in as :code:`pow()`\ . Do not
use the Python :code:`math.sqrt()` method with Units and Quantities. Use
the :code:`simtk.unit.sqrt()` method instead:
::
from simtk.unit import sqrt
side_length = sqrt(4.0*meter**2)
Atomic scale mass and energy units are “per amount”
---------------------------------------------------
Mass and energy units at the atomic scale are specified “per amount” in the
simtk.unit module. Amount (mole) is one of the seven fundamental dimensions in
the SI unit system. The atomic scale mass unit, dalton, is defined as grams
per mole. The dimension of dalton is therefore mass/amount, instead of simply
mass. Similarly, the atomic scale energy unit, kilojoule_per_mole (and
kilocalorie_per_mole) has “per amount” in its dimension. Be careful to always
use “per amount” mass and energy types at the atomic scale, and your dimensional
analysis should work out properly.
The energy unit kilocalories_per_mole does not have the same Dimension as the
macroscopic energy unit kilocalories. Molecular scientists sometimes use the
word "kilocalories" when they mean "kilocalories per mole". Use "kilocalories
per mole" or"kilojoules per mole" for molecular energies. Use "kilocalories"
for the metabolic energy content of your lunch. The energy unit
kilojoule_per_mole happens to go naturally with the units nanometer,
picoseconds, and dalton. This is because 1 kilojoule/mole happens to be equal
to 1 gram-nanometer\ :sup:`2`\ /mole-picosecond\ :sup:`2`\ , and is therefore
consistent with the molecular dynamics unit system used in the C++ OpenMM API.
These "per mole" units are what you should be using for molecular calculations,
as long as you are using SI / cgs / calorie sorts of units.
SI prefixes
-----------
Many units with SI prefixes such as “milligram” (milli) and “kilometer” (kilo)
are provided in the simtk.unit module. Others can be created by multiplying a
prefix symbol by a non-prefixed unit:
::
from simtk.unit import mega, kelvin
megakelvin = mega * kelvin
t = 8.3 * megakelvin
Only grams and meters get all of the SI prefixes (from yotto-(10\ :sup:`-24`\ )
to yotta-(10\ :sup:`24`\ )) automatically.
Converting to different units
-----------------------------
Use the :code:`Quantity.in_units_of()` method to create a new Quantity with
different units.
::
from simtk.unit import nanosecond, fortnight
x = (175000*nanosecond).in_units_of(fortnight)
When you want a plain number out of a Quantity, use the :code:`value_in_unit()` method:
::
from simtk.unit import femtosecond, picosecond
t = 5.0*femtosecond
t_just_a_number = t.value_in_unit(picoseconds)
Using :code:`value_in_unit()` puts the responsibility for unit analysis back
into your hands, and it should be avoided. It is sometimes necessary, however,
when you are called upon to use a non-units-aware Python API.
Lists, tuples, vectors, numpy arrays, and Units
-----------------------------------------------
Units can be attached to containers of numbers to create a vector quantity. The
simtk.unit module overloads the :code:`__setitem__` and
:code:`__getitem__` methods for these containers to ensure that Quantities go
in and out.
::
>>> a = Vec3(1,2,3) * nanometers
>>> print a
(1, 2, 3) nm
>>> print a.in_units_of(angstroms)
(10.0, 20.0, 30.0) A
>>> s2 = [[1,2,3],[4,5,6]] * centimeter
>>> print s2
[[1, 2, 3], [4, 5, 6]] cm
>>> print s2 / millimeter
[[10.0, 20.0, 30.0], [40.0, 50.0, 60.0]]
>>> import numpy
>>> a = Quantity(numpy.array([1,2,3]), centimeter)
>>> print a
[1 2 3] cm
>>> print a / millimeter
[ 10. 20. 30.]
Converting a whole list to different units at once is much faster than
converting each element individually. For example, consider the following code
that prints out the position of every particle in a State, as measured in
Angstroms:
::
for v in state.getPositions():
print v.value_in_unit(angstrom)
This can be rewritten as follows:
::
for v in state.getPositions().value_in_unit(angstrom):
print v
The two versions produce identical results, but the second one will run faster,
and therefore is preferred.
.. _examples-of-openmm-integration:
Examples of OpenMM Integration
###############################
GROMACS
*******
GROMACS is a large, complex application written primarily in C. The
considerations involved in adapting it to use OpenMM are likely to be similar to
those faced by developers of other existing applications.
The first principle we followed in adapting GROMACS was to keep all OpenMM-
related code isolated to just a few files, while modifying as little of the
existing GROMACS code as possible. This minimized the risk of breaking existing
parts of the code, while making the OpenMM-related parts as easy to work with as
possible. It also minimized the need for C code to invoke the C++ API. (This
would not be an issue if we used the OpenMM C API wrapper, but that is less
convenient than the C++ API, and placing all of the OpenMM calls into separate
C++ files solves the problem equally well.) Nearly all of the OpenMM-specific
code is contained in a single file, openmm_wrapper.cpp. It defines four
functions which encapsulate all of the interaction between OpenMM and the rest
of GROMACS:
\ :code:`openmm_init()`\ : As arguments, this function takes pointers to lots of
internal GROMACS data structures that describe the simulation to be run. It
creates a System, Integrator, and Context based on them, then returns an opaque
reference to an object containing them. That reference is an input argument to
all of the other functions defined in openmm_wrapper.cpp. This allows
information to be passed between those functions without exposing it to the rest
of GROMACS.
\ :code:`openmm_take_one_step()`\ : This calls :code:`step(1)` on the
Integrator that was created by :code:`openmm_init()`\ .
\ :code:`openmm_copy_state()`\ : This calls :code:`getState()` on the
Context that was created by :code:`openmm_init()`\ , and then copies
information from the resulting State into various GROMACS data structures. This
function is how state data generated by OpenMM is passed back to GROMACS for
output, analysis, etc.
\ :code:`openmm_cleanup()`\ : This is called at the end of the simulation. It
deletes all the objects that were created by :code:`openmm_init()`\ .
This set of functions defines the interactions between GROMACS and OpenMM:
copying information from the application to OpenMM, performing integration,
copying information from OpenMM back to the application, and freeing resources
at the end of the simulation. While the details of their implementations are
specific to GROMACS, this overall pattern is fairly generic. A similar set of
functions can be used for many other applications as well.
TINKER-OpenMM
*************
TINKER is written primarily in Fortran, and uses common blocks extensively to
store application-wide parameters. Rather than modify the TINKER build scripts
to allow C++ code, it was decided to use the OpenMM C API instead. Despite
these differences, the overall approach used to add OpenMM support was very
similar to that used for GROMACS.
TINKER-OpenMM allows OpenMM to be used to calculate forces and energies and to
perform the integration in the main molecular dynamics loop. The only changes to
the TINKER source code are in the file :code:`dynamic.f` for the setup and
running of a simulation. An added file, :code:`dynamic_openmm.c`\ , contains
the interface C code between TINKER and OpenMM.
The flow of the molecular dynamics simulation using OpenMM is as follows:
#. The TINKER code is used to read the AMOEBA parameter file, the
:code:`*.xyz` and :code:`*.key` files. It then parses the command-line
options.
#. The routine :code:`map_common_blocks_to_c_data_structs()` is
called to map the FORTRAN common blocks to C data structures used in setting the
parameters used by OpenMM.
#. The routine :code:`openmm_validate()` is called from
:code:`dynamic.f` before the main loop. This routine checks that all required
options and settings obtained from the input in step (1) and common blocks in
step (2) are available. If an option or setting is unsupported, the program
exits with an appropriate message. The routine :code:`openmm_validate()`
and the other OpenMM interface methods are in the file
:code:`dynamic_openmm.c`\ .
#. :code:`openmm_init()` is called to create the OpenMM System,
Integrator and Context objects..
#. :code:`openmm_take_steps()` is called to take a specified number
of time steps.
#. :code:`openmm_update()` is then called to retrieve the state
(energies/positions/velocities) and populate the appropriate TINKER data
structures. These values are converted from the OpenMM units of kJ/nm to kcal/Å
when populating the TINKER arrays.
#. Once the main loop has completed, the routine
:code:`openmm_cleanup()` is called to delete the OpenMM objects and release
resources being used on the GPU.
Testing and Validation of OpenMM
################################
The goal of testing and validation is to make sure that OpenMM works correctly.
That means that it runs without crashing or otherwise failing, and that it
produces correct results. Furthermore, it must work correctly on a variety of
hardware platforms (e.g. different models of GPU), software platforms (e.g.
operating systems and OpenCL implementations), and types of simulations.
Three types of tests are used to validate OpenMM:
* **Unit tests:** These are small tests designed to test specific features
or pieces of code in isolation. For example, a test of HarmonicBondForce might
create a System with just a few particles and bonds, compute the forces and
energy, and compare them to the analytically expected values. There are
thousands of unit tests that collectively cover all of OpenMM.
* **System tests:** Whereas unit tests validate small features in
isolation, system tests are designed to validate the entire library as a whole.
They simulate realistic models of biomolecules and perform tests that are likely
to fail if any problem exists anywhere in the library.
* **Direct comparison between OpenMM and other programs:** The third type
of validation performed is a direct comparison of the individual forces computed
by OpenMM to those computed by other programs for a collection of biomolecules.
Each type of test is outlined in greater detail below; a discussion of the
current status of the tests is then given.
Description of Tests
********************
Unit tests
===========
The unit tests are with the source code, so if you build from source you can run
them yourself. See Section :ref:`test-your-build` for details. When you run the tests
(for example, by typing “make test” on Linux or Mac), it should produce output
something like this:
::
Start 1: TestReferenceAndersenThermostat
1/317 Test #1: TestReferenceAndersenThermostat .............. Passed 0.26 sec
Start 2: TestReferenceBrownianIntegrator
2/317 Test #2: TestReferenceBrownianIntegrator .............. Passed 0.13 sec
Start 3: TestReferenceCheckpoints
3/317 Test #3: TestReferenceCheckpoints ..................... Passed 0.02 sec
... <many other tests> ...
Each line represents a test suite, which may contain multiple unit tests. If
all tests within a suite passed, it prints the word “Passed” and how long the
suite took to execute. Otherwise it prints an error message. If any tests
failed, you can then run them individually (each one is a separate executable)
to get more details on what went wrong.
System tests
============
Several different types of system tests are performed. Each type is run for a
variety of systems, including both proteins and nucleic acids, and involving
both implicit and explicit solvent. The full suite of tests is repeated for
both the CUDA and OpenCL platforms, using both single and double precision (and
for the integration tests, mixed precision as well), on a variety of operating
systems and hardware. There are four types of tests:
* **Consistency between platforms:** The forces and energy are computed
using the platform being tested, then compared to ones computed with the
Reference platform. The results are required to agree to within a small
tolerance.
* **Energy-force consistency:** This verifies that the force really is the
gradient of the energy. It first computes the vector of forces for a given
conformation. It then generates four other conformations by displacing the
particle positions by small amounts along the force direction. It computes the
energy of each one, uses those to calculate a fourth order finite difference
approximation to the derivative along that direction, and compares it to the
actual forces. They are required to agree to within a small tolerance.
* **Energy conservation:** The system is simulated at constant energy using
a Verlet integrator, and the total energy is periodically recorded. A linear
regression is used to estimate the rate of energy drift. In addition, all
constrained distances are monitored during the simulation to make sure they
never differ from the expected values by more than the constraint tolerance.
* **Thermostability:** The system is simulated at constant temperature
using a Langevin integrator. The mean kinetic energy over the course of the
simulation is computed and compared to the expected value based on the
temperature. In addition, all constrained distances are monitored during the
simulation to make sure they never differ from the expected values by more than
the constraint tolerance.
If you want to run the system tests yourself, they can be found in the
Subversion repository at https://simtk.org/svn/pyopenmm/trunk/test/system-tests.
Check out that directory, then execute the runAllTests.sh shell script. It will
create a series of files with detailed information about the results of the
tests. Be aware that running the full test suite may take a long time (possibly
several days) depending on the speed of your GPU.
Direct comparisons between OpenMM and other programs
====================================================
As a final check, identical systems are set up in OpenMM and in another program
(Gromacs 4.5 or Tinker 6.1), each one is used to compute the forces on atoms,
and the results are directly compared to each other.
Test Results
************
In this section, we highlight the major results obtained from the tests
described above. They are not exhaustive, but should give a reasonable idea of
the level of accuracy you can expect from OpenMM.
Comparison to Reference Platform
================================
The differences between forces computed with the Reference platform and those
computed with the OpenCL or CUDA platform are shown in
:numref:`Table,force comparison between platforms`\ . For every
atom, the relative difference between platforms was computed as
2·\|F\ :sub:`ref`\ –F\ :sub:`test`\ \|/(\|F\ :sub:`ref`\ \|+|F\ :sub:`test`\ \|), where
F\ :sub:`ref` is the force computed by the Reference platform and F\ :sub:`test`
is the force computed by the platform being tested (OpenCL or CUDA). The median
over all atoms in a given system was computed to estimate the typical force
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)
==================================== ======================== ==================== =================== =====================
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`
HarmonicAngleForce 2.25·10\ :sup:`-5` 4.21·10\ :sup:`-7` 2.27·10\ :sup:`-5` 4.21·10\ :sup:`-7`
PeriodicTorsionForce 8.23·10\ :sup:`-7` 2.44·10\ :sup:`-7` 9.27·10\ :sup:`-7` 2.56·10\ :sup:`-7`
RBTorsionForce 4.86·10\ :sup:`-6` 1.46·10\ :sup:`-7` 4.72·10\ :sup:`-6` 1.4·10\ :sup:`-8`
NonbondedForce (no cutoff) 1.49·10\ :sup:`-6` 6.49·10\ :sup:`-8` 1.49·10\ :sup:`-6` 6.49·10\ :sup:`-8`
NonbondedForce (cutoff, nonperiodic) 9.74·10\ :sup:`-7` 4.88·10\ :sup:`-9` 9.73·10\ :sup:`-7` 4.88·10\ :sup:`-9`
NonbondedForce (cutoff, periodic) 9.82·10\ :sup:`-7` 4.88·10\ :sup:`-9` 9.8·10\ :sup:`-7` 4.88·10\ :sup:`-9`
NonbondedForce (Ewald) 1.33·10\ :sup:`-6` 5.22·10\ :sup:`-9` 1.33·10\ :sup:`-6` 5.22·10\ :sup:`-9`
NonbondedForce (PME) 3.99·10\ :sup:`-5` 4.08·10\ :sup:`-6` 3.99·10\ :sup:`-5` 4.08·10\ :sup:`-6`
GBSAOBCForce (no cutoff) 3.0·10\ :sup:`-6` 1.76·10\ :sup:`-7` 3.09·10\ :sup:`-6` 9.4·10\ :sup:`-8`
GBSAOBCForce (cutoff, nonperiodic) 2.77·10\ :sup:`-6` 1.76·10\ :sup:`-7` 2.95·10\ :sup:`-6` 9.33·10\ :sup:`-8`
GBSAOBCForce (cutoff, periodic) 2.61·10\ :sup:`-6` 1.78·10\ :sup:`-7` 2.77·10\ :sup:`-6` 9.24·10\ :sup:`-8`
==================================== ======================== ==================== =================== =====================
:autonumber:`Table,force comparison between platforms`\ : Median relative difference in forces between Reference platform and
OpenCL/CUDA platform
Energy Conservation
===================
:numref:`Figure,energy drift` shows the total system energy versus time for three simulations of
ubiquitin in OBC implicit solvent. All three simulations used the CUDA
platform, a Verlet integrator, a time step of 0.5 fs, no constraints, and no
cutoff on the nonbonded interactions. They differ only in the level of numeric
precision that was used for calculations (see Chapter :ref:`platform-specific-properties`\ ).
.. figure:: ../images/EnergyDrift.png
:align: center
:autonumber:`Figure,energy drift`: Total energy versus time for simulations run in three different
precision modes.
For the mixed and double precision simulations, the drift in energy is almost
entirely diffusive with negligible systematic drift. The single precision
simulation has a more significant upward drift with time, though the rate of
drift is still small compared to the rate of short term fluctuations. Fitting a
straight line to each curve gives a long term rate of energy drift of 3.98
kJ/mole/ns for single precision, 0.217 kJ/mole/ns for mixed precision, and
0.00100 kJ/mole/ns for double precision. In the more commonly reported units of
kT/ns/dof, these correspond to 4.3·10\ :sup:`-4` for single precision,
2.3·10\ :sup:`-5` for mixed precision, and 1.1·10\ :sup:`-7` for double precision.
Be aware that different simulation parameters will give different results.
These simulations were designed to minimize all sources of error except those
inherent in OpenMM. There are other sources of error that may be significant in
other situations. In particular:
* Using a larger time step increases the integration error (roughly
proportional to *dt*\ :sup:`2`\ ).
* If a system involves constraints, the level of error will depend strongly on
the constraint tolerance specified by the Integrator.
* When using Ewald summation or Particle Mesh Ewald, the accuracy will depend
strongly on the Ewald error tolerance.
* Applying a distance cutoff to implicit solvent calculations will increase the
error, and the shorter the cutoff is, the greater the error will be.
As a result, the rate of energy drift may be much greater in some simulations
than in the ones shown above.
Comparison to Gromacs
=====================
OpenMM and Gromacs 4.5.5 were each used to compute the atomic forces for
dihydrofolate reductase (DHFR) in implicit and explicit solvent. The implicit
solvent calculations used the OBC solvent model and no cutoff on nonbonded
interactions. The explicit solvent calculations used Particle Mesh Ewald and a
1 nm cutoff on direct space interactions. For OpenMM, the Ewald error tolerance
was set to 10\ :sup:`-6`\ . For Gromacs, :code:`fourierspacing` was set to
0.07 and :code:`ewald_rtol` to 10\ :sup:`-6`\ . No constraints were applied
to any degrees of freedom. Both programs used single precision. The test was
repeated for OpenCL, CUDA, and CPU platforms.
For every atom, the relative difference between OpenMM and Gromacs was computed
as 2·\|F\ :sub:`MM`\ –F\ :sub:`Gro`\ \|/(\|F\ :sub:`MM`\ \|+\|F\ :sub:`Gro`\ \|),
where F\ :sub:`MM` is the force computed by OpenMM and F\ :sub:`Gro` is the
force computed by Gromacs. The median over all atoms is shown in :numref:`Table,comparison to Gromacs`\ .
============= =================== =================== ===================
Solvent Model OpenCL CUDA CPU
============= =================== =================== ===================
Implicit 7.66·10\ :sup:`-6` 7.68·10\ :sup:`-6` 1.94·10\ :sup:`-5`
Explicit 6.77·10\ :sup:`-5` 6.78·10\ :sup:`-5` 9.89·10\ :sup:`-5`
============= =================== =================== ===================
:autonumber:`Table,comparison to Gromacs`\ : Median relative difference in forces between OpenMM and Gromacs
AMOEBA Plugin
#############
OpenMM |version| provides a plugin that implements the AMOEBA polarizable atomic
multipole force field from Jay Ponder’s lab. The AMOEBA force field may be used
through OpenMM’s Python application layer. We have also created a modified
version of TINKER (referred to as TINKER-OpenMM here) that uses OpenMM to
accelerate AMOEBA simulations. TINKER-OpenMM can be created from a TINKER
package using three files made available through the OpenMM home page. OpenMM
AMOEBA Force and System objects containing AMOEBA forces can be serialized.
At present, AMOEBA is only supported on the CUDA and Reference platforms, not on
the OpenCL platform.
In the following sections, the individual forces and options available in the
plugin are listed, and the steps required to build and use the plugin and
TINKER-OpenMM are outlined. Validation results are also reported. Benchmarks
can be found on the OpenMM wiki at http://wiki.simtk.org/openmm/Benchmarks.
OpenMM AMOEBA Supported Forces and Options
*******************************************
.. _supported-forces-and-options:
Supported Forces and Options
============================
The AMOEBA force terms implemented in OpenMM are listed in :numref:`Table,mapping from TINKER` along
with the supported and unsupported options. TINKER options that are not
supported for any OpenMM force include the grouping of atoms (e.g. protein
chains), the infinite polymer check, and no exclusion of particles from
energy/force calculations (‘active’/’inactive’ particles). The virial is not
calculated for any force.
All rotation axis types are supported: ‘Z-then-X’, ‘Bisector’, ‘Z-Bisect’,
‘3-Fold’, ‘Z-Only’.
================================= ================================== ======================================================================================================================================================================================
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
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
================================= ================================== ======================================================================================================================================================================================
:autonumber:`Table,mapping from TINKER`\ : Mapping between TINKER and OpenMM AMOEBA forces
Some specific details to be aware of are the following:
* Forces available in TINKER but not implemented in the OpenMM AMOEBA plugin
include the following: angle-angle, out-of-plane distance, improper dihedral,
improper torsion, stretch-torsion, charge-charge, atomwise charge-dipole,
dipole-dipole, reaction field, ligand field, restraint, scf molecular orbital
calculation; strictly speaking, these are not part of the AMOEBA force field.
* Implicit solvent in TINKER-OpenMM is implemented with key file entry ‘solvate
GK’. The entry ‘born-radius grycuk’ should also be included; only the ‘grycuk’
option for calculating the Born radii is available in the plugin.
* In TINKER, the nonpolar cavity contribution to the solvation term is
calculated using an algorithm that does not map well to GPUs. Instead the
OpenMM plugin uses the TINKER version of the ACE approximation to estimate the
cavity contribution to the SASA.
* Calculations using the CUDA platform may be done in either single or double
precision; for the Reference platform, double precision is used. TINKER uses
double precision.
* The TINKER parameter files for the AMOEBA force-field parameters are based on
units of kilocalorie/Å, whereas OpenMM uses units of kilojoules/nanometer; both
TINKER and OpenMM use picoseconds time units. Hence, in mapping the force-field
parameters from TINKER files to OpenMM, many of the parameter values must be
converted to the OpenMM units. The setup methods in the TINKER-OpenMM
application perform the required conversions.
Supported Integrators
=====================
In addition to the limitations to the forces outlined above, TINKER-OpenMM can
only use either the ‘Verlet’ or ‘Stochastic’ integrators when the OpenMM plugin
is used; an equivalent to the TINKER ‘Beeman’ integrator is unavailable in
OpenMM.
TINKER-OpenMM
**************
Building TINKER-OpenMM (Linux)
==============================
Below are instructions for building TINKER-OpenMM in Linux.
#. To build and install the OpenMM plugin libraries, follow the steps outlined
in Chapter :ref:`compiling-openmm-from-source-code` (Compiling OpenMM from Source Code).
You will need to set the following options to ‘ON’ when you run CMake:
#. OPENMM_BUILD_AMOEBA_PLUGIN
#. OPENMM_BUILD_AMOEBA_CUDA_LIB
#. OPENMM_BUILD_CUDA_LIB
#. OPENMM_BUILD_C_AND_FORTRAN_WRAPPERS
#. Download the complete TINKER distribution from http://dasher.wustl.edu/ffe/
and unzip/untar the file.
#. Obtain the modified TINKER file :code:`dynamic.f`\ , the interface file
:code:`dynamic_openmm.c` and the :code:`Makefile` from the “Downloads”
section of OpenMM’s homepage (https://simtk.org/home/openmm) and place them in
the TINKER source directory. These files are compatible with TINKER 6.0.4. If
you are using later versions of TINKER, some minor edits may be required to get
the program to compile.
#. In the :code:`Makefile`\ , edit the following fields, as needed:
#. TINKERDIR – This should point to the head of the TINKER
distribution directory, e.g., ‘/home/user/tinker-5.1.09’
#. LINKDIR – directory in executable path containing linked
copies of the TINKER executables; typical directory would be ‘/usr/local/bin’
#. CC – This is an added field that should point to the C compiler
(e.g., ‘/usr/bin/gcc’)
#. OpenMM_INSTALL_DIR - This should identify the directory where the
OpenMM files were installed, i.e., the OPENMM_INSTALL_PREFIX setting when CMake
was run in step (1)
#. At the command line, type::
make dynamic_openmm.x
to create the executable.
#. Check that the environment variable ‘OPENMM_PLUGIN_DIR’ is set to the
installed plugins directory and that the environment variable ‘LD_LIBRARY_PATH’
includes both the installed lib and plugins directory; for example:
::
OPENMM_PLUGIN_DIR=/home/usr/install/openmm/lib/plugins
LD_LIBRARY_PATH=/usr/local/cuda/lib64:/home/usr/install/openmm/lib:
/home/usr/install/openmm/lib/plugins
Using TINKER-OpenMM
===================
Run :code:`dynamic_openmm.x` with the same command-line options as you would
\ :code:`dynamic.x`\ . Consult the TINKER documentation and :numref:`Table,mapping from TINKER` for
more details.
Available outputs
-------------------
Only the total force and potential energy are returned by TINKER-OpenMM; a
breakdown of the energy and force into individual terms (bond, angle, …), as is
done in TINKER, is unavailable through the OpenMM plugin. Also, the pressure
cannot be calculated since the virial is not calculated in the plugin.
Setting the frequency of output data updates
--------------------------------------------
Frequent retrieval of the state information from the GPU board can use up a
substantial portion of the total wall clock time. This is due to the fact that
the forces and energies are recalculated for each retrieval. Hence, if the
state information is obtained after every timestep, the wall clock time will
approximately double over runs where the state information in only gathered
infrequently (say every 50-100 timesteps).
Two options are provided for updating the TINKER data structures:
#. (DEFAULT) If the logical value of ‘oneTimeStepPerUpdate’ in
:code:`dynamic.f` is true, then a single step is taken and the TINKER data
structures are populated at each step. This option is conceptually simpler and
is consistent with the TINKER md loops; for example, the output from the TINKER
subroutine mdstat() will be accurate for this choice. However, the performance
will be degraded since the forces and energy are recalculated with each call,
doubling the required time. This is the default option.
#. If ‘oneTimeStepPerUpdate’ is false, then depending on the values of iprint
(TINKER keyword ‘PRINTOUT’) and iwrite (=dump time/dt), multiple time steps are
taken on the GPU before data is transferred from the GPU to the CPU; here dump
time is the value given to the TINKER command-line query ‘Enter Time between
Dumps in Picoseconds’. Under this option, every iprint and every iwrite
timesteps, the state information will be retrieved. For example if ‘PRINTOUT’ is
10 and iwrite is 15, then the information will be retrieved at time steps { 10,
15, 20, 30, 40, 45, …}. This option will lead to better performance than option
1. However, a downside to this approach is that the fluctuation values printed
by the Tinker routine mdstat() will be incorrect.
Specify the GPU board to use
----------------------------
To specify a GPU board other than the default, set the environment variable
‘CUDA_DEVICE’ to the desired board id. A line like the following will be printed
to stderr for the setting CUDA_DEVICE=2:
::
Platform Cuda: setting device id to 2 based on env variable CUDA_DEVICE.
Running comparison tests between TINKER and OpenMM routines
-----------------------------------------------------------
To turn on testing (comparison of forces and potential energy for the initial
conformation calculated using TINKER routines and OpenMM routines), set
‘applyOpenMMTest’ to a non-zero value in :code:`dynamic.f`\ . Note: the
program exits after the force/energy comparisons; it does not execute the main
molecular dynamics loop.
*Testing individual forces:* An example key file for testing the harmonic
bond term is as follows:
::
parameters /home/user/tinker/params/amoebabio09
verbose
solvate GK
born-radius grycuk
polar-eps 0.0001
integrate verlet
bondterm only
For the other covalent and Van der Waals forces, replace the line :code:`bondterm only`
above with the following lines depending on the force to be tested:
::
angle force: angleterm onl
out-of-plane bend: opbendterm only
stretch bend force strbndterm only
pi-torsion force: pitorsterm only
torsion force: torsionterm only
torsion-torsion force: tortorterm only
Urey-Bradley force: ureyterm only
Van der Waals force: vdwterm only
A sample key file for the multipole force with no cutoffs is given below:
::
parameters /home/user/tinker/params/amoebabio09
verbose
solvate GK
born-radius grycuk
polar-eps 0.0001
integrate verlet
mpoleterm only
polarizeterm
A sample key file for PME multipole tests
::
parameters /home/user/tinker/params/amoebabio09
verbose
randomseed 123456789
neighbor-list
vdw-cutoff 12.0
ewald
ewald-cutoff 7.0
pme-grid 64 64 64
polar-eps 0.01
fft-package fftw
integrate verlet
mpoleterm only
polarizeterm
For the Generalized Kirkwood force, the following entries are needed:
::
parameters /home/user/tinker/params/amoebabio09
verbose
solvate GK
born-radius grycuk
polar-eps 0.0001
integrate verlet
solvateterm only
polarizeterm
mpoleterm
For the implicit solvent (‘solvate GK’ runs) test, the forces and energies will
differ due to the different treatments of the cavity term (see Section :ref:`supported-forces-and-options`
above). With these options for the Generalized Kirkwood force, the test routine
will remove the cavity contribution from the TINKER and OpenMM forces/energy
when performing the comparisons between the two calculations.
To test the multipole force or the Generalized Kirkwood forces with direct
polarization, add the following line to the end of the above files:
::
polarization DIRECT
Turning off OpenMM / Reverting to TINKER routines
-------------------------------------------------
To use the TINKER routines, as opposed to the OpenMM plugin, to run a
simulation, set ‘useOpenMM’ to .false. in :code:`dynamic.f`\ .
OpenMM AMOEBA Validation
************************
OpenMM and TINKER 6.1.01 were each used to compute the atomic forces for
dihydrofolate reductase (DHFR) in implicit and explicit solvent. Calculations
used the CUDA platform, and were repeated for both single and double precision.
For every atom, the relative difference between OpenMM and TINKER was computed
as 2·\|F\ :sub:`MM`\ –F\ :sub:`T`\ \|/(\|F\ :sub:`MM`\ \|+\|F\ :sub:`T`\ \|), where
F\ :sub:`MM` is the force computed by OpenMM and F\ :sub:`T` is the force
computed by TINKER. The median over all atoms is shown in :numref:`Table,comparison to TINKER`\ .
Because OpenMM and TINKER use different approximations to compute the cavity
term, the differences in forces are much larger for implicit solvent than for
explicit solvent. We therefore repeated the calculations, removing the cavity
term. This yields much closer agreement between OpenMM and TINKER,
demonstrating that the difference comes entirely from that one term.
========================= ========================== ===================
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`
Explicit 3.73·10\ :sup:`-5` 1.83·10\ :sup:`-7`
========================= ========================== ===================
:autonumber:`Table,comparison to TINKER`\ : Median relative difference in forces between OpenMM and TINKER
Ring Polymer Molecular Dynamics (RPMD) Plugin
#############################################
Ring Polymer Molecular Dynamics (RPMD) provides an efficient approach to include
nuclear quantum effects in molecular simulations.\ :cite:`Craig2004` When
used to calculate static equilibrium properties, RPMD reduces to path integral
molecular dynamics and gives an exact description of the effect of quantum
fluctuations for a given potential energy model.\ :cite:`Parrinello1984` For
dynamical properties RPMD is no longer exact but has shown to be a good
approximation in many cases.
For a system with a classical potential energy *E*\ (\ *q*\ ), the RPMD
Hamiltonian is given by
.. math::
H=\sum _{k=1}^{n}\left(\frac{{p}_{{k}^{2}}}{2m}+E({q}_{k})+\frac{m({k}_{B}Tn)^{2}}{2h^{2}}({q}_{k}-{q}_{k-1})^{2}\right)
This Hamiltonian resembles that of a system of classical ring polymers where
different copies of the system are connected by harmonic springs. Hence each
copy of the classical system is commonly referred to as a “bead”. The spread of
the ring polymer representing each particle is directly related to its De
Broglie thermal wavelength (uncertainty in its position).
RPMD calculations must be converged with respect to the number *n* of beads
used. Each bead is evolved at the effective temperature *nT*\ , where *T*\
is the temperature for which properties are required. The number of beads
needed to converge a calculation can be estimated using\ :cite:`Markland2008`\
.. math::
n>\frac{h\omega_{max}}{{k}_{B}T}
where :math:`\omega_{max}` is the highest frequency in the problem. For example, for
flexible liquid water the highest frequency is the OH stretch at around 3000
cm\ :sup:`-1`\ , so around 24 to 32 beads are needed depending on the accuracy
required. For rigid water where the highest frequency is only around 1000
cm\ :sup:`-1`\ , only 6 beads are typically needed. Due to the replication needed
of the classical system, the extra cost of the calculation compared to a
classical simulation increases linearly with the number of beads used.
This cost can be reduced by “contracting” the ring polymer to a smaller number
of beads.\ :cite:`Markland2008` The rapidly changing forces are then computed
for the full number of beads, while slower changing forces are computed on a
smaller set. In the case of flexible water, for example, a common arrangement
would be to compute the high frequency bonded forces on all 32 beads, the direct
space nonbonded forces on only 6 beads, and the reciprocal space nonbonded
forces on only a single bead.
Due to the stiff spring terms between the beads, NVE RPMD trajectories can
suffer from ergodicity problems and hence thermostatting is highly recommended,
especially when dynamical properties are not required.\ :cite:`Hall1984` The
thermostat implemented here is the path integral Langevin equation (PILE)
approach.\ :cite:`Ceriotti2010` This method couples an optimal white noise
Langevin thermostat to the normal modes of each polymer, leaving only one
parameter to be chosen by the user which controls the friction applied to the
center of mass of each ring polymer. A good choice for this is to use a value
similar to that used in a classical calculation of the same system.
.. _drude-plugin:
Drude Plugin
############
Drude oscillators are a method for incorporating electronic polarizability into
a model.\ :cite:`Lamoureux2003` For each polarizable particle, a second
particle (the “Drude particle”) is attached to it by an anisotropic harmonic
spring. When both particles are at the same location, they are equivalent to an
ordinary point particle. Applying an electric field causes the Drude particle
to move a short distance away from its parent particle, creating an induced
dipole moment. The polarizability :math:`\alpha` is related to the charge *q* on
the Drude particle and the spring constant *k* by
.. math::
\alpha =\frac{{q}^{2}}{k}
A damped interaction\ :cite:`Thole1981` is used between dipoles that are
bonded to each other.
The equations of motion can be integrated with two different methods:
#. In the Self Consistent Field (SCF) method, the ordinary particles are first
updated as usual. A local energy minimization is then performed to select new
positions for the Drude particles. This ensures that the induced dipole moments
respond instantly to changes in their environments. This method is accurate but
computationally expensive.
#. In the extended Lagrangian method, the positions of the Drude particles are
treated as dynamical variables, just like any other particles. A small amount
of mass is transferred from the parent particles to the Drude particles,
allowing them to be integrated normally. A dual Langevin integrator is used to
maintain the center of mass of each Drude particle pair at the system
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.
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment