Block-Sparse Tensor
A SubTensor
is a numpy.ndarray
with a tuple
of SZ
for quantum labels associated.
It can be initialized using a numpy.ndarray.shape
and a tuple
of SZ
.
>>> from pyblock3.algebra.core import SubTensor
>>> from pyblock3.algebra.symmetry import SZ
>>> x = SubTensor.zeros((4,3), q_labels=(SZ(0, 0, 0), SZ(1, 1, 2)))
>>> x
(Q=) (< N=0 SZ=0 PG=0 >, < N=1 SZ=1/2 PG=2 >) (R=) array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
>>> x[1,:] = 1
>>> x
(Q=) (< N=0 SZ=0 PG=0 >, < N=1 SZ=1/2 PG=2 >) (R=) array([[0., 0., 0.],
[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.]])
>>> x.q_labels
(< N=0 SZ=0 PG=0 >, < N=1 SZ=1/2 PG=2 >)
A SparseTensor
represents a block-sparse tensor, which contains a list of SubTensor
.
A quantum-number conserving SparseTensor
can be initialized using a BondInfo
, pattern
and dq
.
pattern
is a string of ‘+’ or ‘-’, indicating how to combine SZ
to get dq
.
dq
is the conserved quantum number.
For 1D SparseTensor
, the initialization method does not require quantum-number conservation.
>>> from pyblock3.algebra.core import SparseTensor
>>> from pyblock3.algebra.symmetry import SZ, BondInfo
>>> x = BondInfo({SZ(0, 0, 0): 1, SZ(1, 1, 2): 2, SZ(-1, -1, 2): 2})
>>> SparseTensor.random((x, x), pattern='++', dq=SZ(0, 0, 0))
0 (Q=) (< N=-1 SZ=-1/2 PG=2 >, < N=1 SZ=1/2 PG=2 >) (R=) array([[0.89718406, 0.85419892],
[0.65863698, 0.98023596]])
1 (Q=) (< N=0 SZ=0 PG=0 >, < N=0 SZ=0 PG=0 >) (R=) array([[0.69742141]])
2 (Q=) (< N=1 SZ=1/2 PG=2 >, < N=-1 SZ=-1/2 PG=2 >) (R=) array([[0.50722408, 0.34099007],
[0.40760832, 0.8430552 ]])
Note that the resulting tensor has three non-zero blocks, for each block, the quantum numbers adds to dq
, which is SZ(0, 0, 0)
.
So this is a quantum-number-conserving block-sparse tensor.
SparseTensor
supports most common numpy.ndarray operations:
>>> import numpy as np
>>> x = SparseTensor.random((x, x), pattern='++', dq=SZ(0, 0, 0))
>>> y = 2 * x
>>> np.linalg.norm(y)
3.386356824229238
>>> np.linalg.norm(x)
1.693178412114619
>>> np.tensordot(x, y, axes=1)
0 (Q=) (< N=-1 SZ=-1/2 PG=2 >, < N=-1 SZ=-1/2 PG=2 >) (R=) array([[0.37106833, 0.92381267],
[0.23117763, 1.27553566]])
1 (Q=) (< N=0 SZ=0 PG=0 >, < N=0 SZ=0 PG=0 >) (R=) array([[1.25199691]])
2 (Q=) (< N=1 SZ=1/2 PG=2 >, < N=1 SZ=1/2 PG=2 >) (R=) array([[0.66650452, 0.63606196],
[0.61864202, 0.98009947]])
A FermionTensor
contains two SparseTensor
, including blocks with odd dq
and even dq
, respectively.
FlatSparseTensor
is another representation of block-sparse tensor, where quantum-number are combined together to a single integer,
and floating-point contents of all blocks are merged to one single “flattened” numpy.ndarray
.
FlatSparseTensor
has the same interface as SparseTensor
, but FlatSparseTensor
provides much faster C++ implementation
for functions like tensordot and tranpose. For debugging purpose, FlatSparseTensor
also has pure python implementation,
which can be activated by setting ENABLE_FAST_IMPLS = False
in flat.py
.