diff --git a/src/tjoperators.jl b/src/tjoperators.jl index 16166e6..a55abdd 100644 --- a/src/tjoperators.jl +++ b/src/tjoperators.jl @@ -48,7 +48,8 @@ function tj_space(::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) end end function tj_space(::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) - return error("Not implemented") + return slave_fermion ? Vect[FermionParity ⊠ SU2Irrep]((1, 0) => 1, (0, 1 // 2) => 1) : + Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 1, (1, 1 // 2) => 1) end function tj_space(::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) return if slave_fermion @@ -67,7 +68,11 @@ function tj_space(::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) end end function tj_space(::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) - return error("Not implemented") + return if slave_fermion + Vect[FermionParity ⊠ U1Irrep ⊠ SU2Irrep]((1, 0, 0) => 1, (0, 1, 1 // 2) => 1) + else + Vect[FermionParity ⊠ U1Irrep ⊠ SU2Irrep]((0, 0, 0) => 1, (1, 1, 1 // 2) => 1) + end end # Single-site operators @@ -181,6 +186,26 @@ function c_num(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Secto return u_num(T, particle_symmetry, spin_symmetry; slave_fermion) + d_num(T, particle_symmetry, spin_symmetry; slave_fermion) end +function c_num(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, SU2Irrep; slave_fermion) + I = sectortype(t) + if slave_fermion + block(t, I(0, 1 // 2))[1, 1] = 1 + else + block(t, I(1, 1 // 2))[1, 1] = 1 + end + return t +end +function c_num(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, SU2Irrep; slave_fermion) + I = sectortype(t) + if slave_fermion + block(t, I(0, 1, 1 // 2))[1, 1] = 1 + else + block(t, I(1, 1, 1 // 2))[1, 1] = 1 + end + return t +end const n = c_num @doc """ @@ -364,7 +389,7 @@ function u_plus_u_min(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=f return t end function u_plus_u_min(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) - return error("Not implemented") + throw(ArgumentError("`u_plus_u_min` is not symmetric under `SU2Irrep` spin symmetry")) end function u_plus_u_min(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) @@ -381,7 +406,7 @@ function u_plus_u_min(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=f return t end function u_plus_u_min(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) - return error("Not implemented") + throw(ArgumentError("`u_plus_u_min` is not symmetric under `SU2Irrep` spin symmetry")) end const u⁺u⁻ = u_plus_u_min @@ -409,7 +434,7 @@ function d_plus_d_min(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=f return t end function d_plus_d_min(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) - return error("Not implemented") + throw(ArgumentError("`d_plus_d_min` is not symmetric under `SU2Irrep` spin symmetry")) end function d_plus_d_min(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) @@ -426,7 +451,7 @@ function d_plus_d_min(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=f return t end function d_plus_d_min(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) - return error("Not implemented") + throw(ArgumentError("`d_plus_d_min` is not symmetric under `SU2Irrep` spin symmetry")) end const d⁺d⁻ = d_plus_d_min @@ -490,6 +515,12 @@ end function u_min_d_min(T, ::Type{U1Irrep}, ::Type{<:Sector}; slave_fermion::Bool=false) throw(ArgumentError("`u_min_d_min` is not symmetric under `U1Irrep` particle symmetry")) end +function u_min_d_min(T, ::Type{<:Sector}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + throw(ArgumentError("`u_min_d_min` is not symmetric under `SU2Irrep` spin symmetry")) +end +function u_min_d_min(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + throw(ArgumentError("`u_min_d_min` is not symmetric under `U1Irrep` particle symmetry or under `SU2Irrep` spin symmetry")) +end const u⁻d⁻ = u_min_d_min @doc """ @@ -518,6 +549,12 @@ end function d_min_u_min(T, ::Type{U1Irrep}, ::Type{<:Sector}; slave_fermion::Bool=false) throw(ArgumentError("`d_min_u_min` is not symmetric under `U1Irrep` particle symmetry")) end +function d_min_u_min(T, ::Type{<:Sector}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + throw(ArgumentError("`d_min_u_min` is not symmetric under `SU2Irrep` spin symmetry")) +end +function d_min_u_min(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + throw(ArgumentError("`d_min_u_min` is not symmetric under `U1Irrep` particle symmetry or under `SU2Irrep` particle symmetry")) +end const d⁻u⁻ = d_min_u_min @doc """ @@ -534,6 +571,35 @@ function c_plus_c_min(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{ return u_plus_u_min(T, particle_symmetry, spin_symmetry; slave_fermion) + d_plus_d_min(T, particle_symmetry, spin_symmetry; slave_fermion) end +function c_plus_c_min(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, SU2Irrep; slave_fermion) + I = sectortype(t) + if slave_fermion + f1 = only(fusiontrees((I(1, 0), I(0, 1 // 2)), I(1, 1 // 2))) + f2 = only(fusiontrees((I(0, 1 // 2), I(1, 0)), I(1, 1 // 2))) + t[f1, f2][1, 1, 1, 1] = 1 + else + f1 = only(fusiontrees((I(0, 0), I(1, 1 // 2)), I(1, 1 // 2))) + f2 = only(fusiontrees((I(1, 1 // 2), I(0, 0)), I(1, 1 // 2))) + t[f1, f2][1, 1, 1, 1] = 1 + end + return t +end +function c_plus_c_min(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, SU2Irrep; slave_fermion) + I = sectortype(t) + if slave_fermion + f1 = only(fusiontrees((I(1, 0, 0), I(0, 1, 1 // 2)), I(1, 1, 1 // 2))) + f2 = only(fusiontrees((I(0, 1, 1 // 2), I(1, 0, 0)), I(1, 1, 1 // 2))) + t[f1, f2][1, 1, 1, 1] = 1 + else + f1 = only(fusiontrees((I(0, 0, 0), I(1, 1, 1 // 2)), I(1, 1, 1 // 2))) + f2 = only(fusiontrees((I(1, 1, 1 // 2), I(0, 0, 0)), I(1, 1, 1 // 2))) + t[f1, f2][1, 1, 1, 1] = 1 + end + return t +end + const c⁺c⁻ = c_plus_c_min @doc """ @@ -635,5 +701,27 @@ function S_exchange(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<: S_minplus(T, particle_symmetry, spin_symmetry; slave_fermion)) + Sz ⊗ Sz end +function S_exchange(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, SU2Irrep; slave_fermion) + + for (s, f) in fusiontrees(t) + l3 = f.uncoupled[1][2].j + l4 = f.uncoupled[2][2].j + k = f.coupled[2].j + t[s, f] .= (k * (k + 1) - l3 * (l3 + 1) - l4 * (l4 + 1)) / 2 + end + return t +end +function S_exchange(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, SU2Irrep; slave_fermion) + + for (s, f) in fusiontrees(t) + l3 = f.uncoupled[1][3].j + l4 = f.uncoupled[2][3].j + k = f.coupled[3].j + t[s, f] .= (k * (k + 1) - l3 * (l3 + 1) - l4 * (l4 + 1)) / 2 + end + return t +end end diff --git a/test/tjoperators.jl b/test/tjoperators.jl index 88c9bd4..32e8c97 100644 --- a/test/tjoperators.jl +++ b/test/tjoperators.jl @@ -6,27 +6,30 @@ using .TensorKitTensorsTestSetup using TensorKitTensors.TJOperators using StableRNGs -implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep), - (U1Irrep, Trivial), (U1Irrep, U1Irrep)] +implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep), (Trivial, SU2Irrep), + (U1Irrep, Trivial), (U1Irrep, U1Irrep), (U1Irrep, SU2Irrep)] @testset "Compare symmetric with trivial tensors" begin for particle_symmetry in [Trivial, U1Irrep], spin_symmetry in [Trivial, U1Irrep, SU2Irrep] - if (particle_symmetry, spin_symmetry) in implemented_symmetries - space = tj_space(particle_symmetry, spin_symmetry) + for slave_fermion in (false, true) + if (particle_symmetry, spin_symmetry) in implemented_symmetries + space = tj_space(particle_symmetry, spin_symmetry; slave_fermion) - O = c_plus_c_min(ComplexF64, particle_symmetry, spin_symmetry) - O_triv = c_plus_c_min(ComplexF64, Trivial, Trivial) - test_operator(O, O_triv) + O = c_plus_c_min(ComplexF64, particle_symmetry, spin_symmetry; + slave_fermion) + O_triv = c_plus_c_min(ComplexF64, Trivial, Trivial; slave_fermion) + test_operator(O, O_triv) - O = c_num(ComplexF64, particle_symmetry, spin_symmetry) - O_triv = c_num(ComplexF64, Trivial, Trivial) - test_operator(O, O_triv) + O = c_num(ComplexF64, particle_symmetry, spin_symmetry; slave_fermion) + O_triv = c_num(ComplexF64, Trivial, Trivial; slave_fermion) + test_operator(O, O_triv) - else - @test_broken c_plus_c_min(ComplexF64, particle_symmetry, spin_symmetry) - @test_broken c_num(ComplexF64, particle_symmetry, spin_symmetry) + else + @test_broken c_plus_c_min(ComplexF64, particle_symmetry, spin_symmetry) + @test_broken c_num(ComplexF64, particle_symmetry, spin_symmetry) + end end end end @@ -74,17 +77,22 @@ end c_num_hole(particle_symmetry, spin_symmetry; slave_fermion) + c_num(particle_symmetry, spin_symmetry; slave_fermion) else - @test_broken c_num(particle_symmetry, spin_symmetry; slave_fermion) @test_broken u_num(particle_symmetry, spin_symmetry; slave_fermion) @test_broken d_num(particle_symmetry, spin_symmetry; slave_fermion) end # test spin operator - if particle_symmetry == Trivial + if particle_symmetry == Trivial && spin_symmetry !== SU2Irrep @test c_singlet(particle_symmetry, spin_symmetry; slave_fermion) ≈ (u_min_d_min(particle_symmetry, spin_symmetry; slave_fermion) - d_min_u_min(particle_symmetry, spin_symmetry; slave_fermion)) / sqrt(2) + else + @test_broken c_singlet(particle_symmetry, spin_symmetry; slave_fermion) + @test_broken u_min_d_min(particle_symmetry, spin_symmetry; + slave_fermion) + @test_broken d_min_u_min(particle_symmetry, spin_symmetry; + slave_fermion) end if spin_symmetry == Trivial