Unverified Commit 6786cc75 authored by peastman's avatar peastman Committed by GitHub
Browse files

Merge pull request #2561 from peastman/middle

Converted BAOABLangevinIntegrator to LangevinMiddleIntegrator
parents 3fdc297c cc59da1a
...@@ -120,7 +120,7 @@ steps. ...@@ -120,7 +120,7 @@ steps.
forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml')
system = forcefield.createSystem(pdb.topology, nonbondedMethod=PME, system = forcefield.createSystem(pdb.topology, nonbondedMethod=PME,
nonbondedCutoff=1*nanometer, constraints=HBonds) nonbondedCutoff=1*nanometer, constraints=HBonds)
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
simulation = Simulation(pdb.topology, system, integrator) simulation = Simulation(pdb.topology, system, integrator)
simulation.context.setPositions(pdb.positions) simulation.context.setPositions(pdb.positions)
simulation.minimizeEnergy() simulation.minimizeEnergy()
...@@ -210,14 +210,17 @@ convenient and less error-prone. We could have equivalently specified ...@@ -210,14 +210,17 @@ convenient and less error-prone. We could have equivalently specified
The units system will be described in more detail later, in Section :ref:`units-and-dimensional-analysis`. The units system will be described in more detail later, in Section :ref:`units-and-dimensional-analysis`.
:: ::
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
This line creates the integrator to use for advancing the equations of motion. This line creates the integrator to use for advancing the equations of motion.
It specifies a :class:`BAOABLangevinIntegrator`, which performs Langevin dynamics, It specifies a :class:`LangevinMiddleIntegrator`, which performs Langevin dynamics,
and assigns it to a variable called :code:`integrator`\ . It also specifies and assigns it to a variable called :code:`integrator`\ . It also specifies
the values of three parameters that are specific to Langevin dynamics: the the values of three parameters that are specific to Langevin dynamics: the
simulation temperature (300 K), the friction coefficient (1 ps\ :sup:`-1`\ ), and simulation temperature (300 K), the friction coefficient (1 ps\ :sup:`-1`\ ), and
the step size (0.004 ps). the step size (0.004 ps). Lots of other integration methods are also available.
For example, if you wanted to simulate the system at constant energy rather than
constant temperature you would use a :code:`VerletIntegrator`\ . The available
integration methods are listed in Section :ref:`integrators`.
:: ::
simulation = Simulation(pdb.topology, system, integrator) simulation = Simulation(pdb.topology, system, integrator)
...@@ -295,7 +298,7 @@ found in OpenMM’s :file:`examples` folder with the name :file:`simulateAmber.p ...@@ -295,7 +298,7 @@ found in OpenMM’s :file:`examples` folder with the name :file:`simulateAmber.p
inpcrd = AmberInpcrdFile('input.inpcrd') inpcrd = AmberInpcrdFile('input.inpcrd')
system = prmtop.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer, system = prmtop.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer,
constraints=HBonds) constraints=HBonds)
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
simulation = Simulation(prmtop.topology, system, integrator) simulation = Simulation(prmtop.topology, system, integrator)
simulation.context.setPositions(inpcrd.positions) simulation.context.setPositions(inpcrd.positions)
if inpcrd.boxVectors is not None: if inpcrd.boxVectors is not None:
...@@ -389,7 +392,7 @@ with the name :file:`simulateGromacs.py`. ...@@ -389,7 +392,7 @@ with the name :file:`simulateGromacs.py`.
includeDir='/usr/local/gromacs/share/gromacs/top') includeDir='/usr/local/gromacs/share/gromacs/top')
system = top.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer, system = top.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer,
constraints=HBonds) constraints=HBonds)
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
simulation = Simulation(top.topology, system, integrator) simulation = Simulation(top.topology, system, integrator)
simulation.context.setPositions(gro.positions) simulation.context.setPositions(gro.positions)
simulation.minimizeEnergy() simulation.minimizeEnergy()
...@@ -453,7 +456,7 @@ on the :class:`CharmmPsfFile`. ...@@ -453,7 +456,7 @@ on the :class:`CharmmPsfFile`.
params = CharmmParameterSet('charmm22.rtf', 'charmm22.prm') params = CharmmParameterSet('charmm22.rtf', 'charmm22.prm')
system = psf.createSystem(params, nonbondedMethod=NoCutoff, system = psf.createSystem(params, nonbondedMethod=NoCutoff,
nonbondedCutoff=1*nanometer, constraints=HBonds) nonbondedCutoff=1*nanometer, constraints=HBonds)
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
simulation = Simulation(psf.topology, system, integrator) simulation = Simulation(psf.topology, system, integrator)
simulation.context.setPositions(pdb.positions) simulation.context.setPositions(pdb.positions)
simulation.minimizeEnergy() simulation.minimizeEnergy()
...@@ -1018,36 +1021,42 @@ mass constant while slowing down the fast motions of hydrogens. When combined ...@@ -1018,36 +1021,42 @@ mass constant while slowing down the fast motions of hydrogens. When combined
with constraints (typically :code:`constraints=AllBonds`\ ), this often allows a with constraints (typically :code:`constraints=AllBonds`\ ), this often allows a
further increase in integration step size. further increase in integration step size.
.. _integrators:
Integrators Integrators
=========== ===========
OpenMM offers a choice of several different integration methods. You select OpenMM offers a choice of several different integration methods. You select
which one to use by creating an integrator object of the appropriate type. which one to use by creating an integrator object of the appropriate type.
Detailed descriptions of all these integrators can be found in Chapter
:ref:`integrators-theory`. In addition to these built in integrators, lots of
others are available as part of the `OpenMMTools <https://openmmtools.readthedocs.io>`_ package.
BAOAB Langevin Integrator Langevin Middle Integrator
------------------------- --------------------------
In the examples of the previous sections, we used Langevin integration: In the examples of the previous sections, we used Langevin integration:
:: ::
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
The three parameter values in this line are the simulation temperature (300 K), 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.004 ps). You the friction coefficient (1 ps\ :sup:`-1`\ ), and the step size (0.004 ps). You
are free to change these to whatever values you want. Be sure to specify units 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 on all values. For example, the step size could be written either as
:code:`0.004*picoseconds` or :code:`4*femtoseconds`\ . They are exactly :code:`0.004*picoseconds` or :code:`4*femtoseconds`\ . They are exactly
equivalent. equivalent. Note that :code:`LangevinMiddleIntegrator` is a leapfrog
integrator, so the velocities are offset by half a time step from the positions.
Langevin Integrator Langevin Integrator
------------------- -------------------
:code:`LangevinIntegrator` is very similar to :code:`BAOABLangevinIntegrator`, :code:`LangevinIntegrator` is very similar to :code:`LangevinMiddleIntegrator`,
but it uses a different discretization of the Langevin equation. but it uses a different discretization of the Langevin equation.
:code:`BAOABLangevinIntegrator` tends to produce more accurate configurational :code:`LangevinMiddleIntegrator` tends to produce more accurate configurational
sampling, and therefore is preferred for most applications. Also note that sampling, and therefore is preferred for most applications. Also note that
:code:`LangevinIntegrator` (unlike :code:`BAOABLangevinIntegrator`) is a leapfrog :code:`LangevinIntegrator`\ , like :code:`LangevinMiddleIntegrator`\ , is a leapfrog
integrator, so the velocities are offset by half a time step from the positions. integrator, so the velocities are offset by half a time step from the positions.
Leapfrog Verlet Integrator Leapfrog Verlet Integrator
...@@ -1158,7 +1167,7 @@ previous section: ...@@ -1158,7 +1167,7 @@ previous section:
system = prmtop.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer, system = prmtop.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer,
constraints=HBonds) constraints=HBonds)
system.addForce(MonteCarloBarostat(1*bar, 300*kelvin)) system.addForce(MonteCarloBarostat(1*bar, 300*kelvin))
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
... ...
The parameters of the Monte Carlo barostat are the pressure (1 bar) and The parameters of the Monte Carlo barostat are the pressure (1 bar) and
...@@ -1718,7 +1727,7 @@ executing 1000 time steps at each temperature: ...@@ -1718,7 +1727,7 @@ executing 1000 time steps at each temperature:
:autonumber:`Example,simulated annealing` :autonumber:`Example,simulated annealing`
This code needs very little explanation. The loop is executed 100 times. Each This code needs very little explanation. The loop is executed 100 times. Each
time through, it adjusts the temperature of the :class:`BAOABLangevinIntegrator` and then time through, it adjusts the temperature of the :class:`LangevinMiddleIntegrator` and then
calls :code:`step(1000)` to take 1000 time steps. calls :code:`step(1000)` to take 1000 time steps.
Applying an External Force to Particles: a Spherical Container Applying an External Force to Particles: a Spherical Container
...@@ -1750,7 +1759,7 @@ coordinates. Here is the code to do it: ...@@ -1750,7 +1759,7 @@ coordinates. Here is the code to do it:
system.addForce(force) system.addForce(force)
for i in range(system.getNumParticles()): for i in range(system.getNumParticles()):
force.addParticle(i, []) force.addParticle(i, [])
integrator = BAOABLangevinIntegrator(300*kelvin, 91/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 91/picosecond, 0.004*picoseconds)
... ...
.. caption:: .. caption::
......
...@@ -243,14 +243,14 @@ simulation might look like: ...@@ -243,14 +243,14 @@ simulation might look like:
angles->addAngle(angle[i].particle1, angle[i].particle2, angles->addAngle(angle[i].particle1, angle[i].particle2,
angle[i].particle3, angle[i].angle, angle[i].k); angle[i].particle3, angle[i].angle, angle[i].k);
// ...create and initialize other force field terms in the same way // ...create and initialize other force field terms in the same way
BAOABLangevinIntegrator integrator(temperature, friction, stepSize); LangevinMiddleIntegrator integrator(temperature, friction, stepSize);
Context context(system, integrator); Context context(system, integrator);
context.setPositions(initialPositions); context.setPositions(initialPositions);
context.setVelocities(initialVelocities); context.setVelocities(initialVelocities);
integrator.step(10000); integrator.step(10000);
We create a System, add various Forces to it, and set parameters on both the We create a System, add various Forces to it, and set parameters on both the
System and the Forces. We then create a BAOABLangevinIntegrator, initialize a System and the Forces. We then create a LangevinMiddleIntegrator, initialize a
Context in which to run a simulation, and instruct the Integrator to advance the Context in which to run a simulation, and instruct the Integrator to advance the
simulation for 10,000 time steps. simulation for 10,000 time steps.
...@@ -1631,7 +1631,7 @@ along with the handle :code:`omm`\ , back to the calling function. ...@@ -1631,7 +1631,7 @@ along with the handle :code:`omm`\ , back to the calling function.
// best available Platform. Initialize the configuration from the default // best available Platform. Initialize the configuration from the default
// positions we collected above. Initial velocities will be zero but could // positions we collected above. Initial velocities will be zero but could
// have been set here. // have been set here.
omm->integrator = new OpenMM::BAOABLangevinIntegrator(temperature, omm->integrator = new OpenMM::LangevinMiddleIntegrator(temperature,
frictionInPs, frictionInPs,
stepSizeInFs * OpenMM::PsPerFs); stepSizeInFs * OpenMM::PsPerFs);
omm->context = new OpenMM::Context(*omm->system, *omm->integrator); omm->context = new OpenMM::Context(*omm->system, *omm->integrator);
......
...@@ -240,19 +240,6 @@ ...@@ -240,19 +240,6 @@
type = {Journal Article} type = {Journal Article}
} }
@article{Leimkuhler2013,
author = {Leimkuhler, Benedict and Matthews, Charles},
title = {Rational Construction of Stochastic Numerical Methods for Molecular Sampling},
journal = {Applied Mathematics Research eXpress},
volume = {2013},
number = {1},
pages = {34-56},
year = {2012},
month = {06},
doi = {10.1093/amrx/abs010},
type = {Journal Article}
}
@article{Li2010 @article{Li2010
author = {Li, D.W. and Br{\"u}schweiler, R.}, author = {Li, D.W. and Br{\"u}schweiler, R.},
title = {{NMR}-based protein potentials}, title = {{NMR}-based protein potentials},
...@@ -629,3 +616,15 @@ ...@@ -629,3 +616,15 @@
year = {2015}, year = {2015},
type = {Journal Article} type = {Journal Article}
} }
@article{Zhang2019,
author = {Zhang, Zhijun and Liu, Xinzijian and Yan, Kangyu and Tuckerman, Mark E. and Liu, Jian},
title = {Unified Efficient Thermostat Scheme for the Canonical Ensemble with Holonomic or Isokinetic Constraints via Molecular Dynamics},
journal = {The Journal of Physical Chemistry A},
volume = {123},
number = {28},
pages = {6056-6079},
year = {2019},
doi = {10.1021/acs.jpca.9b02771},
type = {Journal Article}
}
...@@ -1278,6 +1278,8 @@ algorithm. This can be used to implement algorithms such as lambda-dynamics, ...@@ -1278,6 +1278,8 @@ algorithm. This can be used to implement algorithms such as lambda-dynamics,
where a global parameter is integrated as a dynamic variable. where a global parameter is integrated as a dynamic variable.
.. _integrators-theory:
Integrators Integrators
########### ###########
...@@ -1353,16 +1355,16 @@ random number, and :math:`\alpha=\exp(-\gamma\Delta t)`. ...@@ -1353,16 +1355,16 @@ random number, and :math:`\alpha=\exp(-\gamma\Delta t)`.
The same comments about the offset between positions and velocities apply to The same comments about the offset between positions and velocities apply to
this integrator as to VerletIntegrator. this integrator as to VerletIntegrator.
BAOABLangevinIntegrator LangevinMiddleIntegrator
*********************** ************************
This integrator is similar to LangevinIntegerator, but it instead uses the BAOAB This integrator is similar to LangevinIntegerator, but it instead uses the LFMiddle
discretization. :cite:`Leimkuhler2013` In each step, the positions and velocities discretization. :cite:`Zhang2019` In each step, the positions and velocities
are updated as follows: are updated as follows:
.. math:: .. math::
\mathbf{v}_{i}(t+\Delta t/2) = \mathbf{v}_{i}(t) + \mathbf{f}_{i}(t)\Delta t/2{m}_{i} \mathbf{v}_{i}(t+\Delta t/2) = \mathbf{v}_{i}(t-\Delta t/2) + \mathbf{f}_{i}(t)\Delta t/{m}_{i}
.. math:: .. math::
...@@ -1377,26 +1379,18 @@ are updated as follows: ...@@ -1377,26 +1379,18 @@ are updated as follows:
\mathbf{r}_{i}(t+\Delta t) = \mathbf{r}_{i}(t+\Delta t/2) + \mathbf{v'}_{i}(t+\Delta t/2)\Delta t/2 \mathbf{r}_{i}(t+\Delta t) = \mathbf{r}_{i}(t+\Delta t/2) + \mathbf{v'}_{i}(t+\Delta t/2)\Delta t/2
.. math:: This tends to produce more accurate sampling of configurational properties (such
\mathbf{v}_{i}(t+\Delta t) = \mathbf{v'}_{i}(t+\Delta t/2) + \mathbf{f}_{i}(t+\Delta t)\Delta t/2{m}_{i} as free energies), but less accurate sampling of kinetic properties. Because
This tends to produce more accurate
sampling of configurational properties (such as free energies), but less
accurate sampling of kinetic properties (such as mean kinetic energy). Because
configurational properties are much more important than kinetic ones in most configurational properties are much more important than kinetic ones in most
simulations, this integrator is generally preferred over LangevinIntegrator. It simulations, this integrator is generally preferred over LangevinIntegrator. It
often allows one to use a larger time step while still maintaining similar or often allows one to use a larger time step while still maintaining similar or
better accuracy. better accuracy.
One disadvantage of this integrator is that it requires applying constraints One disadvantage of this integrator is that it requires applying constraints
three times per time step, compared to only once for LangevinIntegrator. This twice per time step, compared to only once for LangevinIntegrator. This
can make it slightly slower for systems that involve constraints. However, this can make it slightly slower for systems that involve constraints. However, this
usually is more than compensated by allowing you to use a larger time step. usually is more than compensated by allowing you to use a larger time step.
Unlike LangevinIntegrator, this does not use a leap-frog algorithm. The
positions and velocities all correspond to the same point in time.
BrownianIntegrator BrownianIntegrator
****************** ******************
......
...@@ -249,7 +249,7 @@ myInitializeOpenMM( const MyAtomInfo atoms[], ...@@ -249,7 +249,7 @@ myInitializeOpenMM( const MyAtomInfo atoms[],
// best available Platform. Initialize the configuration from the default // best available Platform. Initialize the configuration from the default
// positions we collected above. Initial velocities will be zero but could // positions we collected above. Initial velocities will be zero but could
// have been set here. // have been set here.
omm->integrator = new OpenMM::BAOABLangevinIntegrator(temperature, frictionInPs, omm->integrator = new OpenMM::LangevinMiddleIntegrator(temperature, frictionInPs,
stepSizeInFs * OpenMM::PsPerFs); stepSizeInFs * OpenMM::PsPerFs);
omm->context = new OpenMM::Context(*omm->system, *omm->integrator); omm->context = new OpenMM::Context(*omm->system, *omm->integrator);
omm->context->setPositions(initialPosInNm); omm->context->setPositions(initialPosInNm);
......
...@@ -252,7 +252,7 @@ myInitializeOpenMM( const MyAtomInfo atoms[], ...@@ -252,7 +252,7 @@ myInitializeOpenMM( const MyAtomInfo atoms[],
* best available Platform. Initialize the configuration from the default * best available Platform. Initialize the configuration from the default
* positions we collected above. Initial velocities will be zero but could * positions we collected above. Initial velocities will be zero but could
* have been set here. */ * have been set here. */
omm->integrator = (OpenMM_Integrator*)OpenMM_BAOABLangevinIntegrator_create( omm->integrator = (OpenMM_Integrator*)OpenMM_LangevinMiddleIntegrator_create(
temperature, frictionInPerPs, temperature, frictionInPerPs,
stepSizeInFs * OpenMM_PsPerFs); stepSizeInFs * OpenMM_PsPerFs);
omm->context = OpenMM_Context_create(omm->system, omm->integrator); omm->context = OpenMM_Context_create(omm->system, omm->integrator);
......
...@@ -171,7 +171,7 @@ SUBROUTINE myInitializeOpenMM(ommHandle, platformName) ...@@ -171,7 +171,7 @@ SUBROUTINE myInitializeOpenMM(ommHandle, platformName)
! These are the objects we'll create here thare are stored in the ! These are the objects we'll create here thare are stored in the
! Context for later access. Don't forget to delete them at the end. ! Context for later access. Don't forget to delete them at the end.
type (OpenMM_System) system type (OpenMM_System) system
type (OpenMM_BAOABLangevinIntegrator) langevin type (OpenMM_LangevinMiddleIntegrator) langevin
type (OpenMM_Context) context type (OpenMM_Context) context
! These are temporary OpenMM objects used and discarded here. ! These are temporary OpenMM objects used and discarded here.
...@@ -236,11 +236,11 @@ SUBROUTINE myInitializeOpenMM(ommHandle, platformName) ...@@ -236,11 +236,11 @@ SUBROUTINE myInitializeOpenMM(ommHandle, platformName)
! best available Platform. Initialize the configuration from the default ! best available Platform. Initialize the configuration from the default
! positions we collected above. Initial velocities will be zero but could ! positions we collected above. Initial velocities will be zero but could
! have been set here. ! have been set here.
call OpenMM_BAOABLangevinIntegrator_create(langevin, & call OpenMM_LangevinMiddleIntegrator_create(langevin, &
Temperature, FrictionInPerPs, & Temperature, FrictionInPerPs, &
StepSizeInFs * OpenMM_PsPerFs) StepSizeInFs * OpenMM_PsPerFs)
! Convert BAOABLangevinIntegrator to generic Integrator type for this call. ! Convert LangevinMiddleIntegrator to generic Integrator type for this call.
call OpenMM_Context_create(context, system, & call OpenMM_Context_create(context, system, &
transfer(langevin, OpenMM_Integrator(0))) transfer(langevin, OpenMM_Integrator(0)))
call OpenMM_Context_setPositions(context, initialPosInNm) call OpenMM_Context_setPositions(context, initialPosInNm)
......
...@@ -6,7 +6,7 @@ from sys import stdout ...@@ -6,7 +6,7 @@ from sys import stdout
prmtop = AmberPrmtopFile('input.prmtop') prmtop = AmberPrmtopFile('input.prmtop')
inpcrd = AmberInpcrdFile('input.inpcrd') inpcrd = AmberInpcrdFile('input.inpcrd')
system = prmtop.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer, constraints=HBonds) system = prmtop.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer, constraints=HBonds)
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
simulation = Simulation(prmtop.topology, system, integrator) simulation = Simulation(prmtop.topology, system, integrator)
simulation.context.setPositions(inpcrd.positions) simulation.context.setPositions(inpcrd.positions)
if inpcrd.boxVectors is not None: if inpcrd.boxVectors is not None:
......
...@@ -21,7 +21,7 @@ params = CharmmParameterSet('charmm22.rtf', 'charmm22.par') ...@@ -21,7 +21,7 @@ params = CharmmParameterSet('charmm22.rtf', 'charmm22.par')
# Instantiate the system # Instantiate the system
system = psf.createSystem(params, nonbondedMethod=NoCutoff, constraints=HBonds) system = psf.createSystem(params, nonbondedMethod=NoCutoff, constraints=HBonds)
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
simulation = Simulation(psf.topology, system, integrator) simulation = Simulation(psf.topology, system, integrator)
simulation.context.setPositions(pdb.getPositions()) simulation.context.setPositions(pdb.getPositions())
simulation.minimizeEnergy() simulation.minimizeEnergy()
......
...@@ -6,7 +6,7 @@ from sys import stdout ...@@ -6,7 +6,7 @@ from sys import stdout
gro = GromacsGroFile('input.gro') gro = GromacsGroFile('input.gro')
top = GromacsTopFile('input.top', periodicBoxVectors=gro.getPeriodicBoxVectors()) top = GromacsTopFile('input.top', periodicBoxVectors=gro.getPeriodicBoxVectors())
system = top.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer, constraints=HBonds) system = top.createSystem(nonbondedMethod=PME, nonbondedCutoff=1*nanometer, constraints=HBonds)
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
simulation = Simulation(top.topology, system, integrator) simulation = Simulation(top.topology, system, integrator)
simulation.context.setPositions(gro.positions) simulation.context.setPositions(gro.positions)
simulation.minimizeEnergy() simulation.minimizeEnergy()
......
...@@ -6,7 +6,7 @@ from sys import stdout ...@@ -6,7 +6,7 @@ from sys import stdout
pdb = PDBFile('input.pdb') pdb = PDBFile('input.pdb')
forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml')
system = forcefield.createSystem(pdb.topology, nonbondedMethod=PME, nonbondedCutoff=1*nanometer, constraints=HBonds) system = forcefield.createSystem(pdb.topology, nonbondedMethod=PME, nonbondedCutoff=1*nanometer, constraints=HBonds)
integrator = BAOABLangevinIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds) integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)
simulation = Simulation(pdb.topology, system, integrator) simulation = Simulation(pdb.topology, system, integrator)
simulation.context.setPositions(pdb.positions) simulation.context.setPositions(pdb.positions)
simulation.minimizeEnergy() simulation.minimizeEnergy()
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2019 Stanford University and the Authors. * * Portions copyright (c) 2008-2020 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "openmm/AndersenThermostat.h" #include "openmm/AndersenThermostat.h"
#include "openmm/BAOABLangevinIntegrator.h" #include "openmm/LangevinMiddleIntegrator.h"
#include "openmm/BrownianIntegrator.h" #include "openmm/BrownianIntegrator.h"
#include "openmm/CMAPTorsionForce.h" #include "openmm/CMAPTorsionForce.h"
#include "openmm/CMMotionRemover.h" #include "openmm/CMMotionRemover.h"
...@@ -1129,40 +1129,36 @@ public: ...@@ -1129,40 +1129,36 @@ public:
}; };
/** /**
* This kernel is invoked by BAOABLangevinIntegrator to take one time step. * This kernel is invoked by LangevinMiddleIntegrator to take one time step.
*/ */
class IntegrateBAOABStepKernel : public KernelImpl { class IntegrateLangevinMiddleStepKernel : public KernelImpl {
public: public:
static std::string Name() { static std::string Name() {
return "IntegrateBAOABStep"; return "IntegrateLangevinMiddleStep";
} }
IntegrateBAOABStepKernel(std::string name, const Platform& platform) : KernelImpl(name, platform) { IntegrateLangevinMiddleStepKernel(std::string name, const Platform& platform) : KernelImpl(name, platform) {
} }
/** /**
* Initialize the kernel. * Initialize the kernel.
* *
* @param system the System this kernel will be applied to * @param system the System this kernel will be applied to
* @param integrator the BAOABLangevinIntegrator this kernel will be used for * @param integrator the LangevinMiddleIntegrator this kernel will be used for
*/ */
virtual void initialize(const System& system, const BAOABLangevinIntegrator& integrator) = 0; virtual void initialize(const System& system, const LangevinMiddleIntegrator& integrator) = 0;
/** /**
* Execute the kernel. * Execute the kernel.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for * @param integrator the LangevinMiddleIntegrator this kernel is being used for
* @param forcesAreValid if the context has been modified since the last time step, this will be
* false to show that cached forces are invalid and must be recalculated.
* On exit, this should specify whether the cached forces are valid at the
* end of the step.
*/ */
virtual void execute(ContextImpl& context, const BAOABLangevinIntegrator& integrator, bool& forcesAreValid) = 0; virtual void execute(ContextImpl& context, const LangevinMiddleIntegrator& integrator) = 0;
/** /**
* Compute the kinetic energy. * Compute the kinetic energy.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for * @param integrator the LangevinMiddleIntegrator this kernel is being used for
*/ */
virtual double computeKineticEnergy(ContextImpl& context, const BAOABLangevinIntegrator& integrator) = 0; virtual double computeKineticEnergy(ContextImpl& context, const LangevinMiddleIntegrator& integrator) = 0;
}; };
/** /**
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "openmm/AndersenThermostat.h" #include "openmm/AndersenThermostat.h"
#include "openmm/BAOABLangevinIntegrator.h"
#include "openmm/BrownianIntegrator.h" #include "openmm/BrownianIntegrator.h"
#include "openmm/CMAPTorsionForce.h" #include "openmm/CMAPTorsionForce.h"
#include "openmm/CMMotionRemover.h" #include "openmm/CMMotionRemover.h"
...@@ -57,6 +56,7 @@ ...@@ -57,6 +56,7 @@
#include "openmm/HarmonicBondForce.h" #include "openmm/HarmonicBondForce.h"
#include "openmm/Integrator.h" #include "openmm/Integrator.h"
#include "openmm/LangevinIntegrator.h" #include "openmm/LangevinIntegrator.h"
#include "openmm/LangevinMiddleIntegrator.h"
#include "openmm/LocalEnergyMinimizer.h" #include "openmm/LocalEnergyMinimizer.h"
#include "openmm/MonteCarloAnisotropicBarostat.h" #include "openmm/MonteCarloAnisotropicBarostat.h"
#include "openmm/MonteCarloBarostat.h" #include "openmm/MonteCarloBarostat.h"
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2019 Stanford University and the Authors. * * Portions copyright (c) 2011-2020 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -236,7 +236,7 @@ namespace OpenMM { ...@@ -236,7 +236,7 @@ namespace OpenMM {
* </pre></tt> * </pre></tt>
* *
* The second one implements the algorithm used by the standard * The second one implements the algorithm used by the standard
* BAOABLangevinIntegrator class. kB is Boltzmann's constant. * LangevinMiddleIntegrator class. kB is Boltzmann's constant.
* *
* <tt><pre> * <tt><pre>
* CustomIntegrator integrator(dt); * CustomIntegrator integrator(dt);
...@@ -245,18 +245,14 @@ namespace OpenMM { ...@@ -245,18 +245,14 @@ namespace OpenMM {
* integrator.addGlobalVariable("kT", kB*temperature); * integrator.addGlobalVariable("kT", kB*temperature);
* integrator.addPerDofVariable("x1", 0); * integrator.addPerDofVariable("x1", 0);
* integrator.addUpdateContextState(); * integrator.addUpdateContextState();
* integrator.addComputePerDof("v", "v + 0.5*dt*f/m"); * integrator.addComputePerDof("v", "v + dt*f/m");
* integrator.addConstrainVelocities();
* integrator.addComputePerDof("x", "x + 0.5*dt*v"); * integrator.addComputePerDof("x", "x + 0.5*dt*v");
* integrator.addComputePerDof("x1", "x");
* integrator.addConstrainPositions();
* integrator.addComputePerDof("v", "v + 2*(x-x1)/dt");
* integrator.addComputePerDof("v", "a*v + b*sqrt(kT/m)*gaussian"); * integrator.addComputePerDof("v", "a*v + b*sqrt(kT/m)*gaussian");
* integrator.addComputePerDof("x", "x + 0.5*dt*v"); * integrator.addComputePerDof("x", "x + 0.5*dt*v");
* integrator.addComputePerDof("x1", "x"); * integrator.addComputePerDof("x1", "x");
* integrator.addConstrainPositions(); * integrator.addConstrainPositions();
* integrator.addComputePerDof("v", "v + 2*(x-x1)/dt"); * integrator.addComputePerDof("v", "v + (x-x1)/dt");
* integrator.addComputePerDof("v", "v + 0.5*dt*f/m");
* integrator.addConstrainVelocities();
* </pre></tt> * </pre></tt>
* *
* Another feature of CustomIntegrator is that it can use derivatives of the * Another feature of CustomIntegrator is that it can use derivatives of the
......
#ifndef OPENMM_BAOABLANGEVININTEGRATOR_H_ #ifndef OPENMM_LANGEVINMIDDLEINTEGRATOR_H_
#define OPENMM_BAOABLANGEVININTEGRATOR_H_ #define OPENMM_LANGEVINMIDDLEINTEGRATOR_H_
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* OpenMM * * OpenMM *
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2019 Stanford University and the Authors. * * Portions copyright (c) 2008-2020 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -40,21 +40,21 @@ namespace OpenMM { ...@@ -40,21 +40,21 @@ namespace OpenMM {
/** /**
* This is an Integrator which simulates a System using Langevin dynamics, with * This is an Integrator which simulates a System using Langevin dynamics, with
* the BAOAB discretization of Leimkuhler and Matthews (http://dx.doi.org/10.1093/amrx/abs010). * the LFMiddle discretization (http://dx.doi.org/10.1021/acs.jpca.9b02771).
* This method tend to produce more accurate configurational sampling than other * This method tend to produce more accurate configurational sampling than other
* discretizations, such as the one used in LangevinIntegrator. * discretizations, such as the one used in LangevinIntegrator.
*/ */
class OPENMM_EXPORT BAOABLangevinIntegrator : public Integrator { class OPENMM_EXPORT LangevinMiddleIntegrator : public Integrator {
public: public:
/** /**
* Create a BAOABLangevinIntegrator. * Create a LangevinMiddleIntegrator.
* *
* @param temperature the temperature of the heat bath (in Kelvin) * @param temperature the temperature of the heat bath (in Kelvin)
* @param frictionCoeff the friction coefficient which couples the system to the heat bath (in inverse picoseconds) * @param frictionCoeff the friction coefficient which couples the system to the heat bath (in inverse picoseconds)
* @param stepSize the step size with which to integrate the system (in picoseconds) * @param stepSize the step size with which to integrate the system (in picoseconds)
*/ */
BAOABLangevinIntegrator(double temperature, double frictionCoeff, double stepSize); LangevinMiddleIntegrator(double temperature, double frictionCoeff, double stepSize);
/** /**
* Get the temperature of the heat bath (in Kelvin). * Get the temperature of the heat bath (in Kelvin).
* *
...@@ -128,10 +128,6 @@ protected: ...@@ -128,10 +128,6 @@ protected:
* cleanup. It will also get called again if the application calls reinitialize() on the Context. * cleanup. It will also get called again if the application calls reinitialize() on the Context.
*/ */
void cleanup(); void cleanup();
/**
* When the user modifies the state, we need to mark that the forces need to be recalculated.
*/
void stateChanged(State::DataType changed);
/** /**
* Get the names of all Kernels used by this Integrator. * Get the names of all Kernels used by this Integrator.
*/ */
...@@ -147,10 +143,9 @@ protected: ...@@ -147,10 +143,9 @@ protected:
private: private:
double temperature, friction; double temperature, friction;
int randomNumberSeed; int randomNumberSeed;
bool forcesAreValid;
Kernel kernel; Kernel kernel;
}; };
} // namespace OpenMM } // namespace OpenMM
#endif /*OPENMM_BAOABLANGEVININTEGRATOR_H_*/ #endif /*OPENMM_LANGEVINMIDDLEINTEGRATOR_H_*/
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2019 Stanford University and the Authors. * * Portions copyright (c) 2008-2020 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "openmm/BAOABLangevinIntegrator.h" #include "openmm/LangevinMiddleIntegrator.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/OpenMMException.h" #include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
...@@ -40,53 +40,47 @@ using namespace OpenMM; ...@@ -40,53 +40,47 @@ using namespace OpenMM;
using std::string; using std::string;
using std::vector; using std::vector;
BAOABLangevinIntegrator::BAOABLangevinIntegrator(double temperature, double frictionCoeff, double stepSize) { LangevinMiddleIntegrator::LangevinMiddleIntegrator(double temperature, double frictionCoeff, double stepSize) {
setTemperature(temperature); setTemperature(temperature);
setFriction(frictionCoeff); setFriction(frictionCoeff);
setStepSize(stepSize); setStepSize(stepSize);
setConstraintTolerance(1e-5); setConstraintTolerance(1e-5);
setRandomNumberSeed(0); setRandomNumberSeed(0);
forcesAreValid = false;
} }
void BAOABLangevinIntegrator::initialize(ContextImpl& contextRef) { void LangevinMiddleIntegrator::initialize(ContextImpl& contextRef) {
if (owner != NULL && &contextRef.getOwner() != owner) if (owner != NULL && &contextRef.getOwner() != owner)
throw OpenMMException("This Integrator is already bound to a context"); throw OpenMMException("This Integrator is already bound to a context");
context = &contextRef; context = &contextRef;
owner = &contextRef.getOwner(); owner = &contextRef.getOwner();
kernel = context->getPlatform().createKernel(IntegrateBAOABStepKernel::Name(), contextRef); kernel = context->getPlatform().createKernel(IntegrateLangevinMiddleStepKernel::Name(), contextRef);
kernel.getAs<IntegrateBAOABStepKernel>().initialize(contextRef.getSystem(), *this); kernel.getAs<IntegrateLangevinMiddleStepKernel>().initialize(contextRef.getSystem(), *this);
} }
void BAOABLangevinIntegrator::cleanup() { void LangevinMiddleIntegrator::cleanup() {
kernel = Kernel(); kernel = Kernel();
} }
void BAOABLangevinIntegrator::stateChanged(State::DataType changed) { vector<string> LangevinMiddleIntegrator::getKernelNames() {
forcesAreValid = false;
}
vector<string> BAOABLangevinIntegrator::getKernelNames() {
std::vector<std::string> names; std::vector<std::string> names;
names.push_back(IntegrateBAOABStepKernel::Name()); names.push_back(IntegrateLangevinMiddleStepKernel::Name());
return names; return names;
} }
double BAOABLangevinIntegrator::computeKineticEnergy() { double LangevinMiddleIntegrator::computeKineticEnergy() {
forcesAreValid = false; return kernel.getAs<IntegrateLangevinMiddleStepKernel>().computeKineticEnergy(*context, *this);
return kernel.getAs<IntegrateBAOABStepKernel>().computeKineticEnergy(*context, *this);
} }
bool BAOABLangevinIntegrator::kineticEnergyRequiresForce() const { bool LangevinMiddleIntegrator::kineticEnergyRequiresForce() const {
return false; return false;
} }
void BAOABLangevinIntegrator::step(int steps) { void LangevinMiddleIntegrator::step(int steps) {
if (context == NULL) if (context == NULL)
throw OpenMMException("This Integrator is not bound to a context!"); throw OpenMMException("This Integrator is not bound to a context!");
for (int i = 0; i < steps; ++i) { for (int i = 0; i < steps; ++i) {
if (context->updateContextState()) context->updateContextState();
forcesAreValid = false; context->calcForcesAndEnergy(true, false);
kernel.getAs<IntegrateBAOABStepKernel>().execute(*context, *this, forcesAreValid); kernel.getAs<IntegrateLangevinMiddleStepKernel>().execute(*context, *this);
} }
} }
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2019 Stanford University and the Authors. * * Portions copyright (c) 2008-2020 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -905,44 +905,40 @@ private: ...@@ -905,44 +905,40 @@ private:
}; };
/** /**
* This kernel is invoked by BAOABLangevinIntegrator to take one time step. * This kernel is invoked by LangevinMiddleIntegrator to take one time step.
*/ */
class CommonIntegrateBAOABStepKernel : public IntegrateBAOABStepKernel { class CommonIntegrateLangevinMiddleStepKernel : public IntegrateLangevinMiddleStepKernel {
public: public:
CommonIntegrateBAOABStepKernel(std::string name, const Platform& platform, ComputeContext& cc) : IntegrateBAOABStepKernel(name, platform), cc(cc), CommonIntegrateLangevinMiddleStepKernel(std::string name, const Platform& platform, ComputeContext& cc) : IntegrateLangevinMiddleStepKernel(name, platform), cc(cc),
hasInitializedKernels(false) { hasInitializedKernels(false) {
} }
/** /**
* Initialize the kernel, setting up the particle masses. * Initialize the kernel, setting up the particle masses.
* *
* @param system the System this kernel will be applied to * @param system the System this kernel will be applied to
* @param integrator the BAOABLangevinIntegrator this kernel will be used for * @param integrator the LangevinMiddleIntegrator this kernel will be used for
*/ */
void initialize(const System& system, const BAOABLangevinIntegrator& integrator); void initialize(const System& system, const LangevinMiddleIntegrator& integrator);
/** /**
* Execute the kernel. * Execute the kernel.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for * @param integrator the LangevinMiddleIntegrator this kernel is being used for
* @param forcesAreValid if the context has been modified since the last time step, this will be
* false to show that cached forces are invalid and must be recalculated.
* On exit, this should specify whether the cached forces are valid at the
* end of the step.
*/ */
void execute(ContextImpl& context, const BAOABLangevinIntegrator& integrator, bool& forcesAreValid); void execute(ContextImpl& context, const LangevinMiddleIntegrator& integrator);
/** /**
* Compute the kinetic energy. * Compute the kinetic energy.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for * @param integrator the LangevinMiddleIntegrator this kernel is being used for
*/ */
double computeKineticEnergy(ContextImpl& context, const BAOABLangevinIntegrator& integrator); double computeKineticEnergy(ContextImpl& context, const LangevinMiddleIntegrator& integrator);
private: private:
ComputeContext& cc; ComputeContext& cc;
double prevTemp, prevFriction, prevStepSize; double prevTemp, prevFriction, prevStepSize;
bool hasInitializedKernels; bool hasInitializedKernels;
ComputeArray params, oldDelta; ComputeArray params, oldDelta;
ComputeKernel kernel1, kernel2, kernel3, kernel4; ComputeKernel kernel1, kernel2, kernel3;
}; };
/** /**
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2019 Stanford University and the Authors. * * Portions copyright (c) 2008-2020 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -5547,27 +5547,26 @@ double CommonIntegrateLangevinStepKernel::computeKineticEnergy(ContextImpl& cont ...@@ -5547,27 +5547,26 @@ double CommonIntegrateLangevinStepKernel::computeKineticEnergy(ContextImpl& cont
return cc.getIntegrationUtilities().computeKineticEnergy(0.5*integrator.getStepSize()); return cc.getIntegrationUtilities().computeKineticEnergy(0.5*integrator.getStepSize());
} }
void CommonIntegrateBAOABStepKernel::initialize(const System& system, const BAOABLangevinIntegrator& integrator) { void CommonIntegrateLangevinMiddleStepKernel::initialize(const System& system, const LangevinMiddleIntegrator& integrator) {
cc.initializeContexts(); cc.initializeContexts();
cc.setAsCurrent(); cc.setAsCurrent();
cc.getIntegrationUtilities().initRandomNumberGenerator(integrator.getRandomNumberSeed()); cc.getIntegrationUtilities().initRandomNumberGenerator(integrator.getRandomNumberSeed());
ComputeProgram program = cc.compileProgram(CommonKernelSources::baoab); ComputeProgram program = cc.compileProgram(CommonKernelSources::langevinMiddle);
kernel1 = program->createKernel("integrateBAOABPart1"); kernel1 = program->createKernel("integrateLangevinMiddlePart1");
kernel2 = program->createKernel("integrateBAOABPart2"); kernel2 = program->createKernel("integrateLangevinMiddlePart2");
kernel3 = program->createKernel("integrateBAOABPart3"); kernel3 = program->createKernel("integrateLangevinMiddlePart3");
kernel4 = program->createKernel("integrateBAOABPart4");
if (cc.getUseDoublePrecision() || cc.getUseMixedPrecision()) { if (cc.getUseDoublePrecision() || cc.getUseMixedPrecision()) {
params.initialize<double>(cc, 2, "baoabParams"); params.initialize<double>(cc, 2, "langevinMiddleParams");
oldDelta.initialize<mm_double4>(cc, cc.getPaddedNumAtoms(), "oldDelta"); oldDelta.initialize<mm_double4>(cc, cc.getPaddedNumAtoms(), "oldDelta");
} }
else { else {
params.initialize<float>(cc, 2, "baoabParams"); params.initialize<float>(cc, 2, "langevinMiddleParams");
oldDelta.initialize<mm_float4>(cc, cc.getPaddedNumAtoms(), "oldDelta"); oldDelta.initialize<mm_float4>(cc, cc.getPaddedNumAtoms(), "oldDelta");
} }
prevStepSize = -1.0; prevStepSize = -1.0;
} }
void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLangevinIntegrator& integrator, bool& forcesAreValid) { void CommonIntegrateLangevinMiddleStepKernel::execute(ContextImpl& context, const LangevinMiddleIntegrator& integrator) {
IntegrationUtilities& integration = cc.getIntegrationUtilities(); IntegrationUtilities& integration = cc.getIntegrationUtilities();
int numAtoms = cc.getNumAtoms(); int numAtoms = cc.getNumAtoms();
int paddedNumAtoms = cc.getPaddedNumAtoms(); int paddedNumAtoms = cc.getPaddedNumAtoms();
...@@ -5577,11 +5576,8 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa ...@@ -5577,11 +5576,8 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa
kernel1->addArg(paddedNumAtoms); kernel1->addArg(paddedNumAtoms);
kernel1->addArg(cc.getVelm()); kernel1->addArg(cc.getVelm());
kernel1->addArg(cc.getLongForceBuffer()); kernel1->addArg(cc.getLongForceBuffer());
kernel1->addArg(integration.getPosDelta());
kernel1->addArg(oldDelta);
kernel1->addArg(integration.getStepSize()); kernel1->addArg(integration.getStepSize());
kernel2->addArg(numAtoms); kernel2->addArg(numAtoms);
kernel2->addArg(cc.getPosq());
kernel2->addArg(cc.getVelm()); kernel2->addArg(cc.getVelm());
kernel2->addArg(integration.getPosDelta()); kernel2->addArg(integration.getPosDelta());
kernel2->addArg(oldDelta); kernel2->addArg(oldDelta);
...@@ -5589,8 +5585,6 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa ...@@ -5589,8 +5585,6 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa
kernel2->addArg(integration.getStepSize()); kernel2->addArg(integration.getStepSize());
kernel2->addArg(integration.getRandom()); kernel2->addArg(integration.getRandom());
kernel2->addArg(); // Random index will be set just before it is executed. kernel2->addArg(); // Random index will be set just before it is executed.
if (cc.getUseMixedPrecision())
kernel2->addArg(cc.getPosqCorrection());
kernel3->addArg(numAtoms); kernel3->addArg(numAtoms);
kernel3->addArg(cc.getPosq()); kernel3->addArg(cc.getPosq());
kernel3->addArg(cc.getVelm()); kernel3->addArg(cc.getVelm());
...@@ -5599,15 +5593,6 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa ...@@ -5599,15 +5593,6 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa
kernel3->addArg(integration.getStepSize()); kernel3->addArg(integration.getStepSize());
if (cc.getUseMixedPrecision()) if (cc.getUseMixedPrecision())
kernel3->addArg(cc.getPosqCorrection()); kernel3->addArg(cc.getPosqCorrection());
kernel4->addArg(numAtoms);
kernel4->addArg(paddedNumAtoms);
kernel4->addArg(cc.getVelm());
kernel4->addArg(cc.getLongForceBuffer());
kernel4->addArg(integration.getStepSize());
}
if (!forcesAreValid) {
context.calcForcesAndEnergy(true, false);
forcesAreValid = true;
} }
double temperature = integrator.getTemperature(); double temperature = integrator.getTemperature();
double friction = integrator.getFriction(); double friction = integrator.getFriction();
...@@ -5630,15 +5615,12 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa ...@@ -5630,15 +5615,12 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa
// Perform the integration. // Perform the integration.
kernel2->setArg(8, integration.prepareRandomNumbers(cc.getPaddedNumAtoms())); kernel2->setArg(7, integration.prepareRandomNumbers(cc.getPaddedNumAtoms()));
kernel1->execute(numAtoms); kernel1->execute(numAtoms);
integration.applyConstraints(integrator.getConstraintTolerance()); integration.applyVelocityConstraints(integrator.getConstraintTolerance());
kernel2->execute(numAtoms); kernel2->execute(numAtoms);
integration.applyConstraints(integrator.getConstraintTolerance()); integration.applyConstraints(integrator.getConstraintTolerance());
kernel3->execute(numAtoms); kernel3->execute(numAtoms);
context.calcForcesAndEnergy(true, false);
kernel4->execute(numAtoms);
integration.applyVelocityConstraints(integrator.getConstraintTolerance());
integration.computeVirtualSites(); integration.computeVirtualSites();
// Update the time and step count. // Update the time and step count.
...@@ -5646,8 +5628,6 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa ...@@ -5646,8 +5628,6 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa
cc.setTime(cc.getTime()+stepSize); cc.setTime(cc.getTime()+stepSize);
cc.setStepCount(cc.getStepCount()+1); cc.setStepCount(cc.getStepCount()+1);
cc.reorderAtoms(); cc.reorderAtoms();
if (cc.getAtomsWereReordered())
forcesAreValid = false;
// Reduce UI lag. // Reduce UI lag.
...@@ -5656,7 +5636,7 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa ...@@ -5656,7 +5636,7 @@ void CommonIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLa
#endif #endif
} }
double CommonIntegrateBAOABStepKernel::computeKineticEnergy(ContextImpl& context, const BAOABLangevinIntegrator& integrator) { double CommonIntegrateLangevinMiddleStepKernel::computeKineticEnergy(ContextImpl& context, const LangevinMiddleIntegrator& integrator) {
return cc.getIntegrationUtilities().computeKineticEnergy(0.0); return cc.getIntegrationUtilities().computeKineticEnergy(0.0);
} }
......
enum {VelScale, NoiseScale}; enum {VelScale, NoiseScale};
/** /**
* Perform the first part of BAOAB integration: velocity half step, then position half step. * Perform the first part of integration: velocity step.
*/ */
KERNEL void integrateBAOABPart1(int numAtoms, int paddedNumAtoms, GLOBAL mixed4* RESTRICT velm, GLOBAL const mm_long* RESTRICT force, GLOBAL mixed4* RESTRICT posDelta, KERNEL void integrateLangevinMiddlePart1(int numAtoms, int paddedNumAtoms, GLOBAL mixed4* RESTRICT velm, GLOBAL const mm_long* RESTRICT force,
GLOBAL mixed4* RESTRICT oldDelta, GLOBAL const mixed2* RESTRICT dt) { GLOBAL const mixed2* RESTRICT dt) {
mixed halfdt = 0.5*dt[0].y; mixed fscale = dt[0].y/(mixed) 0x100000000;
mixed fscale = halfdt/(mixed) 0x100000000;
for (int index = GLOBAL_ID; index < numAtoms; index += GLOBAL_SIZE) { for (int index = GLOBAL_ID; index < numAtoms; index += GLOBAL_SIZE) {
mixed4 velocity = velm[index]; mixed4 velocity = velm[index];
if (velocity.w != 0.0) { if (velocity.w != 0.0) {
...@@ -15,59 +14,33 @@ KERNEL void integrateBAOABPart1(int numAtoms, int paddedNumAtoms, GLOBAL mixed4* ...@@ -15,59 +14,33 @@ KERNEL void integrateBAOABPart1(int numAtoms, int paddedNumAtoms, GLOBAL mixed4*
velocity.y += fscale*velocity.w*force[index+paddedNumAtoms]; velocity.y += fscale*velocity.w*force[index+paddedNumAtoms];
velocity.z += fscale*velocity.w*force[index+paddedNumAtoms*2]; velocity.z += fscale*velocity.w*force[index+paddedNumAtoms*2];
velm[index] = velocity; velm[index] = velocity;
mixed4 delta = make_mixed4(halfdt*velocity.x, halfdt*velocity.y, halfdt*velocity.z, 0);
posDelta[index] = delta;
oldDelta[index] = delta;
} }
} }
} }
/** /**
* Perform the second part of BAOAB integration: apply constraint forces to velocities, then interact with heat bath, * Perform the second part of integration: position half step, then interact with heat bath,
* then position half step. * then another position half step.
*/ */
KERNEL void integrateBAOABPart2(int numAtoms, GLOBAL real4* RESTRICT posq, GLOBAL mixed4* RESTRICT velm, GLOBAL mixed4* RESTRICT posDelta, KERNEL void integrateLangevinMiddlePart2(int numAtoms, GLOBAL mixed4* RESTRICT velm, GLOBAL mixed4* RESTRICT posDelta,
GLOBAL mixed4* RESTRICT oldDelta, GLOBAL const mixed* RESTRICT paramBuffer, GLOBAL const mixed2* RESTRICT dt, GLOBAL const float4* RESTRICT random, unsigned int randomIndex GLOBAL mixed4* RESTRICT oldDelta, GLOBAL const mixed* RESTRICT paramBuffer, GLOBAL const mixed2* RESTRICT dt, GLOBAL const float4* RESTRICT random, unsigned int randomIndex
#ifdef USE_MIXED_PRECISION
, GLOBAL real4* RESTRICT posqCorrection
#endif
) { ) {
mixed vscale = paramBuffer[VelScale]; mixed vscale = paramBuffer[VelScale];
mixed noisescale = paramBuffer[NoiseScale]; mixed noisescale = paramBuffer[NoiseScale];
mixed halfdt = 0.5*dt[0].y; mixed halfdt = 0.5*dt[0].y;
mixed invHalfdt = 1/halfdt;
int index = GLOBAL_ID; int index = GLOBAL_ID;
randomIndex += index; randomIndex += index;
while (index < numAtoms) { while (index < numAtoms) {
mixed4 velocity = velm[index]; mixed4 velocity = velm[index];
if (velocity.w != 0.0) { if (velocity.w != 0.0) {
mixed4 delta = posDelta[index]; mixed4 delta = make_mixed4(halfdt*velocity.x, halfdt*velocity.y, halfdt*velocity.z, 0);
mixed sqrtInvMass = SQRT(velocity.w); mixed sqrtInvMass = SQRT(velocity.w);
velocity.x += (delta.x-oldDelta[index].x)*invHalfdt;
velocity.y += (delta.y-oldDelta[index].y)*invHalfdt;
velocity.z += (delta.z-oldDelta[index].z)*invHalfdt;
velocity.x = vscale*velocity.x + noisescale*sqrtInvMass*random[randomIndex].x; velocity.x = vscale*velocity.x + noisescale*sqrtInvMass*random[randomIndex].x;
velocity.y = vscale*velocity.y + noisescale*sqrtInvMass*random[randomIndex].y; velocity.y = vscale*velocity.y + noisescale*sqrtInvMass*random[randomIndex].y;
velocity.z = vscale*velocity.z + noisescale*sqrtInvMass*random[randomIndex].z; velocity.z = vscale*velocity.z + noisescale*sqrtInvMass*random[randomIndex].z;
velm[index] = velocity; velm[index] = velocity;
#ifdef USE_MIXED_PRECISION delta += make_mixed4(halfdt*velocity.x, halfdt*velocity.y, halfdt*velocity.z, 0);
real4 pos1 = posq[index];
real4 pos2 = posqCorrection[index];
mixed4 pos = make_mixed4(pos1.x+(mixed)pos2.x, pos1.y+(mixed)pos2.y, pos1.z+(mixed)pos2.z, pos1.w);
#else
real4 pos = posq[index];
#endif
pos.x += delta.x;
pos.y += delta.y;
pos.z += delta.z;
#ifdef USE_MIXED_PRECISION
posq[index] = make_real4((real) pos.x, (real) pos.y, (real) pos.z, (real) pos.w);
posqCorrection[index] = make_real4(pos.x-(real) pos.x, pos.y-(real) pos.y, pos.z-(real) pos.z, 0);
#else
posq[index] = pos;
#endif
delta = make_mixed4(halfdt*velocity.x, halfdt*velocity.y, halfdt*velocity.z, 0);
posDelta[index] = delta; posDelta[index] = delta;
oldDelta[index] = delta; oldDelta[index] = delta;
} }
...@@ -77,25 +50,24 @@ KERNEL void integrateBAOABPart2(int numAtoms, GLOBAL real4* RESTRICT posq, GLOBA ...@@ -77,25 +50,24 @@ KERNEL void integrateBAOABPart2(int numAtoms, GLOBAL real4* RESTRICT posq, GLOBA
} }
/** /**
* Perform the third part of BAOAB integration: apply constraint forces to velocities, then record * Perform the third part of integration: apply constraint forces to velocities, then record
* the constrained positions in preparation for computing forces. * the constrained positions.
*/ */
KERNEL void integrateBAOABPart3(int numAtoms, GLOBAL real4* RESTRICT posq, GLOBAL mixed4* RESTRICT velm, KERNEL void integrateLangevinMiddlePart3(int numAtoms, GLOBAL real4* RESTRICT posq, GLOBAL mixed4* RESTRICT velm,
GLOBAL mixed4* RESTRICT posDelta, GLOBAL mixed4* RESTRICT oldDelta, GLOBAL const mixed2* RESTRICT dt GLOBAL mixed4* RESTRICT posDelta, GLOBAL mixed4* RESTRICT oldDelta, GLOBAL const mixed2* RESTRICT dt
#ifdef USE_MIXED_PRECISION #ifdef USE_MIXED_PRECISION
, GLOBAL real4* RESTRICT posqCorrection , GLOBAL real4* RESTRICT posqCorrection
#endif #endif
) { ) {
mixed halfdt = 0.5*dt[0].y; mixed invDt = 1/dt[0].y;
mixed invHalfdt = 1/halfdt;
for (int index = GLOBAL_ID; index < numAtoms; index += GLOBAL_SIZE) { for (int index = GLOBAL_ID; index < numAtoms; index += GLOBAL_SIZE) {
mixed4 velocity = velm[index]; mixed4 velocity = velm[index];
if (velocity.w != 0.0) { if (velocity.w != 0.0) {
mixed4 delta = posDelta[index]; mixed4 delta = posDelta[index];
velocity.x += (delta.x-oldDelta[index].x)*invHalfdt; velocity.x += (delta.x-oldDelta[index].x)*invDt;
velocity.y += (delta.y-oldDelta[index].y)*invHalfdt; velocity.y += (delta.y-oldDelta[index].y)*invDt;
velocity.z += (delta.z-oldDelta[index].z)*invHalfdt; velocity.z += (delta.z-oldDelta[index].z)*invDt;
velm[index] = velocity; velm[index] = velocity;
#ifdef USE_MIXED_PRECISION #ifdef USE_MIXED_PRECISION
real4 pos1 = posq[index]; real4 pos1 = posq[index];
...@@ -116,22 +88,3 @@ KERNEL void integrateBAOABPart3(int numAtoms, GLOBAL real4* RESTRICT posq, GLOBA ...@@ -116,22 +88,3 @@ KERNEL void integrateBAOABPart3(int numAtoms, GLOBAL real4* RESTRICT posq, GLOBA
} }
} }
} }
/**
* Perform the fourth part of BAOAB integration: velocity half step.
*/
KERNEL void integrateBAOABPart4(int numAtoms, int paddedNumAtoms, GLOBAL mixed4* RESTRICT velm,
GLOBAL const mm_long* RESTRICT force, GLOBAL const mixed2* RESTRICT dt) {
mixed halfdt = 0.5*dt[0].y;
mixed fscale = halfdt/(mixed) 0x100000000;
for (int index = GLOBAL_ID; index < numAtoms; index += GLOBAL_SIZE) {
mixed4 velocity = velm[index];
if (velocity.w != 0.0) {
velocity.x += fscale*velocity.w*force[index];
velocity.y += fscale*velocity.w*force[index+paddedNumAtoms];
velocity.z += fscale*velocity.w*force[index+paddedNumAtoms*2];
velm[index] = velocity;
}
}
}
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2013-2019 Stanford University and the Authors. * * Portions copyright (c) 2013-2020 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "CpuBAOABDynamics.h"
#include "CpuBondForce.h" #include "CpuBondForce.h"
#include "CpuCustomGBForce.h" #include "CpuCustomGBForce.h"
#include "CpuCustomManyParticleForce.h" #include "CpuCustomManyParticleForce.h"
...@@ -40,6 +39,7 @@ ...@@ -40,6 +39,7 @@
#include "CpuGayBerneForce.h" #include "CpuGayBerneForce.h"
#include "CpuGBSAOBCForce.h" #include "CpuGBSAOBCForce.h"
#include "CpuLangevinDynamics.h" #include "CpuLangevinDynamics.h"
#include "CpuLangevinMiddleDynamics.h"
#include "CpuNeighborList.h" #include "CpuNeighborList.h"
#include "CpuNonbondedForce.h" #include "CpuNonbondedForce.h"
#include "CpuPlatform.h" #include "CpuPlatform.h"
...@@ -538,42 +538,38 @@ private: ...@@ -538,42 +538,38 @@ private:
}; };
/** /**
* This kernel is invoked by BAOABLangevinIntegrator to take one time step. * This kernel is invoked by LangevinMiddleIntegrator to take one time step.
*/ */
class CpuIntegrateBAOABStepKernel : public IntegrateBAOABStepKernel { class CpuIntegrateLangevinMiddleStepKernel : public IntegrateLangevinMiddleStepKernel {
public: public:
CpuIntegrateBAOABStepKernel(std::string name, const Platform& platform, CpuPlatform::PlatformData& data) : IntegrateBAOABStepKernel(name, platform), CpuIntegrateLangevinMiddleStepKernel(std::string name, const Platform& platform, CpuPlatform::PlatformData& data) : IntegrateLangevinMiddleStepKernel(name, platform),
data(data), dynamics(0) { data(data), dynamics(0) {
} }
~CpuIntegrateBAOABStepKernel(); ~CpuIntegrateLangevinMiddleStepKernel();
/** /**
* Initialize the kernel, setting up the particle masses. * Initialize the kernel, setting up the particle masses.
* *
* @param system the System this kernel will be applied to * @param system the System this kernel will be applied to
* @param integrator the BAOABLangevinIntegrator this kernel will be used for * @param integrator the LangevinMiddleIntegrator this kernel will be used for
*/ */
void initialize(const System& system, const BAOABLangevinIntegrator& integrator); void initialize(const System& system, const LangevinMiddleIntegrator& integrator);
/** /**
* Execute the kernel. * Execute the kernel.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for * @param integrator the LangevinMiddleIntegrator this kernel is being used for
* @param forcesAreValid if the context has been modified since the last time step, this will be
* false to show that cached forces are invalid and must be recalculated.
* On exit, this should specify whether the cached forces are valid at the
* end of the step.
*/ */
void execute(ContextImpl& context, const BAOABLangevinIntegrator& integrator, bool& forcesAreValid); void execute(ContextImpl& context, const LangevinMiddleIntegrator& integrator);
/** /**
* Compute the kinetic energy. * Compute the kinetic energy.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for * @param integrator the LangevinMiddleIntegrator this kernel is being used for
*/ */
double computeKineticEnergy(ContextImpl& context, const BAOABLangevinIntegrator& integrator); double computeKineticEnergy(ContextImpl& context, const LangevinMiddleIntegrator& integrator);
private: private:
CpuPlatform::PlatformData& data; CpuPlatform::PlatformData& data;
CpuBAOABDynamics* dynamics; CpuLangevinMiddleDynamics* dynamics;
std::vector<double> masses; std::vector<double> masses;
double prevTemp, prevFriction, prevStepSize; double prevTemp, prevFriction, prevStepSize;
}; };
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment