TensorKitTensors

Documentation for TensorKitTensors. This is a lightweight package that defines several commonly used tensors for TensorKit, with various symmetries.

Symmetric operators through basis transformations

Each operator module defines its operators only once, in a non-symmetric reference basis. The symmetric versions are generated automatically by rotating the reference operator with a documented unitary basis transformation and projecting the result onto the symmetric tensor structure. The basis transformations are exposed through each module's basis_transform function, and each module exports symmetrize_operator to apply the appropriate transformation and symmetry projection to an operator on its desymmetrized form. Operators that are incompatible with a given symmetry throw an ArgumentError.

Custom operators

For each operator module, one can define a custom operator in TensorMap format in the non-symmetric reference basis, and then impose the symmetries with that module's symmetrize_operator function:

using TensorKit
using TensorKitTensors.SpinOperators
V = spin_space(Trivial)
O = TensorMap([1.0 0.0; 0.0 -1.0], V ← V)
Z = symmetrize_operator(O, U1Irrep)
TensorKitTensors.symmetrizeFunction
symmetrize(O::AbstractTensorMap, U::AbstractTensorMap, V::ElementarySpace; tol=...)
symmetrize(O::AbstractTensorMap, Us::NTuple{N, AbstractTensorMap}, V::ElementarySpace; tol=...)
symmetrize(O::AbstractTensorMap, (Us, Uds)::Tuple{NTuple{M, AbstractTensorMap}, NTuple{N, AbstractTensorMap}}, V::HomSpace; tol=...)

Construct the symmetric version of an $M ← N$ operator O on the space V, given the basis transformations that map the basis of O onto the basis of V.

The operator O is first brought to its dense form (see desymmetrize), then rotated by applying the basis transformations to each of its legs, and finally projected onto the symmetric tensor structure of V. If the rotated operator is not symmetric, i.e. if it has nonzero entries (larger than tol) that are incompatible with the symmetry structure of V, an ArgumentError is thrown.

The most general form takes V::HomSpace (V_cod ← V_dom) and a pair of tuples of basis transformations (Us, Uds) for each of the spaces of V. In other words, the dense representation of the symmetrized operator is $(U_1 ⊗ ⋯ ⊗ U_M)\, O\, (Ũ_1 ⊗ ⋯ ⊗ Ũ_N)^†$.

For the common case of a square operator over a single space V::ElementarySpace, a single transformation U (applied to every leg) or an N-tuple Us (one per site, applied to both codomain and domain) suffices, and the target space V^N ← V^N is constructed automatically.

The default tol is sqrt(eps) of the scalar type of the rotated operator, floored at sqrt(eps) of the TensorKit.sectorscalartype of the symmetry, i.e. the element type of the fusion-tensor data used by the projection. Sectors with exact (integer) topological data, such as Z2Irrep, U1Irrep, FermionParity, and their products, preserve the full precision of the input, while for sectors with floating-point data (e.g. SU2Irrep, whose Clebsch-Gordan coefficients are Float64) the result of wider scalar types such as BigFloat is only accurate up to that precision.

The basis transformations of the operator modules in this package are documented and exposed through their respective basis_transform functions.

Examples

Symmetrizing the transverse-field term of the Ising model with respect to its $ℤ₂$ spin-flip symmetry, using the Hadamard transformation to map the $S^z$ basis onto the $S^x$ basis:

julia> using TensorKit, TensorKitTensors, TensorKitTensors.SpinOperators;

julia> X = S_x(); # single-site trivial operator

julia> U = basis_transform(Z2Irrep); # Hadamard transformation

julia> X_z2 = symmetrize(X, U, spin_space(Z2Irrep))
2←2 TensorMap{ComplexF64, Rep[ℤ₂], 1, 1, Vector{ComplexF64}}:
 codomain: ⊗(Rep[ℤ₂](0 => 1, 1 => 1))
 domain: ⊗(Rep[ℤ₂](0 => 1, 1 => 1))
 blocks:
 * Irrep[ℤ₂](0) => 1×1 reshape(view(::Vector{ComplexF64}, 1:1), 1, 1) with eltype ComplexF64:
 0.5 + 0.0im

 * Irrep[ℤ₂](1) => 1×1 reshape(view(::Vector{ComplexF64}, 2:2), 1, 1) with eltype ComplexF64:
 -0.5 + 0.0im
source
TensorKitTensors.desymmetrizeFunction
desymmetrize(V::VectorSpace)
desymmetrize(t::AbstractTensorMap)

Map a symmetric (graded) vector space or tensor onto its non-symmetric counterpart over ComplexSpace.

For an elementary space, this is ComplexSpace(dim(V)) with the duality of V preserved; product and hom spaces are mapped elementwise. For a tensor, the result is the TensorMap over the desymmetrized spaces holding the dense representation of t, in which the basis vectors of each space are grouped per sector, in the order of sectors(V). This is the inverse operation of symmetrize (with trivial basis transformations).

Note

For tensors with fermionic gradings, the dense representation discards the fermionic statistics: the resulting purely bosonic tensor incorporates the sign conventions of TensorKit's fusion-tensor data, and is consistent with what symmetrize expects, but permuting its indices is no longer equivalent to permuting the indices of the original tensor.

source

Adding symmetry charges

Use fuse_charge to attach symmetry charges to each site of the operator by fusing a one-dimensional auxiliary space to every local space of an operator.

For example, the following adds a uniform U(1) charge of 1 // 2 to the local spaces of a U(1)-symmetric spin-exchange operator:

using TensorKit
using TensorKitTensors
using TensorKitTensors.SpinOperators

O = S_exchange(U1Irrep)
O_shifted = fuse_charge(O, U1Irrep(1 // 2))
TensorKitTensors.fuse_chargeFunction
fuse_charge(O::AbstractTensorMap, charge::Sector)
fuse_charge(O::AbstractTensorMap{<:Any, <:Any, N, N}, charges::NTuple{N, <:Sector}) where {N}

Fuse auxiliary symmetry charges into the local spaces of a square N-site operator O. Pass a single charge to use it at every site, or an N-tuple charges to select the charge fused into each site. Each charge must be compatible with the sector type of O.

If O acts on local spaces V₁, …, Vₙ, the result acts on fuse(Vₖ ⊗ Cₖ) at site k, where Cₖ is the one-dimensional space carrying the selected charge. The transformation fuses O with the identity operator on C₁ ⊗ ⋯ ⊗ Cₙ.

source