Coverage for cvpack/torsion.py: 100%
12 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:: Torsion
3 :platform: Linux, MacOS, Windows
4 :synopsis: The torsion angle formed by four atoms
6.. classauthor:: Charlles Abreu <craabreu@gmail.com>
8"""
10import numpy as np
11import openmm
12from openmm import unit as mmunit
14from .collective_variable import CollectiveVariable
17class Torsion(CollectiveVariable, openmm.CustomTorsionForce):
18 r"""
19 The torsion angle formed by four atoms:
21 .. math::
23 \varphi({\bf r}) = {\rm atan2}\left(\frac{
24 ({\bf r}_{2,1} \times {\bf r}_{3,4}) \cdot {\bf u}_{2,3}
25 }{
26 {\bf r}_{2,1} \cdot {\bf r}_{3,4} -
27 ({\bf r}_{2,1} \cdot {\bf u}_{2,3})
28 ({\bf r}_{3,4} \cdot {\bf u}_{2,3})
29 }\right),
31 where :math:`{\bf r}_{i,j} = {\bf r}_j - {\bf r}_i`,
32 :math:`{\bf u}_{2,3} = {\bf r}_{2,3}/\|{\bf r}_{2,3}\|`,
33 and `atan2 <https://en.wikipedia.org/wiki/Atan2>`_ is the arctangent function that
34 receives the numerator and denominator above as separate arguments.
36 Parameters
37 ----------
38 atom1
39 The index of the first atom.
40 atom2
41 The index of the second atom.
42 atom3
43 The index of the third atom.
44 atom4
45 The index of the fourth atom.
46 pbc
47 Whether to use periodic boundary conditions in distance calculations.
48 name
49 The name of the collective variable.
51 Example
52 -------
53 >>> import cvpack
54 >>> import openmm
55 >>> system = openmm.System()
56 >>> [system.addParticle(1) for i in range(4)]
57 [0, 1, 2, 3]
58 >>> torsion = cvpack.Torsion(0, 1, 2, 3, pbc=False)
59 >>> system.addForce(torsion)
60 0
61 >>> integrator = openmm.VerletIntegrator(0)
62 >>> platform = openmm.Platform.getPlatformByName('Reference')
63 >>> context = openmm.Context(system, integrator, platform)
64 >>> positions = [[0, 0, 0], [1, 0, 0], [1, 1, 0], [1, 1, 1]]
65 >>> context.setPositions([openmm.Vec3(*pos) for pos in positions])
66 >>> torsion.getValue(context)
67 1.5707... rad
69 """
71 def __init__(
72 self,
73 atom1: int,
74 atom2: int,
75 atom3: int,
76 atom4: int,
77 pbc: bool = False,
78 name: str = "torsion",
79 ) -> None:
80 super().__init__("theta")
81 self.addTorsion(atom1, atom2, atom3, atom4, [])
82 self.setUsesPeriodicBoundaryConditions(pbc)
83 self._registerCV(
84 name,
85 mmunit.radians,
86 atom1=atom1,
87 atom2=atom2,
88 atom3=atom3,
89 atom4=atom4,
90 pbc=pbc,
91 )
92 self._registerPeriodicBounds(-np.pi, np.pi)
95Torsion.registerTag("!cvpack.Torsion")