Coverage for cvpack/openmm_force_wrapper.py: 74%
23 statements
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-09 16:14 +0000
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-09 16:14 +0000
1"""
2.. class:: OpenMMForceWrapper
3 :platform: Linux, MacOS, Windows
4 :synopsis: A collective variable built from the potential energy of an OpenMM force
6.. classauthor:: Charlles Abreu <craabreu@gmail.com>
8"""
10import typing as t
12import openmm
13from openmm import unit as mmunit
15from .collective_variable import CollectiveVariable
16from .units import Unit, VectorQuantity
19class OpenMMForceWrapper(CollectiveVariable, openmm.Force):
20 r"""
21 A collective variable whose numerical value is computed from the potential energy,
22 in kJ/mol, of an OpenMM force object.
24 Parameters
25 ----------
26 openmmForce
27 The OpenMM force whose potential energy will be used to define the collective
28 variable. It can be passed as an instance of :OpenMM:`Force` or as a string
29 containing the XML serialization of the force.
30 unit
31 The unit of measurement of the collective variable. It must be compatible
32 with the MD unit system (mass in `daltons`, distance in `nanometers`, time
33 in `picoseconds`, temperature in `kelvin`, energy in `kilojoules_per_mol`,
34 angle in `radians`). If the collective variables does not have a unit, use
35 `dimensionless`.
36 periodicBounds
37 The periodic bounds of the collective variable if it is periodic, or `None` if
38 it is not.
39 name
40 The name of the collective variable.
42 Example
43 -------
44 >>> import cvpack
45 >>> import numpy as np
46 >>> import openmm
47 >>> from openmm import unit
48 >>> from openmmtools import testsystems
49 >>> model = testsystems.AlanineDipeptideVacuum()
50 >>> angle = openmm.CustomAngleForce("theta")
51 >>> _ = angle.addAngle(0, 1, 2)
52 >>> cv = cvpack.OpenMMForceWrapper(
53 ... angle,
54 ... unit.radian,
55 ... periodicBounds=[-np.pi, np.pi] * unit.radian,
56 ... )
57 >>> cv.addToSystem(model.system)
58 >>> integrator = openmm.VerletIntegrator(0)
59 >>> platform = openmm.Platform.getPlatformByName("Reference")
60 >>> context = openmm.Context(model.system, integrator, platform)
61 >>> context.setPositions(model.positions)
62 >>> cv.getValue(context)
63 1.911... rad
64 >>> cv.getEffectiveMass(context)
65 0.00538... nm**2 Da/(rad**2)
66 """
68 def __init__( # pylint: disable=super-init-not-called
69 self,
70 openmmForce: t.Union[openmm.Force, str],
71 unit: mmunit.Unit,
72 periodicBounds: t.Optional[VectorQuantity] = None,
73 name: str = "openmm_force_wrapper",
74 ) -> None:
75 if isinstance(openmmForce, openmm.Force):
76 openmmForce = openmm.XmlSerializer.serialize(openmmForce)
77 unit = Unit(unit)
78 self._wrapped_force = openmm.XmlSerializer.deserialize(openmmForce)
79 self.this = self._wrapped_force.this
80 self._registerCV(
81 name,
82 unit,
83 openmmForce=openmmForce,
84 unit=unit,
85 periodicBounds=periodicBounds,
86 )
87 if periodicBounds is not None:
88 self._registerPeriodicBounds(*periodicBounds)
90 def __getattr__(self, name: str) -> t.Any:
91 attr = getattr(self._wrapped_force, name)
92 if callable(attr):
94 def _wrapped_method(*args, **kwargs):
95 return attr(*args, **kwargs)
97 return _wrapped_method
99 return attr
102OpenMMForceWrapper.registerTag("!cvpack.OpenMMForceWrapper")