Source code for cvpack.angle
"""
.. class:: Angle
:platform: Linux, MacOS, Windows
:synopsis: The angle formed by three atoms
.. classauthor:: Charlles Abreu <craabreu@gmail.com>
"""
import numpy as np
import openmm
from openmm import unit as mmunit
from .collective_variable import CollectiveVariable
[docs]
class Angle(CollectiveVariable, openmm.CustomAngleForce):
r"""
The angle formed by three atoms:
.. math::
\theta({\bf r}) =
\mathrm{acos}\left(
\frac{{\bf r}_{2,1} \cdot {\bf r}_{2,3} }
{\| {\bf r}_{2,1} \| \| {\bf r}_{2,3} \|}
\right),
where :math:`{\bf r}_{i,j} = {\bf r}_j - {\bf r}_i`.
Parameters
----------
atom1
The index of the first atom.
atom2
The index of the second atom.
atom3
The index of the third atom.
pbc
Whether to use periodic boundary conditions.
name
The name of the collective variable.
Example
-------
>>> import cvpack
>>> import openmm
>>> system = openmm.System()
>>> [system.addParticle(1) for i in range(3)]
[0, 1, 2]
>>> angle = cvpack.Angle(0, 1, 2)
>>> system.addForce(angle)
0
>>> integrator = openmm.VerletIntegrator(0)
>>> platform = openmm.Platform.getPlatformByName('Reference')
>>> context = openmm.Context(system, integrator, platform)
>>> positions = [[0, 0, 0], [1, 0, 0], [1, 1, 0]]
>>> context.setPositions([openmm.Vec3(*pos) for pos in positions])
>>> angle.getValue(context)
1.570796... rad
"""
def __init__(
self,
atom1: int,
atom2: int,
atom3: int,
pbc: bool = False,
name: str = "angle",
) -> None:
super().__init__("theta")
self.addAngle(atom1, atom2, atom3, [])
self.setUsesPeriodicBoundaryConditions(pbc)
self._registerCV(
name, mmunit.radians, atom1=atom1, atom2=atom2, atom3=atom3, pbc=pbc
)
self._registerPeriodicBounds(-np.pi, np.pi)
Angle.registerTag("!cvpack.Angle")