Source code for httk.atomistic.models.cell.numeric

"""
The NumericCell presentation: a Cell exposed as plain numpy numbers.
"""

from httk.core import NumericVector, to_numeric, to_numeric_scalar

from httk.atomistic.models._vector_guards import require_numpy
from httk.atomistic.models.cell.cell import Cell
from httk.atomistic.models.cell.like import CellLike
from httk.atomistic.models.cell.view import CellView


[docs] class NumericCell: """ A plain-numpy presentation of a :class:`~httk.atomistic.Cell`. Where a ``Cell`` holds its geometry **exactly** (a :class:`~httk.core.SurdVector` basis, exact ``SurdScalar`` lengths/volume, exact ``Fraction`` angles), a ``NumericCell`` mirrors that interface but returns plain numpy numbers — a ``float64`` :class:`numpy.ndarray` for every vector and a plain :class:`float` for every scalar — for callers who do not need exact arithmetic and just want numpy arrays. The presentation is numpy-backed, so constructing a ``NumericCell`` **requires numpy** (the ``httk-atomistic[numpy]`` extra) and raises :class:`ImportError` eagerly when it is unavailable. The exact object is always one hop away via :attr:`exact`. :param cell: The cell or cell-like object to present. """ _cell: Cell def __init__(self, cell: CellLike) -> None: require_numpy() self._cell = cell if isinstance(cell, Cell) else CellView(cell) def _vector(self, values: tuple[object, ...]) -> NumericVector: """Present a tuple of exact scalars as a plain ``float64`` numpy vector.""" return to_numeric(tuple(to_numeric_scalar(value) for value in values)) @property
[docs] def scale(self) -> float: """The overall length factor. :return: The scale as a floating-point value. """ return to_numeric_scalar(self._cell.scale)
@property
[docs] def precision(self) -> float | None: """The cell precision, or ``None`` if unknown. :return: The absolute precision as a floating-point value. """ return None if self._cell.precision is None else float(self._cell.precision)
@property
[docs] def periodicity(self) -> tuple[bool, bool, bool]: """Which of the three basis rows is a genuine lattice translation. :return: Flags identifying the periodic basis rows. """ return self._cell.periodicity
@property
[docs] def nperiodic_dimensions(self) -> int: """How many of the three directions are periodic. :return: The number of periodic directions. """ return self._cell.nperiodic_dimensions
@property
[docs] def unscaled_basis(self) -> NumericVector: """The 3x3 cell vectors before applying ``scale``. :return: The unscaled lattice vectors as floating-point values. """ return to_numeric(self._cell.unscaled_basis)
@property
[docs] def basis(self) -> NumericVector: """The 3x3 lattice vectors ``scale * unscaled_basis``. :return: The scaled lattice vectors as floating-point values. """ return to_numeric(self._cell.basis)
@property
[docs] def lengths(self) -> NumericVector: """The three cell-vector lengths. :return: The lengths as floating-point values. """ return self._vector(self._cell.lengths)
@property
[docs] def angles(self) -> NumericVector: """The cell angles ``(alpha, beta, gamma)`` in degrees. :return: The angles as floating-point values. """ return self._vector(self._cell.angles)
@property
[docs] def volume(self) -> float: """The cell volume. :return: The volume as a floating-point value. :raises ValueError: If the exact cell is not periodic in all three directions. """ return to_numeric_scalar(self._cell.volume)
[docs] def metric(self) -> NumericVector: """The Gram matrix ``basis * basis^T``. :return: The Gram matrix as floating-point values. """ return to_numeric(self._cell.metric())
@property
[docs] def exact(self) -> Cell: """The exact cell this presentation wraps. :return: The exact cell. """ return self._cell
def __repr__(self) -> str: return f"NumericCell(basis={self.basis!r}, scale={self.scale!r})"