Running a PyRETIS simulation with OpenMMΒΆ

In this example we will show the interface between OpenMM and PyRETIS. The implementation, so far, only exists as a library. So instead of using the standard PyRETIS input files, this example will consist of python scripts. They will import PyRETIS and OpenMM objects and use them directly.

First we will have to generate an OpenMM Simulation object. We use the online tool OpenMM Script Builder to generate the example pdb of 2 water molecules.

##########################################################################
# this script was generated by openmm-builder. to customize it further,
# you can save the file to disk and edit it with your favorite editor.
##########################################################################

from simtk.openmm import app
import simtk.openmm as mm
from simtk import unit

pdb = app.PDBFile('input.pdb')
forcefield = app.ForceField('amber99sbildn.xml', 'tip3p.xml')

system = forcefield.createSystem(pdb.topology, nonbondedMethod=app.PME,
                                 nonbondedCutoff=1.0*unit.nanometers,
                                 constraints=app.HBonds, rigidWater=True,
                                 ewaldErrorTolerance=0.0005)
integrator = mm.LangevinIntegrator(300*unit.kelvin,
                                   1.0/unit.picoseconds,
                                   2.0*unit.femtoseconds)
integrator.setConstraintTolerance(0.00001)
platform = mm.Platform.getPlatformByName('CPU')
simulation = app.Simulation(pdb.topology, system, integrator, platform)
simulation.context.setPositions(pdb.positions)

With this Simulation object we can now construct the internal PyRETIS system and OpenMMEngine objects

import simtk.unit as u
from pyretis.core import System, Particles
from pyretis.core.box import create_box, box_matrix_to_list
from pyretis.engines import OpenMMEngine
def make_pyretis_system(simulation):
    """Makes PyRETIS system from OpenMM Simulation."""
    state = simulation.context.getState(getPositions=True, getVelocities=True)
    box = state.getPeriodicBoxVectors(asNumpy=True).T
    box = create_box(cell=box_matrix_to_list(box),
                     periodic=[True, True, True])
    system = System(units='gromacs', box=box,
                    temperature=simulation.integrator.getTemperature())
    system.particles = Particles(system.get_dim())
    pos = state.getPositions(asNumpy=True)
    vel = state.getVelocities(asNumpy=True)
    for i, atom in enumerate(simulation.topology.atoms()):
        mass = simulation.system.getParticleMass(i)
        mass = mass.value_in_unit(u.grams/u.mole)
        name = atom.name
        system.particles.add_particle(pos=pos[i], vel=vel[i],
                                      force=[None, None, None],
                                      mass=mass, name=name)
    return system

# Make system and initialise the engine.
system = make_pyretis_system(simulation=simulation)
engine = OpenMMEngine(simulation=simulation)

From this point on we can define an order parameter, interfaces and propagate with this engine inside the TIS ensemble.

from pyretis.core.random_gen import RandomGenerator
from pyretis.core.path import Path
from pyretis.orderparameter import Distance
import numpy as np

# Get a random number generator
rgen = RandomGenerator(seed=1)

# Define an empty path of a specific max length (10 in this case)
path = Path(None, maxlen=10)

# Define the order parameter, the distance between the two water oxygens
order_parameter = Distance((0, 3), periodic=False)

# Define state A, Interface and state B of the sampled TIS ensemble.
ifaces = (1, 2, 3)

# Modify the velocities of the shooting point
engine.modify_velocities(system, rgen=rgen,
                         sigma_v=None, aimless=True,
                         momentum=False, rescale=None)

# Propegate forward
engine.propagate(path=path, initial_system=system,
                 order_function=order_parameter,
                 interfaces=ifaces , reverse=False)

The path variable now will have the newly generated path for the user to apply acceptance criteria on. The communication to and from the OpenMM kernel has been reduced to a minimum, as communication can be expensive for simulations on GPUs. Further integration with the PyRETIS application layer is envisioned for later PyRETIS releases.