OpenMMTools Integration

This enables OPS to use any testsystem from openmmtools to be used as well as add ANY possible OpenMM setup, not just the ones that we provided before. The old OpenMMEngine has been rename intp SimpleOpenMMEngine


In [1]:
from __future__ import print_function

import openpathsampling as paths
import openmmtools as omt
import simtk.openmm as omm
import simtk.unit as u
import mdtraj as md

import openpathsampling.engines.openmm as eng

Create Alanine in Vacuum and run it using OPS.


In [2]:
testsystem = omt.testsystems.AlanineDipeptideVacuum()

Let's have a look at the content


In [3]:
#! skip
{ key: type(value) for key, value in testsystem.__dict__.items()}


Out[3]:
{'_positions': simtk.unit.quantity.Quantity,
 '_system': simtk.openmm.openmm.System,
 '_topology': simtk.openmm.app.topology.Topology}

An OpenMM simulation in OPS needs 3 ingredients to function

  1. A template snapshot (which contains topolgy and coordinates/velocities),
  2. an OpenMM system object, and
  3. an OpenMM integrator object.

In the following we will get these parts.

1. The template

The information for the template is contained in the _topology and the _positions object.


In [4]:
template = eng.snapshot_from_testsystem(testsystem)

2. The system

This is easy since we directly get it from the testsytem objects


In [5]:
system = testsystem.system

3. The integrator

The openmmtools system is (almost) independent of the integrator and openmm provides us with lots of options. For now we pick something simple.


In [6]:
integrator = omm.VerletIntegrator(
    0.002 * u.picoseconds    
)

build the engine


In [7]:
engine = eng.Engine(
    template.topology, 
    system, 
    integrator)

Let's run a simulation of 10 steps.


In [8]:
traj = engine.generate(template, [paths.LengthEnsemble(10).can_append])

In [9]:
assert len(traj) == 10

In [10]:
#! skip
print(traj[5].coordinates)


[[ 0.18766722  0.11599677  0.01245   ]
 [ 0.19458348  0.22444929  0.00401418]
 [ 0.14436732  0.27122673  0.08869708]
 [ 0.14886753  0.25747469 -0.08926163]
 [ 0.33994535  0.26638278  0.00609841]
 [ 0.42709583  0.18970115  0.0438005 ]
 [ 0.36886495  0.38998333 -0.03181564]
 [ 0.29336688  0.45243087 -0.05633814]
 [ 0.49859312  0.45657614 -0.02400122]
 [ 0.55814373  0.41515267  0.05735515]
 [ 0.57325351  0.43391329 -0.15561193]
 [ 0.51911271  0.48312774 -0.23640624]
 [ 0.67427617  0.47320506 -0.14414099]
 [ 0.58423084  0.32728142 -0.17536463]
 [ 0.47495222  0.60669047 -0.00127666]
 [ 0.35958397  0.64924192  0.00474685]
 [ 0.58359265  0.68379164  0.00902623]
 [ 0.6747424   0.64066124  0.00332432]
 [ 0.57127428  0.82897234  0.0185309 ]
 [ 0.46718934  0.86095452  0.02347786]
 [ 0.62214297  0.86301553  0.10872202]
 [ 0.61715889  0.87434286 -0.06931634]] nm

In [11]:
psi = md.compute_psi(traj.to_mdtraj())


/Users/dwhs/miniconda3/lib/python3.6/site-packages/mdtraj/utils/validation.py:116: TypeCastPerformanceWarning: Casting unitcell_vectors dtype=float64 to <class 'numpy.float32'> 
  TypeCastPerformanceWarning)

In [12]:
#! ignore
psi[1][3:8]


Out[12]:
array([[ 3.10614586],
       [-3.09586358],
       [ 3.1367557 ],
       [ 3.12832713],
       [ 3.09317851]], dtype=float32)

In [13]:
st = paths.Storage('engine_store_test.nc', mode='w')

In [14]:
st.engines.save(engine);
st.tag['template'] = template

The engine is stored by using the XML serialization of OpenMM and put this into the storage.


In [15]:
#! skip
st.variables['engines_json'][0][0:256] + '...'


Out[15]:
'{"_cls":"OpenMMEngine","_dict":{"system_xml":"<?xml version=\\"1.0\\" ?>\\n<System openmmVersion=\\"7.1.1\\" type=\\"System\\" version=\\"1\\">\\n\\t<PeriodicBoxVectors>\\n\\t\\t<A x=\\"2\\" y=\\"0\\" z=\\"0\\"\\/>\\n\\t\\t<B x=\\"0\\" y=\\"2\\" z=\\"0\\"\\/>\\n\\t\\t<C x=\\"0\\" y=\\"0\\" z=\\...'

In [16]:
st.save(traj);

In [17]:
st.close()

try to load the stored engine


In [18]:
st = paths.AnalysisStorage('engine_store_test.nc')

In [19]:
engine = st.engines[0]

Run another 10 steps to test


In [20]:
template = st.tag['template']

In [21]:
traj = engine.generate(template, [paths.LengthEnsemble(10).can_append])

In [22]:
print(traj)


Trajectory[10]

In [23]:
st.close()

And save the trajectory for future use (other tests)


In [24]:
st = paths.Storage('engine_store_test.nc', "a")
st.save(traj)
st.close()

In [ ]: