"""Core APIs."""
from __future__ import annotations
from typing import TYPE_CHECKING
import numpy as np
from spinspg.group import (
SYMMETRY_FINDER_BACKEND,
get_primitive_spin_symmetry,
get_symmetry_with_cell,
)
if TYPE_CHECKING:
from spinspg.spin import SpinOnlyGroup
from spinspg.utils import NDArrayFloat, NDArrayInt
[docs]
def get_spin_symmetry(
lattice: NDArrayFloat,
positions: NDArrayFloat,
numbers: NDArrayInt,
magmoms: NDArrayFloat,
symprec: float = 1e-5,
mag_symprec: float | None = None,
angle_tolerance: float = -1.0,
backend: SYMMETRY_FINDER_BACKEND = "spglib",
) -> tuple[SpinOnlyGroup, NDArrayInt, NDArrayFloat, NDArrayFloat]:
"""Return spin symmetry operations of a given spin arrangement.
See :ref:`Spglib's document <spglib:py_variables_crystal_structure>` for how to specify the spin arrangement by ``lattice``, ``positions``, ``numbers``, and ``magmoms`` in details.
With the returned spin symmetry operations, the ``i``-th spin symmetry operation maps point coordinates ``x`` to ``rotations[i] @ x + translations[i]`` and magnetic moment ``m`` to ``spin_rotations[i] @ m``.
Parameters
----------
lattice: array, (3, 3)
``lattice[i, :]`` is the ``i``-th basis vector of a lattice
positions: array, (num_sites, 3)
``positions[i, :]`` is a fractional coordinates of the ``i``-th site w.r.t. ``lattice``.
numbers: array[int], (num_sites, )
``numbers[i]`` specifies a specie at the ``i``-th site.
magmoms: array, (num_sites, 3)
``magmoms[i, :]`` is a magnetic moments at the ``i``-th site in Cartesian coordinates.
symprec: float, default=1e-5
See :ref:`spglib:variables_symprec`.
mag_symprec: float | None
See :ref:`spglib:variables_mag_symprec`.
angle_tolerance: float, default=-1
See :ref:`spglib:variables_angle_tolerance`.
Returns
-------
spin_only_group: :class:`spin.SpinOnlyGroup`
Spin-only group, which preserve the given spin arrangement with identity spatial operation.
rotations: array[int], (num_sym, 3, 3)
Rotation parts of spin symmetry operations w.r.t. ``lattice``.
translations: array, (num_sym, 3)
Translation parts of spin symmetry operations w.r.t. ``lattice``.
spin_rotations: array, (num_sym, 3, 3)
Spin rotation parts of spin symmetry operations in Cartesian coordinates.
"""
ns = get_symmetry_with_cell(
lattice, positions, numbers, symprec, angle_tolerance, backend=backend
)
ssg = get_primitive_spin_symmetry(
ns, magmoms, mag_symprec=mag_symprec if mag_symprec is not None else symprec
)
spin_only_group = ssg.spin_only_group
tmat = ssg.transformation
invtmat = np.linalg.inv(tmat)
rotations = []
translations = []
spin_rotations = []
# Products of "translations in cell", "nontrivial spin translation group's coset", and "nontrivial spin space group's coset"
for ops in ssg.nontrivial_coset:
# Transform to primitive to input cell
new_rotation = np.around(invtmat @ ops.rotation @ tmat).astype(np.int_)
for ops_st in ssg.spin_translation_coset:
for centering in ssg.prim_centerings:
new_translation = np.remainder(
invtmat @ (ops.translation + ops_st.translation + centering), 1
)
rotations.append(new_rotation)
translations.append(new_translation)
spin_rotations.append(ops_st.spin_rotation @ ops.spin_rotation)
return spin_only_group, np.array(rotations), np.array(translations), np.array(spin_rotations)