ariadnetor_tensor/block_sparse/mod.rs
1//! Block-sparse tensor storage for abelian symmetries.
2//!
3//! Provides [`BlockSparseTensorData<T, S>`] — the joined storage +
4//! layout bundle for tensors whose blocks are constrained by an
5//! abelian conservation law (flux). Only blocks satisfying the
6//! conservation law are allocated; the packed flat buffer lives on
7//! [`BlockSparseStorage<T>`] and the per-leg sector indices /
8//! allowed-block metadata live on [`BlockSparseLayout<S>`].
9//!
10//! # Key types
11//!
12//! - [`Direction`] — leg direction (Out/In) for flux computation
13//! - [`QNIndex<S>`] — quantum-number index mapping sectors to block dimensions
14//! - [`BlockCoord`] — N-dimensional block coordinate
15//! - [`BlockMeta`] — per-block metadata (coordinate, offset, size)
16//! - [`BlockSparseStorage<T>`] / [`BlockSparseLayout<S>`] /
17//! [`BlockSparseTensorData<T, S>`] — the storage / layout / joined
18//! bundle
19
20use crate::sector::Sector;
21
22mod layout;
23mod qn_index;
24mod storage;
25mod tensor_data;
26
27pub use layout::BlockSparseLayout;
28pub use qn_index::QNIndex;
29pub use storage::BlockSparseStorage;
30pub use tensor_data::BlockSparseTensorData;
31
32// ---------------------------------------------------------------------------
33// Direction
34// ---------------------------------------------------------------------------
35
36/// Leg direction for flux computation (see each variant).
37#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
38pub enum Direction {
39 /// Ket / row index: the sector contributes as-is to the flux.
40 Out,
41 /// Bra / column index: the sector contributes via `dual()` to the flux.
42 In,
43}
44
45impl Direction {
46 /// Apply direction to a sector: identity for `Out`, `dual()` for `In`.
47 pub fn apply<S: Sector>(&self, sector: &S) -> S {
48 match self {
49 Direction::Out => sector.clone(),
50 Direction::In => sector.dual(),
51 }
52 }
53}
54
55// ---------------------------------------------------------------------------
56// BlockCoord
57// ---------------------------------------------------------------------------
58
59/// N-dimensional block coordinate.
60///
61/// Each element is an index into the corresponding `QNIndex.blocks`.
62/// `Ord` is derived (lexicographic) to define a deterministic sort order
63/// for `Vec<BlockMeta>`.
64#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
65pub struct BlockCoord(pub Vec<usize>);
66
67// ---------------------------------------------------------------------------
68// BlockMeta
69// ---------------------------------------------------------------------------
70
71/// Metadata for a single block within a block-sparse tensor.
72#[derive(Clone, Debug)]
73pub struct BlockMeta {
74 /// Block coordinate (index into each leg's QNIndex).
75 pub coord: BlockCoord,
76 /// Element offset into the flat data buffer.
77 pub offset: usize,
78 /// Number of elements in this block.
79 pub size: usize,
80}
81
82#[cfg(test)]
83mod tests;