"""
Periodic Info
=============
Class holding periodic cell information.
"""
from __future__ import annotations
import logging
import numpy as np
from stk._internal.utilities.utilities import cap_absolute_value
logger = logging.getLogger(__name__)
[docs]
class PeriodicInfo:
"""
Periodic cell information for periodic systems.
"""
def __init__(
self,
vector_1: np.ndarray,
vector_2: np.ndarray,
vector_3: np.ndarray,
) -> None:
"""
Initialize a :class:`.PeriodicInfo` instance.
Converts cell matrix to lengths and angles, where lengths are
in Angstrom and angles are in degrees. This code is modified
from the pymatgen source code [1]_.
Parameters:
vector_1:
First cell lattice vector of shape (3, ) in Angstrom.
vector_2:
Second cell lattice vector of shape (3, ) in Angstrom.
vector_3:
Third cell lattice vector of shape (3, ) in Angstrom.
References:
.. [1] https://pymatgen.org/_modules/pymatgen/core/\
lattice.html
"""
self._vector_1 = np.array(vector_1)
self._vector_2 = np.array(vector_2)
self._vector_3 = np.array(vector_3)
self._cell_matrix = (
self._vector_1,
self._vector_2,
self._vector_3,
)
a, b, c = tuple(
np.sqrt(np.sum(i**2)).tolist() for i in self._cell_matrix
)
self._a = a
self._b = b
self._c = c
lengths = (a, b, c)
angles = np.zeros(3)
for i in range(3):
j = (i + 1) % 3
k = (i + 2) % 3
angles[i] = cap_absolute_value(
value=(
np.dot(self._cell_matrix[j], self._cell_matrix[k])
/ (lengths[j] * lengths[k])
),
)
angles = np.arccos(angles) * 180.0 / np.pi
alpha, beta, gamma = angles
self._alpha = alpha
self._beta = beta
self._gamma = gamma
[docs]
def clone(self) -> PeriodicInfo:
"""
Return a clone.
Returns:
The clone.
"""
clone = self.__class__.__new__(self.__class__)
PeriodicInfo.__init__(
self=clone,
vector_1=self._vector_1,
vector_2=self._vector_2,
vector_3=self._vector_3,
)
return clone
[docs]
def get_vector_1(self) -> np.ndarray:
"""
Get *x* vector.
Returns:
Cell lattice vector of shape (3, ) in *x* direction in
Angstrom.
"""
return np.array(self._vector_1)
[docs]
def get_vector_2(self) -> np.ndarray:
"""
Get *y* vector.
Returns:
Cell lattice vector of shape (3, ) in *y* direction in
Angstrom.
"""
return np.array(self._vector_2)
[docs]
def get_vector_3(self) -> np.ndarray:
"""
Get *z* vector.
Returns:
Cell lattice vector of shape (3, ) in *z* direction in
Angstrom.
"""
return np.array(self._vector_3)
[docs]
def get_cell_matrix(
self,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""
Get cell matrix.
Returns:
Tuple of length three containing *x*, *y* and *z* direction
lattice vector of shape (3, ) in Angstrom.
"""
a, b, c = self._cell_matrix
return (np.array(a), np.array(b), np.array(c))
[docs]
def get_a(self) -> float:
"""
Get *a* length.
Returns:
Length of cell along *a* direction in Angstrom.
"""
return self._a
[docs]
def get_b(self) -> float:
"""
Get *b* length.
Returns:
Length of cell along *b* direction in Angstrom.
"""
return self._b
[docs]
def get_c(self) -> float:
"""
Get *c* length.
Returns:
Length of cell along *c* direction in Angstrom.
"""
return self._c
[docs]
def get_alpha(self) -> float:
"""
Get *alpha* angle.
Returns:
*Alpha* angle of cell in degrees.
"""
return self._alpha
[docs]
def get_beta(self) -> float:
"""
Get *beta* angle.
Returns:
*Beta* angle of cell in degrees.
"""
return self._beta
[docs]
def get_gamma(self) -> float:
"""
Get *gamma* angle.
Returns:
*Gamma* angle of cell in degrees.
"""
return self._gamma
def __str__(self) -> str:
return (
f"{self.__class__.__name__}(a={self._a}, b={self._b}, "
f"c={self._c}, alpha={self._alpha}, beta={self._beta}, "
f"gamma={self._gamma})"
)
def __repr__(self) -> str:
return str(self)