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

1""" 

2.. class:: OpenMMForceWrapper 

3 :platform: Linux, MacOS, Windows 

4 :synopsis: A collective variable built from the potential energy of an OpenMM force 

5 

6.. classauthor:: Charlles Abreu <craabreu@gmail.com> 

7 

8""" 

9 

10import typing as t 

11 

12import openmm 

13from openmm import unit as mmunit 

14 

15from .collective_variable import CollectiveVariable 

16from .units import Unit, VectorQuantity 

17 

18 

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. 

23 

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. 

41 

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 """ 

67 

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) 

89 

90 def __getattr__(self, name: str) -> t.Any: 

91 attr = getattr(self._wrapped_force, name) 

92 if callable(attr): 

93 

94 def _wrapped_method(*args, **kwargs): 

95 return attr(*args, **kwargs) 

96 

97 return _wrapped_method 

98 

99 return attr 

100 

101 

102OpenMMForceWrapper.registerTag("!cvpack.OpenMMForceWrapper")