Symmetric tensors
ITensorBase supports tensors that are symmetric under group actions by wrapping ITensors around GradedArrays.jl. To get started, build Index objects out of sector => multiplicity pairs and pass them to the standard Julia array constructors (randn, zeros, and so on):
using ITensorBase: Index, inds
using GradedArrays: U1, dual, isdual
i = Index([U1(0) => 1, U1(1) => 2])
j = Index([U1(0) => 2, U1(1) => 1])
k = Index([U1(0) => 1, U1(1) => 1])
a = randn(i, dual(j))Index(length=3|id=7ae1e3de)×dual(Index(length=3|id=e92b5516)) ITensor:
3×3 GradedArray (codomain 2, domain 0):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Codomain Dim 2: dual(gradedrange([U1(0) => 2, U1(1) => 1]))
3×1 GradedArrays.FusedGradedMatrix{Float64, GradedArrays.U1, Vector{Float64}, …} with 1 stored block at sectors [U1(0)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 4, U1(1) => 4, U1(-1) => 1])
Domain Dim 1: fusedgradedrange([U1(0) => 1])
-0.23957395341496163
-0.7193960587329553
0.8314341169644748
1.2742740772431795
────────────────────
⋅
⋅
⋅
⋅
────────────────────
⋅ A GradedArray only stores the symmetry-allowed blocks.
These tensors support contraction, multiplication by a scalar, and addition.
b = randn(j, dual(k))
a * bIndex(length=3|id=7ae1e3de)×dual(Index(length=2|id=e26623ab)) ITensor:
3×2 GradedArray (codomain 1, domain 1):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Domain Dim 1: gradedrange([U1(0) => 1, U1(1) => 1])
2×2 GradedArrays.FusedGradedMatrix{Float64, GradedArrays.U1, Vector{Float64}, …} with 2 stored blocks at sectors [U1(0), U1(1)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 1, U1(1) => 2])
Domain Dim 1: fusedgradedrange([U1(0) => 1, U1(1) => 1])
-0.353898092541488 │ ⋅
────────────────────┼─────────────────────
⋅ │ -0.8668460616546894
⋅ │ -1.32854719669160582 * aIndex(length=3|id=7ae1e3de)×dual(Index(length=3|id=e92b5516)) ITensor:
3×3 GradedArray (codomain 2, domain 0):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Codomain Dim 2: dual(gradedrange([U1(0) => 2, U1(1) => 1]))
3×1 GradedArrays.FusedGradedMatrix{Float64, GradedArrays.U1, Vector{Float64}, …} with 1 stored block at sectors [U1(0)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 4, U1(1) => 4, U1(-1) => 1])
Domain Dim 1: fusedgradedrange([U1(0) => 1])
-0.47914790682992325
-1.4387921174659106
1.6628682339289496
2.548548154486359
────────────────────
⋅
⋅
⋅
⋅
────────────────────
⋅ c = randn(i, dual(j))
a + cIndex(length=3|id=7ae1e3de)×dual(Index(length=3|id=e92b5516)) ITensor:
3×3 GradedArray (codomain 2, domain 0):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Codomain Dim 2: dual(gradedrange([U1(0) => 2, U1(1) => 1]))
3×1 GradedArrays.FusedGradedMatrix{Float64, GradedArrays.U1, Vector{Float64}, …} with 1 stored block at sectors [U1(0)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 4, U1(1) => 4, U1(-1) => 1])
Domain Dim 1: fusedgradedrange([U1(0) => 1])
1.1475873462224402
-0.2003120792473716
0.16064442691880187
-1.5624122473865811
────────────────────
⋅
⋅
⋅
⋅
────────────────────
⋅ Duality
dual flips the duality of an index, and isdual returns whether an index is dual. Indices can only contract with ones that have opposite duality, for example the j Index of b contracts with the dual(j) Index of a.
isdual.(inds(a))2-element BitVector:
0
1Note that indices of a GradedArray are partitioned into a codomain and a domain, and the GradedArray stores the block diagonal matrix corresponding to the bipartitioning of the indices. When printing, by convention domain indices are implicitly dual (the format and conventions are compatible with those from TensorKit.jl). For more information see the documentation on graded arrays.
Available symmetries
Some standard symmetries are available such as Z2, fU1 (fermionic U(1)), and SU2. See symmetry sectors for the complete list and more details.
You can use named sectors to conserve a product of symmetries.
Index([(; charge = U1(0), spin = U1(1)) => 1, (; charge = U1(1), spin = U1(0)) => 2])Index([(charge = U1(0), spin = U1(1)) => 1, (charge = U1(1), spin = U1(0)) => 2]|id=9e0d4983)