Source code for pyretis.orderparameter.orderangle
# -*- coding: utf-8 -*-
# Copyright (c) 2023, PyRETIS Development Team.
# Distributed under the LGPLv2.1+ License. See LICENSE for more info.
"""This file contains classes to represent angle order parameters.
Important classes defined here
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Angle (:py:class:`.Angle`)
An angle defined by three atoms.
"""
import logging
from numpy import dot
from numpy import arccos # pylint: disable=no-name-in-module
from numpy import clip
from numpy.linalg import norm
from pyretis.orderparameter.orderparameter import OrderParameter
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
logger.addHandler(logging.NullHandler())
__all__ = ['Angle']
[docs]class Angle(OrderParameter):
"""An angle order parameter.
This class defines an order parameter which is an angle
ABC for 3 particles A, B and C. The angle is defined as the
angle given by the two vectors BA and BC.
Attributes
----------
index : list of integers
These are the indices of atoms to be used for the angle,
i.e. system.particles.pos[index] will be used.
periodic : boolean
This determines if periodic boundaries should be applied to
the positions/distances.
"""
[docs] def __init__(self, index, periodic=False):
"""Initialise the order parameter.
Parameters
----------
index : list/tuple of integers
The indices for the atoms defining the angle.
periodic : boolean, optional
This determines if periodic boundary conditions should be
applied to the distance vectors.
"""
try:
if len(index) != 3:
msg = ('Wrong number of atoms for angle definition. '
f'Expected 3 got {len(index)}')
logger.error(msg)
raise ValueError(msg)
except TypeError as err:
msg = 'Angle should be defined as a tuple/list of integers!'
logger.error(msg)
raise TypeError(msg) from err
txt = f'Angle between particles {index[0]}, {index[1]} and {index[2]}'
super().__init__(description=txt)
self.periodic = periodic
self.index = [int(i) for i in index]
[docs] def calculate(self, system):
"""Calculate the angle.
Parameters
----------
system : object like :py:class:`.System`
Object containing the positions and box info we use for
the calculation.
Returns
-------
out : list of floats
The order parameters.
"""
pos = system.particles.pos
vector_ba = pos[self.index[1]] - pos[self.index[0]]
vector_bc = pos[self.index[1]] - pos[self.index[2]]
if self.periodic:
vector_ba = system.box.pbc_dist_coordinate(vector_ba)
vector_bc = system.box.pbc_dist_coordinate(vector_bc)
vector_ba /= norm(vector_ba)
vector_bc /= norm(vector_bc)
angle = arccos(clip(dot(vector_ba, vector_bc), -1, 1))
return [angle]