Orbital transforms
Orbital data may need a different coordinate representation or scale for prediction, comparison, or subsequent physical calculations. These transforms operate on the Torch data structures used for batching, while retaining the basis ordering and physical conventions of the underlying quantities.
Clebsch–Gordan coupling resolves each pair of orbital angular momenta into spherical components. Affine transforms apply fixed scales and symmetry-compatible shifts. A Bloch transform combines cell-shift-indexed blocks into matrices at selected k-points. Each operation has its own role and can be composed where needed.
Coupled orbital coordinates
The CG transform preserves the atom-pair block mapping and changes the coordinates within each block. It provides both decomposition into coupled components and composition back into orbital matrix elements.
BlockSparseCGTransform
BlockSparseCGTransform(basis_set: BasisSet)
Bases: Module
Change packed block-sparse values to and from coupled coordinates.
The transform is defined by one BasisSet. For every ordered pair of
shells with angular momenta \((\ell_1, \ell_2)\), it replaces the flattened
product basis \(m_1 \otimes m_2\) by the canonical sequence
Both orbital axes and the coupled M components use ELFES's Wikipedia real spherical-harmonic basis, ordered from -l to +l (l=1: y, z, x). No Cartesian permutation or conversion to another component basis is required. Coefficients come from the vendored NumPy Wigner-3j generator also used by S2NN tensor products, with its real coupling-path phases. Multiplying each unit-Frobenius-norm block by \(\sqrt{2L+1}\) makes the complete matrix orthogonal, so the inverse is its transpose.
Input and output use the same BlockSparseOrbData mapping. Block order,
block lengths, and all metadata are preserved; only values_real and an
optional values_imag are replaced. The output of decompose is therefore
a transient coupled-coordinate view of the same ragged storage, not another
physical-data type. Any trailing value axes are carried independently
through the spatial transform.
Parameters:
-
basis_set(BasisSet) –Basis set defining species, shell, and orbital order.
decompose
decompose(matrix: BlockSparseOrbData, species_indices: Tensor) -> BlockSparseOrbData
Decompose physical matrix blocks into coupled coordinates.
compose
compose(
coupled_matrix: BlockSparseOrbData, species_indices: Tensor
) -> BlockSparseOrbData
Compose coupled coordinates into physical matrix blocks.
Affine transforms
Orbital vectors are transformed shell by shell. Block-sparse matrices are transformed in coupled coordinates, with shared scales within each spherical multiplet and shifts restricted to scalar components. Both directions are available for normalizing data or restoring physical scales.
OrbVectorAffineTransform
OrbVectorAffineTransform(
basis_set: BasisSet, shell_shifts: Sequence[Tensor], shell_scales: Sequence[Tensor]
)
Bases: Module
Apply a fixed invertible affine transform to real orbital vectors.
Parameters are specified once per atomic basis and shell in the canonical
species order of one BasisSet, and every scale is nonzero. Let atomic
site \(i\) belong to species \(s\).
A shell is labeled by \((n,\ell)\), where \(n\) enumerates radial shells with
the same \(\ell\) in their AtomicBasis order; \(c\) is any trailing channel
multi-index that is not transformed by spatial rotations.
For \(\ell=0\), \(x^i_{n0c}\) and \(y^i_{n0c}\) are scalars. For \(\ell>0\), \(\mathbf{x}^i_{n\ell c}\) and \(\mathbf{y}^i_{n\ell c}\) are complete real spherical vectors in the \((2\ell+1)\)-dimensional orbital representation \(V_{\ell,(-1)^\ell}\). The scale \(A^s_{n\ell c}\) and scalar-shell shift \(B^s_{n0c}\) are scalars. The forward transform is
and
Its inverse is
and
For \(g\in\mathrm{O}(3)\) and \(\ell>0\), the spherical vector transforms by the real orbital irrep matrix \(D^{(\ell,(-1)^\ell)}(g)\). Because \(A^s_{n\ell c}\) is a scalar,
For \(\ell=0\), \(D^{(0,+)}(g)=1\), so
Thus the shift is allowed only for scalar shells. The inverse replaces \(A\) by \(A^{-1}\) and \(B\) by \(-A^{-1}B\), so it obeys the same argument and is O(3)-equivariant as well.
Parameters:
-
basis_set(BasisSet) –Basis set defining the canonical model species order and orbital layouts.
-
shell_shifts(Sequence[Tensor]) –One tensor per entry of
basis_set.atomic_bases, with shape[n_shells, *extra_shape]. -
shell_scales(Sequence[Tensor]) –Nonzero scales with the same shapes as
shell_shifts.
Attributes:
-
orb_shifts(Tensor) –Shifts expanded from shells to orbital components, with shape
[sum_s n_orb(s), *extra_shape]. The first axis concatenates species inbasis_set.atomic_basesorder, then each species in shell order and the2 * ell + 1spherical components within each shell. -
orb_scales(Tensor) –Scales expanded in the same layout and with the same shape as
orb_shifts. -
orb_counts(Tensor) –Number of orbital components per atom for each model species, with shape
[num_species]and dtypetorch.long. -
species_offsets(Tensor) –Leading-zero prefix sum of
orb_counts, with shape[num_species + 1]and dtypetorch.long. Speciessoccupiesorb_shifts[species_offsets[s]:species_offsets[s + 1]], and likewise fororb_scales.
from_stats
classmethod
from_stats(basis_set: BasisSet, stats: OrbVectorStats) -> Self
Construct the transform represented by dataset statistics.
identity
classmethod
identity(basis_set: BasisSet, *, extra_shape: tuple[int, ...] = ()) -> Self
Construct an identity transform with the requested value shape.
forward
Return values * scale + shift in the model's packed order.
Parameters:
-
vector(OrbData) –Real orbital vectors in packed atom order.
-
species_indices(Tensor) –Model species index of every atom, with shape
[n_atoms]and dtypetorch.long.
inverse
Return (values - shift) / scale in the model's packed order.
Parameters:
-
vector(OrbData) –Real orbital vectors in packed atom order.
-
species_indices(Tensor) –Model species index of every atom, with shape
[n_atoms]and dtypetorch.long.
BlockSparseAffineTransform
BlockSparseAffineTransform(
basis_set: BasisSet,
onsite_shifts: Tensor,
onsite_scales: Tensor,
offsite_shifts: Tensor,
offsite_scales: Tensor,
)
Bases: Module
Apply a fixed invertible affine transform in coupled coordinates.
For each canonical onsite or offsite path \(a=(s_1,s_2,n_1\ell_1, n_2\ell_2,L)\), all \(2L+1\) components share one nonzero scale \(A_a\). Only \(L=0\) paths may have a shift \(B_a\). For coupled input \(x\) and output \(y\), the forward transform is
and its inverse is
Onsite and offsite parameters are distinct, while Hermitian reverse species and shell pairs use the same path parameters.
Both directions accept and return coupled-coordinate
BlockSparseOrbData. This module does not couple or decouple
block-sparse values and does not assign normalization semantics to either direction;
a model or experiment composes it with BlockSparseCGTransform according
to its own data flow.
Parameters:
-
basis_set(BasisSet) –Basis set defining species, shells, and orbital order.
-
onsite_shifts(Tensor) –Scalar-path shifts with shape
[n_onsite_paths, *extra_shape]; higher-\(L\) entries must be zero. -
onsite_scales(Tensor) –Nonzero onsite scales with the same shape.
-
offsite_shifts(Tensor) –Offsite shifts with shape
[n_offsite_paths, *extra_shape]; higher-\(L\) entries must be zero. -
offsite_scales(Tensor) –Nonzero offsite scales with the same shape.
from_stats
classmethod
from_stats(basis_set: BasisSet, stats: BlockSparseStats) -> Self
Construct the transform represented by dataset statistics.
identity
classmethod
identity(basis_set: BasisSet, *, extra_shape: tuple[int, ...] = ()) -> Self
Construct an identity transform with the requested value shape.
forward
forward(
coupled_matrix: BlockSparseOrbData, species_indices: Tensor
) -> BlockSparseOrbData
Return values * scale + shift in coupled coordinates.
inverse
inverse(
coupled_matrix: BlockSparseOrbData, species_indices: Tensor
) -> BlockSparseOrbData
Return (values - shift) / scale in coupled coordinates.
Bloch transform
The Torch transform is differentiable with respect to matrix values and supports samples with different orbital dimensions. NumPy transforms and generalized eigensolvers are documented under Physical calculations.
bloch_transform
bloch_transform(
matrix_r: BlockSparseOrbData,
orb_counts: Tensor,
batch_ptr: Tensor,
kpoints: Tensor,
*,
hermitian: bool,
) -> OrbData
Transform cell-shift blocks into compact dense Bloch matrices.
The transform uses fractional reciprocal coordinates and the ELFES forward phase
matrix_r follows the batched BlockSparseOrbData layout, with
batch-global atom indices. When hermitian=True, its stored blocks are the
independent rows of a Hermitian matrix and the omitted conjugate-transpose
partners are included in the result.
Each sample's full dense matrix is flattened in C order along the leading
values axis. The sample matrices remain consecutive but are not padded to a
common orbital dimension. The operation is expressed entirely in ordinary
PyTorch and is differentiable with respect to values_real and optional
values_imag.
Parameters:
-
matrix_r(BlockSparseOrbData) –Real or complex block values.
values_realand optionalvalues_imaghave shape[n_values, *extra_shape]. -
orb_counts(Tensor) –Number of orbitals on every atom in the batch, with shape
[n_atoms]. -
batch_ptr(Tensor) –Sample boundaries on the atom axis, with shape
[n_samples + 1]. -
kpoints(Tensor) –One fractional k-point with shape
[3]or multiple k-points with shape[n_kpoints, 3]. -
hermitian(bool) –Whether
matrix_rstores only independent Hermitian blocks.
Returns: