From 87f05a42a58990612d1fd32ef9dae4078cdc222d Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sat, 30 Nov 2024 11:24:20 +0800 Subject: [PATCH 01/14] change formatting to "blue" --- .JuliaFormatter.toml | 2 +- .gitignore | 2 + docs/make.jl | 25 ++-- src/lattices/lattices.jl | 5 +- src/lattices/squarelattice.jl | 60 +++++---- src/models/hamiltonians.jl | 212 ++++++++++++++++++------------ src/models/quantum_chemistry.jl | 207 +++++++++++++++-------------- src/models/transfermatrices.jl | 34 +++-- src/operators/bosonoperators.jl | 20 +-- src/operators/hubbardoperators.jl | 69 +++++----- src/operators/localoperators.jl | 48 ++++--- src/operators/mpoham.jl | 14 +- src/operators/spinoperators.jl | 71 +++++----- test/bosonoperators.jl | 6 +- test/heisenberg.jl | 19 +-- test/hubbardoperators.jl | 37 +++--- test/potts.jl | 10 +- test/sixvertex.jl | 12 +- test/spinoperators.jl | 37 +++--- 19 files changed, 504 insertions(+), 386 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 9613e05..c743950 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -1 +1 @@ -style = "yas" \ No newline at end of file +style = "blue" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 06ba5eb..deec166 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ docs/build Manifest.toml +.vscode/ +.DS_Store diff --git a/docs/make.jl b/docs/make.jl index 1f9a253..c3c789e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,17 +2,18 @@ using Documenter using MPSKitModels makedocs(; - modules=[MPSKitModels], - sitename="MPSKitModels.jl", - authors="Maarten Vandamme", - format=Documenter.HTML(; - prettyurls=get(ENV, "CI", nothing) == "true", - mathengine=MathJax()), - pages=["Home" => "index.md", - "Manual" => ["man/operators.md", - "man/mpoham.md", - "man/lattices.md", - "man/models.md"], - "Index" => "package_index.md"]) + modules=[MPSKitModels], + sitename="MPSKitModels.jl", + authors="Maarten Vandamme", + format=Documenter.HTML(; + prettyurls=get(ENV, "CI", nothing) == "true", mathengine=MathJax() + ), + pages=[ + "Home" => "index.md", + "Manual" => + ["man/operators.md", "man/mpoham.md", "man/lattices.md", "man/models.md"], + "Index" => "package_index.md", + ], +) deploydocs(; repo="github.com/QuantumKitHub/MPSKitModels.jl.git") diff --git a/src/lattices/lattices.jl b/src/lattices/lattices.jl index fa69c8b..84a5694 100644 --- a/src/lattices/lattices.jl +++ b/src/lattices/lattices.jl @@ -48,7 +48,8 @@ function Base.checkbounds(L::AbstractLattice{N}, inds::Vararg{Int,N}) where {N} return checkbounds(Bool, L, inds...) || throw(BoundsError(L, inds)) end -function Base.checkbounds(::Type{Bool}, L::AbstractLattice{N}, - inds::Vararg{Int,N}) where {N} +function Base.checkbounds( + ::Type{Bool}, L::AbstractLattice{N}, inds::Vararg{Int,N} +) where {N} return Base.checkbounds_indices(Bool, axes(L), inds) end diff --git a/src/lattices/squarelattice.jl b/src/lattices/squarelattice.jl index 52a85ae..fbdf036 100644 --- a/src/lattices/squarelattice.jl +++ b/src/lattices/squarelattice.jl @@ -139,8 +139,9 @@ function linearize_index(helix::InfiniteHelix, i::Int, j::Int) end function vertices(lattice::Union{FiniteStrip,InfiniteStrip,FiniteCylinder,InfiniteCylinder}) - return (LatticePoint((i, j), lattice) for i in 1:(lattice.L), - j in 1:(lattice.N ÷ lattice.L)) + return ( + LatticePoint((i, j), lattice) for i in 1:(lattice.L), j in 1:(lattice.N ÷ lattice.L) + ) end function vertices(lattice::Union{FiniteHelix,InfiniteHelix}) return (LatticePoint((i, 1), lattice) for i in 1:(lattice.N)) @@ -149,28 +150,40 @@ end function nearest_neighbours(lattice::FiniteStrip) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) - for i in 1:rows, j in 1:(cols - 1)) - vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) - for i in 1:(rows - 1), j in 1:cols) + horizontal = ( + LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in 1:rows, + j in 1:(cols - 1) + ) + vertical = ( + LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for + i in 1:(rows - 1), j in 1:cols + ) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::FiniteCylinder) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) - for i in 1:rows, j in 1:(cols - 1)) - vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) - for i in 1:rows, j in 1:cols) + horizontal = ( + LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in 1:rows, + j in 1:(cols - 1) + ) + vertical = ( + LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for i in 1:rows, + j in 1:cols + ) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::FiniteHelix) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) - for i in 1:rows, j in 1:(cols - 1)) - vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) - for i in 1:rows, j in 1:cols if (i != rows && j != cols)) + horizontal = ( + LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in 1:rows, + j in 1:(cols - 1) + ) + vertical = ( + LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for + i in 1:rows, j in 1:cols if (i != rows && j != cols) + ) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::Union{InfiniteStrip,InfiniteCylinder,InfiniteHelix}) @@ -179,22 +192,23 @@ function nearest_neighbours(lattice::Union{InfiniteStrip,InfiniteCylinder,Infini for v in V push!(neighbours, v => v + (0, 1)) if v.coordinates[1] < lattice.L || - lattice isa InfiniteCylinder || - lattice isa InfiniteHelix + lattice isa InfiniteCylinder || + lattice isa InfiniteHelix push!(neighbours, v => v + (1, 0)) end end return neighbours end -function next_nearest_neighbours(lattice::Union{InfiniteStrip,InfiniteCylinder, - InfiniteHelix}) +function next_nearest_neighbours( + lattice::Union{InfiniteStrip,InfiniteCylinder,InfiniteHelix} +) V = vertices(lattice) neighbours = Pair{eltype(V),eltype(V)}[] for v in V if v.coordinates[1] < lattice.L || - lattice isa InfiniteCylinder || - lattice isa InfiniteHelix + lattice isa InfiniteCylinder || + lattice isa InfiniteHelix push!(neighbours, v => v + (1, 1)) end if v.coordinates[1] > 1 || lattice isa InfiniteCylinder || lattice isa InfiniteHelix @@ -206,8 +220,10 @@ end LinearAlgebra.norm(p::LatticePoint{2,InfiniteStrip}) = LinearAlgebra.norm(p.coordinates) function LinearAlgebra.norm(p::LatticePoint{2,InfiniteCylinder}) - return min(sqrt(mod(p.coordinates[1], p.lattice.L)^2 + p.coordinates[2]^2), - sqrt(mod(-p.coordinates[1], p.lattice.L)^2 + p.coordinates[2]^2)) + return min( + sqrt(mod(p.coordinates[1], p.lattice.L)^2 + p.coordinates[2]^2), + sqrt(mod(-p.coordinates[1], p.lattice.L)^2 + p.coordinates[2]^2), + ) end function LinearAlgebra.norm(p::LatticePoint{2,InfiniteHelix}) x₁ = mod(p.coordinates[1], p.lattice.L) diff --git a/src/models/hamiltonians.jl b/src/models/hamiltonians.jl index c500588..c132bd6 100644 --- a/src/models/hamiltonians.jl +++ b/src/models/hamiltonians.jl @@ -22,24 +22,28 @@ function transverse_field_ising end function transverse_field_ising(lattice::AbstractLattice; kwargs...) return transverse_field_ising(ComplexF64, Trivial, lattice; kwargs...) end -function transverse_field_ising(S::Type{<:Sector}, - lattice::AbstractLattice=InfiniteChain(1); - kwargs...) +function transverse_field_ising( + S::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... +) return transverse_field_ising(ComplexF64, S, lattice; kwargs...) end function transverse_field_ising(T::Type{<:Number}, lattice::AbstractLattice; kwargs...) return transverse_field_ising(T, Trivial, lattice; kwargs...) end -function transverse_field_ising(T::Type{<:Number}, - S::Type{<:Sector}, - lattice::AbstractLattice; - kwargs...) - throw(ArgumentError("`symmetry` must be either `Trivial`, `Z2Irrep` or `FermionParity`")) -end -function transverse_field_ising(T::Type{<:Number}=ComplexF64, - S::Union{Type{Trivial},Type{Z2Irrep}}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - J=1.0, g=1.0) +function transverse_field_ising( + T::Type{<:Number}, S::Type{<:Sector}, lattice::AbstractLattice; kwargs... +) + throw( + ArgumentError("`symmetry` must be either `Trivial`, `Z2Irrep` or `FermionParity`") + ) +end +function transverse_field_ising( + T::Type{<:Number}=ComplexF64, + S::Union{Type{Trivial},Type{Z2Irrep}}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + J=1.0, + g=1.0, +) ZZ = rmul!(σᶻᶻ(T, S), -J) X = rmul!(σˣ(T, S), g * -J) return @mpoham begin @@ -50,9 +54,9 @@ function transverse_field_ising(T::Type{<:Number}=ComplexF64, end end end -function transverse_field_ising(T::Type{<:Number}, ::Type{fℤ₂}, - lattice::AbstractLattice=InfiniteChain(1); - J=1.0, g=1.0) +function transverse_field_ising( + T::Type{<:Number}, ::Type{fℤ₂}, lattice::AbstractLattice=InfiniteChain(1); J=1.0, g=1.0 +) twosite = axpby!(-J, c_plusmin(T) + c_minplus(T), J, c_plusplus(T) + c_minmin(T)) onesite = axpby!(2g * J, c_number(T), -g * J, id(Matrix{T}, space(twosite, 1))) @@ -84,9 +88,13 @@ function kitaev_model end function kitaev_model(lattice::AbstractLattice; kwargs...) return kitaev_model(ComplexF64, lattice; kwargs...) end -function kitaev_model(elt::Type{<:Number}=ComplexF64, - lattice::AbstractLattice=InfiniteChain(1); - t=1.0, mu=1.0, Delta=1.0) +function kitaev_model( + elt::Type{<:Number}=ComplexF64, + lattice::AbstractLattice=InfiniteChain(1); + t=1.0, + mu=1.0, + Delta=1.0, +) TB = rmul!(c_plusmin(elt) + c_minplus(elt), -t / 2) # tight-binding term SC = rmul!(c_plusplus(elt) + c_minmin(elt), Delta / 2) # superconducting term CP = rmul!(c_number(elt), -mu) # chemical potential term @@ -122,17 +130,21 @@ function heisenberg_XXX end function heisenberg_XXX(lattice::AbstractLattice; kwargs...) return heisenberg_XXX(ComplexF64, Trivial, lattice; kwargs...) end -function heisenberg_XXX(symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); - kwargs...) +function heisenberg_XXX( + symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... +) return heisenberg_XXX(ComplexF64, symmetry, lattice; kwargs...) end function heisenberg_XXX(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) return heisenberg_XXX(elt, Trivial, lattice; kwargs...) end -function heisenberg_XXX(T::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - J::Real=1.0, spin::Real=1) +function heisenberg_XXX( + T::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + J::Real=1.0, + spin::Real=1, +) term = rmul!(S_exchange(T, symmetry; spin=spin), J) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return term{i,j} @@ -154,20 +166,26 @@ function heisenberg_XXZ end function heisenberg_XXZ(lattice::AbstractLattice; kwargs...) return heisenberg_XXZ(ComplexF64, Trivial, lattice; kwargs...) end -function heisenberg_XXZ(symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); - kwargs...) +function heisenberg_XXZ( + symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... +) return heisenberg_XXZ(ComplexF64, symmetry, lattice; kwargs...) end function heisenberg_XXZ(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) return heisenberg_XXZ(elt, Trivial, lattice; kwargs...) end -function heisenberg_XXZ(elt::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - J=1.0, Delta=1.0, spin=1) - term = rmul!(S_xx(elt, symmetry; spin=spin), J) + - rmul!(S_yy(elt, symmetry; spin=spin), J) + - rmul!(S_zz(elt, symmetry; spin=spin), Delta * J) +function heisenberg_XXZ( + elt::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + J=1.0, + Delta=1.0, + spin=1, +) + term = + rmul!(S_xx(elt, symmetry; spin=spin), J) + + rmul!(S_yy(elt, symmetry; spin=spin), J) + + rmul!(S_zz(elt, symmetry; spin=spin), Delta * J) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return term{i,j} end @@ -188,12 +206,18 @@ function heisenberg_XYZ end function heisenberg_XYZ(lattice::AbstractLattice; kwargs...) return heisenberg_XYZ(ComplexF64, lattice; kwargs...) end -function heisenberg_XYZ(T::Type{<:Number}=ComplexF64, - lattice::AbstractLattice=InfiniteChain(1); - Jx=1.0, Jy=1.0, Jz=1.0, spin=1) - term = rmul!(S_xx(T, Trivial; spin=spin), Jx) + - rmul!(S_yy(T, Trivial; spin=spin), Jy) + - rmul!(S_zz(T, Trivial; spin=spin), Jz) +function heisenberg_XYZ( + T::Type{<:Number}=ComplexF64, + lattice::AbstractLattice=InfiniteChain(1); + Jx=1.0, + Jy=1.0, + Jz=1.0, + spin=1, +) + term = + rmul!(S_xx(T, Trivial; spin=spin), Jx) + + rmul!(S_yy(T, Trivial; spin=spin), Jy) + + rmul!(S_zz(T, Trivial; spin=spin), Jz) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return term{i,j} end @@ -215,18 +239,24 @@ function bilinear_biquadratic_model end function bilinear_biquadratic_model(lattice::AbstractLattice; kwargs...) return bilinear_biquadratic_model(ComplexF64, Trivial, lattice; kwargs...) end -function bilinear_biquadratic_model(symmetry::Type{<:Sector}, - lattice::AbstractLattice=InfiniteChain(1); kwargs...) +function bilinear_biquadratic_model( + symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... +) return bilinear_biquadratic_model(ComplexF64, symmetry, lattice; kwargs...) end -function bilinear_biquadratic_model(elt::Type{<:Number}, lattice::AbstractLattice; - kwargs...) +function bilinear_biquadratic_model( + elt::Type{<:Number}, lattice::AbstractLattice; kwargs... +) return bilinear_biquadratic_model(elt, Trivial, lattice; kwargs...) end -function bilinear_biquadratic_model(elt::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - spin=1, J=1.0, θ=0.0) +function bilinear_biquadratic_model( + elt::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + spin=1, + J=1.0, + θ=0.0, +) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return J * cos(θ) * S_exchange(elt, symmetry; spin=spin){i,j} + J * sin(θ) * (S_exchange(elt, symmetry; spin=spin)^2){i,j} @@ -252,23 +282,29 @@ function quantum_potts end function quantum_potts(lattice::AbstractLattice; kwargs...) return quantum_potts(ComplexF64, Trivial, lattice; kwargs...) end -function quantum_potts(symmetry::Type{<:Sector}, - lattice::AbstractLattice=InfiniteChain(1); kwargs...) +function quantum_potts( + symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... +) return quantum_potts(ComplexF64, symmetry, lattice; kwargs...) end -function quantum_potts(elt::Type{<:Number}, lattice::AbstractLattice; - kwargs...) +function quantum_potts(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) return quantum_potts(elt, Trivial, lattice; kwargs...) end -function quantum_potts(elt::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - q=3, J=1.0, g=1.0) - return @mpoham sum(sum(nearest_neighbours(lattice)) do (i, j) - return -J * (potts_ZZ(elt, symmetry; q)^k){i,j} - end - sum(vertices(lattice)) do i - return g * (potts_field(elt, symmetry; q)^k){i} - end for k in 1:(q - 1)) +function quantum_potts( + elt::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + q=3, + J=1.0, + g=1.0, +) + return @mpoham sum( + sum(nearest_neighbours(lattice)) do (i, j) + return -J * (potts_ZZ(elt, symmetry; q)^k){i,j} + end - sum(vertices(lattice)) do i + return g * (potts_field(elt, symmetry; q)^k){i} + end for k in 1:(q - 1) + ) end #=========================================================================================== @@ -293,27 +329,33 @@ function hubbard_model end function hubbard_model(lattice::AbstractLattice; kwargs...) return hubbard_model(ComplexF64, Trivial, Trivial, lattice; kwargs...) end -function hubbard_model(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - kwargs...) +function hubbard_model( + particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; kwargs... +) return hubbard_model(ComplexF64, particle_symmetry, spin_symmetry; kwargs...) end function hubbard_model(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) return hubbard_model(elt, Trivial, Trivial, lattice; kwargs...) end -function hubbard_model(T::Type{<:Number}=ComplexF64, - particle_symmetry::Type{<:Sector}=Trivial, - spin_symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - t=1.0, U=1.0, mu=0.0, n::Integer=0) - hopping = e⁺e⁻(T, particle_symmetry, spin_symmetry) + - e⁻e⁺(T, particle_symmetry, spin_symmetry) +function hubbard_model( + T::Type{<:Number}=ComplexF64, + particle_symmetry::Type{<:Sector}=Trivial, + spin_symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + t=1.0, + U=1.0, + mu=0.0, + n::Integer=0, +) + hopping = + e⁺e⁻(T, particle_symmetry, spin_symmetry) + + e⁻e⁺(T, particle_symmetry, spin_symmetry) interaction_term = nꜛnꜜ(T, particle_symmetry, spin_symmetry) N = e_number(T, particle_symmetry, spin_symmetry) return @mpoham begin sum(nearest_neighbours(lattice)) do (i, j) return -t * hopping{i,j} - end + - sum(vertices(lattice)) do i + end + sum(vertices(lattice)) do i return U * interaction_term{i} - mu * N{i} end end @@ -336,24 +378,30 @@ function bose_hubbard_model end function bose_hubbard_model(lattice::AbstractLattice; kwargs...) return bose_hubbard_model(ComplexF64, Trivial, lattice; kwargs...) end -function bose_hubbard_model(symmetry::Type{<:Sector}, - lattice::AbstractLattice=InfiniteChain(1); kwargs...) +function bose_hubbard_model( + symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... +) return bose_hubbard_model(ComplexF64, symmetry, lattice; kwargs...) end -function bose_hubbard_model(elt::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - cutoff::Integer=5, t=1.0, U=1.0, mu=0.0, n::Integer=0) - hopping_term = a_plusmin(elt, symmetry; cutoff=cutoff) + - a_minplus(elt, symmetry; cutoff=cutoff) +function bose_hubbard_model( + elt::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + cutoff::Integer=5, + t=1.0, + U=1.0, + mu=0.0, + n::Integer=0, +) + hopping_term = + a_plusmin(elt, symmetry; cutoff=cutoff) + a_minplus(elt, symmetry; cutoff=cutoff) N = a_number(elt, symmetry; cutoff=cutoff) interaction_term = contract_onesite(N, N - id(domain(N))) H = @mpoham begin sum(nearest_neighbours(lattice)) do (i, j) return -t * hopping_term{i,j} - end + - sum(vertices(lattice)) do i + end + sum(vertices(lattice)) do i return U / 2 * interaction_term{i} - mu * N{i} end end diff --git a/src/models/quantum_chemistry.jl b/src/models/quantum_chemistry.jl index 4291b02..468c8e3 100644 --- a/src/models/quantum_chemistry.jl +++ b/src/models/quantum_chemistry.jl @@ -38,22 +38,27 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) half_basis_size = Int(ceil(basis_size / 2)) # the phsyical space - psp = Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((0, 0, 0) => 1, - (1, 1 // 2, 1) => 1, - (2, 0, 0) => 1) - - ap = TensorMap(ones, Elt, - psp * - Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1 // 2, 1) => 1), - psp) + psp = Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]( + (0, 0, 0) => 1, (1, 1//2, 1) => 1, (2, 0, 0) => 1 + ) + + ap = TensorMap( + ones, + Elt, + psp * Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1//2, 1) => 1), + psp, + ) blocks(ap)[(U₁(0) ⊠ SU₂(0) ⊠ FermionParity(0))] .*= -sqrt(2) - blocks(ap)[(U₁(1) ⊠ SU₂(1 // 2) ⊠ FermionParity(1))] .*= 1 - - bm = TensorMap(ones, Elt, psp, - Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1 // 2, 1) => 1) * - psp) + blocks(ap)[(U₁(1) ⊠ SU₂(1//2) ⊠ FermionParity(1))] .*= 1 + + bm = TensorMap( + ones, + Elt, + psp, + Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1//2, 1) => 1) * psp, + ) blocks(bm)[(U₁(0) ⊠ SU₂(0) ⊠ FermionParity(0))] .*= sqrt(2) - blocks(bm)[(U₁(1) ⊠ SU₂(1 // 2) ⊠ FermionParity(1))] .*= -1 + blocks(bm)[(U₁(1) ⊠ SU₂(1//2) ⊠ FermionParity(1))] .*= -1 # this transposition is easier to reason about in a planar way am = transpose(ap', (2, 1), (3,)) @@ -77,7 +82,7 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) h_pm = TensorMap(ones, Elt, psp, psp) blocks(h_pm)[(U₁(0) ⊠ SU₂(0) ⊠ FermionParity(0))] .= 0 - blocks(h_pm)[(U₁(1) ⊠ SU₂(1 // 2) ⊠ FermionParity(1))] .= 1 + blocks(h_pm)[(U₁(1) ⊠ SU₂(1//2) ⊠ FermionParity(1))] .= 1 blocks(h_pm)[(U₁(2) ⊠ SU₂(0) ⊠ FermionParity(0))] .= 2 @plansor o_derp[-1 -2; -3 -4] := am[-1 1; -3] * ap[1 -2; -4] @@ -157,32 +162,36 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) # indmap_2 onsite part # we need pp, mm, pm - pp_f = isometry(fuse(_lastspace(ap)' * _lastspace(ap)'), - _lastspace(ap)' * _lastspace(ap)') - mm_f = isometry(fuse(_lastspace(am)' * _lastspace(am)'), - _lastspace(am)' * _lastspace(am)') - mp_f = isometry(fuse(_lastspace(am)' * _lastspace(ap)'), - _lastspace(am)' * _lastspace(ap)') - pm_f = isometry(fuse(_lastspace(ap)' * _lastspace(am)'), - _lastspace(ap)' * _lastspace(am)') - - @plansor ut_apap[-1 -2; -3 -4] := ut[-1] * ap[-3 1; 3] * ap[1 -2; 4] * - conj(pp_f[-4; 3 4]) - @plansor ut_amam[-1 -2; -3 -4] := ut[-1] * am[-3 1; 3] * am[1 -2; 4] * - conj(mm_f[-4; 3 4]) - @plansor ut_amap[-1 -2; -3 -4] := ut[-1] * am[-3 1; 3] * ap[1 -2; 4] * - conj(mp_f[-4; 3 4]) - @plansor ut_apam[-1 -2; -3 -4] := ut[-1] * ap[-3 1; 3] * am[1 -2; 4] * - conj(pm_f[-4; 3 4]) - - @plansor bpbp_ut[-1 -2; -3 -4] := mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * - conj(ut[-4]) - @plansor bmbm_ut[-1 -2; -3 -4] := pp_f[-1; 1 2] * bm[1; -3 3] * bm[2; 3 -2] * - conj(ut[-4]) - @plansor bmbp_ut[-1 -2; -3 -4] := pm_f[-1; 1 2] * bm[1; -3 3] * bp[2; 3 -2] * - conj(ut[-4]) - @plansor bpbm_ut[-1 -2; -3 -4] := mp_f[-1; 1 2] * bp[1; -3 3] * bm[2; 3 -2] * - conj(ut[-4]) + pp_f = isometry( + fuse(_lastspace(ap)' * _lastspace(ap)'), _lastspace(ap)' * _lastspace(ap)' + ) + mm_f = isometry( + fuse(_lastspace(am)' * _lastspace(am)'), _lastspace(am)' * _lastspace(am)' + ) + mp_f = isometry( + fuse(_lastspace(am)' * _lastspace(ap)'), _lastspace(am)' * _lastspace(ap)' + ) + pm_f = isometry( + fuse(_lastspace(ap)' * _lastspace(am)'), _lastspace(ap)' * _lastspace(am)' + ) + + @plansor ut_apap[-1 -2; -3 -4] := + ut[-1] * ap[-3 1; 3] * ap[1 -2; 4] * conj(pp_f[-4; 3 4]) + @plansor ut_amam[-1 -2; -3 -4] := + ut[-1] * am[-3 1; 3] * am[1 -2; 4] * conj(mm_f[-4; 3 4]) + @plansor ut_amap[-1 -2; -3 -4] := + ut[-1] * am[-3 1; 3] * ap[1 -2; 4] * conj(mp_f[-4; 3 4]) + @plansor ut_apam[-1 -2; -3 -4] := + ut[-1] * ap[-3 1; 3] * am[1 -2; 4] * conj(pm_f[-4; 3 4]) + + @plansor bpbp_ut[-1 -2; -3 -4] := + mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) + @plansor bmbm_ut[-1 -2; -3 -4] := + pp_f[-1; 1 2] * bm[1; -3 3] * bm[2; 3 -2] * conj(ut[-4]) + @plansor bmbp_ut[-1 -2; -3 -4] := + pm_f[-1; 1 2] * bm[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) + @plansor bpbm_ut[-1 -2; -3 -4] := + mp_f[-1; 1 2] * bp[1; -3 3] * bm[2; 3 -2] * conj(ut[-4]) for i in 1:basis_size if i < half_basis_size @@ -214,23 +223,23 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) iso_pp = isomorphism(_lastspace(ap)', _lastspace(ap)') iso_mm = isomorphism(_lastspace(am)', _lastspace(am)') - @plansor p_ap[-1 -2; -3 -4] := iso_pp[-1; 1] * τ[1 2; -3 3] * ap[2 -2; 4] * - conj(pp_f[-4; 3 4]) - @plansor m_ap[-1 -2; -3 -4] := iso_mm[-1; 1] * τ[1 2; -3 3] * ap[2 -2; 4] * - conj(mp_f[-4; 3 4]) - @plansor p_am[-1 -2; -3 -4] := iso_pp[-1; 1] * τ[1 2; -3 3] * am[2 -2; 4] * - conj(pm_f[-4; 3 4]) - @plansor m_am[-1 -2; -3 -4] := iso_mm[-1; 1] * τ[1 2; -3 3] * am[2 -2; 4] * - conj(mm_f[-4; 3 4]) - - @plansor bp_p[-1 -2; -3 -4] := bp[2; -3 3] * iso_mm[1; -4] * τ[4 -2; 3 1] * - mm_f[-1; 2 4] - @plansor bm_p[-1 -2; -3 -4] := bm[2; -3 3] * iso_mm[1; -4] * τ[4 -2; 3 1] * - pm_f[-1; 2 4] - @plansor bm_m[-1 -2; -3 -4] := bm[2; -3 3] * iso_pp[1; -4] * τ[4 -2; 3 1] * - pp_f[-1; 2 4] - @plansor bp_m[-1 -2; -3 -4] := bp[2; -3 3] * iso_pp[1; -4] * τ[4 -2; 3 1] * - mp_f[-1; 2 4] + @plansor p_ap[-1 -2; -3 -4] := + iso_pp[-1; 1] * τ[1 2; -3 3] * ap[2 -2; 4] * conj(pp_f[-4; 3 4]) + @plansor m_ap[-1 -2; -3 -4] := + iso_mm[-1; 1] * τ[1 2; -3 3] * ap[2 -2; 4] * conj(mp_f[-4; 3 4]) + @plansor p_am[-1 -2; -3 -4] := + iso_pp[-1; 1] * τ[1 2; -3 3] * am[2 -2; 4] * conj(pm_f[-4; 3 4]) + @plansor m_am[-1 -2; -3 -4] := + iso_mm[-1; 1] * τ[1 2; -3 3] * am[2 -2; 4] * conj(mm_f[-4; 3 4]) + + @plansor bp_p[-1 -2; -3 -4] := + bp[2; -3 3] * iso_mm[1; -4] * τ[4 -2; 3 1] * mm_f[-1; 2 4] + @plansor bm_p[-1 -2; -3 -4] := + bm[2; -3 3] * iso_mm[1; -4] * τ[4 -2; 3 1] * pm_f[-1; 2 4] + @plansor bm_m[-1 -2; -3 -4] := + bm[2; -3 3] * iso_pp[1; -4] * τ[4 -2; 3 1] * pp_f[-1; 2 4] + @plansor bp_m[-1 -2; -3 -4] := + bp[2; -3 3] * iso_pp[1; -4] * τ[4 -2; 3 1] * mp_f[-1; 2 4] for i in 1:basis_size, j in (i + 1):basis_size if j < half_basis_size @@ -326,18 +335,18 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) # 2|2 for i in 1:basis_size, j in (i + 1):basis_size # p p | . . m m - @plansor __mm[-1 -2; -3 -4] := pp_f[-1; 1 2] * bm[1; -3 3] * bm[2; 3 -2] * - conj(ut[-4]) + @plansor __mm[-1 -2; -3 -4] := + pp_f[-1; 1 2] * bm[1; -3 3] * bm[2; 3 -2] * conj(ut[-4]) hamdat[j, map_2[1, i, 1, i], end] += V[i, i, j, j] * __mm # m m | p p . . - @plansor __pp[-1 -2; -3 -4] := mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * - conj(ut[-4]) + @plansor __pp[-1 -2; -3 -4] := + mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) hamdat[j, map_2[2, i, 2, i], end] += V[j, j, i, i] * __pp # p m | . p . m - @plansor _p_m[-1 -2; -3 -4] := mp_f[-1; 1 2] * bp[1; -3 3] * bm[2; 3 -2] * - conj(ut[-4]) + @plansor _p_m[-1 -2; -3 -4] := + mp_f[-1; 1 2] * bp[1; -3 3] * bm[2; 3 -2] * conj(ut[-4]) hamdat[j, map_2[2, i, 1, i], end] += V[i, j, i, j] * _p_m hamdat[i, 1, end] -= V[i, j, i, j] * h_pm @@ -463,27 +472,29 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) # (i,j) in map_2, 2 onsite for i in 1:basis_size, j in (i + 1):basis_size, k in (j + 1):basis_size # j i m m - @plansor jimm[-1 -2; -3 -4] := bm[1; -3 2] * bm[3; 2 -2] * τ[4 5; 1 3] * - pp_f[-1; 4 5] * conj(ut[-4]) + @plansor jimm[-1 -2; -3 -4] := + bm[1; -3 2] * bm[3; 2 -2] * τ[4 5; 1 3] * pp_f[-1; 4 5] * conj(ut[-4]) hamdat[k, map_2[1, i, 1, j], end] += V[j, i, k, k] * jimm # i j m m - @plansor ijmm[-1 -2; -3 -4] := bm[1; -3 2] * - bm[3; 2 -2] * - τ[4 5; 1 3] * - permute(pp_f, (1,), (3, 2))[-1; 4 5] * - conj(ut[-4]) + @plansor ijmm[-1 -2; -3 -4] := + bm[1; -3 2] * + bm[3; 2 -2] * + τ[4 5; 1 3] * + permute(pp_f, (1,), (3, 2))[-1; 4 5] * + conj(ut[-4]) hamdat[k, map_2[1, i, 1, j], end] += V[i, j, k, k] * ijmm # j p i m - @plansor jpim[-1 -2; -3 -4] := bm[1; -3 2] * bp[3; 2 -2] * τ[4 5; 1 3] * - mp_f[-1; 4 5] * conj(ut[-4]) + @plansor jpim[-1 -2; -3 -4] := + bm[1; -3 2] * bp[3; 2 -2] * τ[4 5; 1 3] * mp_f[-1; 4 5] * conj(ut[-4]) hamdat[k, map_2[2, i, 1, j], end] += V[j, k, i, k] * jpim # i p j m - @plansor ipjm[-1 -2; -3 -4] := bm[1; -3 2] * - bp[3; 2 -2] * - τ[4 5; 1 3] * - permute(pm_f, (1,), (3, 2))[-1; 4 5] * - conj(ut[-4]) + @plansor ipjm[-1 -2; -3 -4] := + bm[1; -3 2] * + bp[3; 2 -2] * + τ[4 5; 1 3] * + permute(pm_f, (1,), (3, 2))[-1; 4 5] * + conj(ut[-4]) hamdat[k, map_2[1, i, 2, j], end] += V[i, k, j, k] * ipjm # j p m i @@ -494,12 +505,12 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_3[1, i, 2, j], end] += V[i, k, k, j] * ipmj # p p j i - @plansor ppji[-1 -2; -3 -4] := mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * - conj(ut[-4]) + @plansor ppji[-1 -2; -3 -4] := + mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) hamdat[k, map_2[2, i, 2, j], end] += V[k, k, j, i] * ppji # p p i j - @plansor ppij[-1 -2; -3 -4] := permute(mm_f, (1,), (3, 2))[-1; 1 2] * bp[1; -3 3] * - bp[2; 3 -2] * conj(ut[-4]) + @plansor ppij[-1 -2; -3 -4] := + permute(mm_f, (1,), (3, 2))[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) hamdat[k, map_2[2, i, 2, j], end] += V[k, k, i, j] * ppij # p . . m @@ -559,8 +570,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[1, i, 1, j], map_4[2, l]] += V[j, i, k, l] * jimR # i j m R - @plansor ijmR[-1 -2; -3 -4] := permute(pp_f, (1,), (3, 2))[-1; 1 2] * - τ[3 2; -4 -2] * bm[1; -3 3] + @plansor ijmR[-1 -2; -3 -4] := + permute(pp_f, (1,), (3, 2))[-1; 1 2] * τ[3 2; -4 -2] * bm[1; -3 3] hamdat[k, map_2[1, i, 1, j], map_4[2, l]] += V[i, j, k, l] * ijmR # j i R m @@ -568,8 +579,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[1, i, 1, j], map_4[2, l]] += V[j, i, l, k] * jiRm # i j R m - @plansor ijRm[-1 -2; -3 -4] := permute(pp_f, (1,), (3, 2))[-1; 1 2] * - τ[1 3; -3 -4] * bm[2; 3 -2] + @plansor ijRm[-1 -2; -3 -4] := + permute(pp_f, (1,), (3, 2))[-1; 1 2] * τ[1 3; -3 -4] * bm[2; 3 -2] hamdat[k, map_2[1, i, 1, j], map_4[2, l]] += V[i, j, l, k] * ijRm # j p i R @@ -577,8 +588,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 1, j], map_4[2, l]] += V[j, k, i, l] * jpiR # i p j R - @plansor ipjR[-1 -2; -3 -4] := permute(pm_f, (1,), (3, 2))[-1; 1 2] * - τ[3 2; -4 -2] * bp[1; -3 3] + @plansor ipjR[-1 -2; -3 -4] := + permute(pm_f, (1,), (3, 2))[-1; 1 2] * τ[3 2; -4 -2] * bp[1; -3 3] hamdat[k, map_2[1, i, 2, j], map_4[2, l]] += V[i, k, j, l] * ipjR # j R i m @@ -586,8 +597,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 1, j], map_4[1, l]] += V[j, l, i, k] * jRim # i R j m - @plansor iRjm[-1 -2; -3 -4] := permute(pm_f, (1,), (3, 2))[-1; 1 2] * - τ[1 3; -3 -4] * bm[2; 3 -2] + @plansor iRjm[-1 -2; -3 -4] := + permute(pm_f, (1,), (3, 2))[-1; 1 2] * τ[1 3; -3 -4] * bm[2; 3 -2] hamdat[k, map_2[1, i, 2, j], map_4[1, l]] += V[i, l, j, k] * iRjm # p j R i @@ -595,8 +606,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 1, j], map_4[2, l]] += V[k, j, l, i] * pjRi # p i R j - @plansor piRj[-1 -2; -3 -4] := permute(pm_f, (1,), (3, 2))[-1; 1 2] * - τ[3 2; -4 -2] * bp[1; -3 3] + @plansor piRj[-1 -2; -3 -4] := + permute(pm_f, (1,), (3, 2))[-1; 1 2] * τ[3 2; -4 -2] * bp[1; -3 3] hamdat[k, map_2[1, i, 2, j], map_4[2, l]] += V[k, i, l, j] * piRj # R j m i @@ -604,8 +615,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 1, j], map_4[1, l]] += V[l, j, k, i] * Rjmi # R i m j - @plansor Rimj[-1 -2; -3 -4] := permute(pm_f, (1,), (3, 2))[-1; 1 2] * - τ[1 3; -3 -4] * bm[2; 3 -2] + @plansor Rimj[-1 -2; -3 -4] := + permute(pm_f, (1,), (3, 2))[-1; 1 2] * τ[1 3; -3 -4] * bm[2; 3 -2] hamdat[k, map_2[1, i, 2, j], map_4[1, l]] += V[l, i, k, j] * Rimj # R p j i @@ -613,8 +624,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 2, j], map_4[1, l]] += V[l, k, j, i] * Rpji # R p i j - @plansor Rpij[-1 -2; -3 -4] := permute(mm_f, (1,), (3, 2))[-1; 1 2] * - τ[1 3; -3 -4] * bp[2; 3 -2] + @plansor Rpij[-1 -2; -3 -4] := + permute(mm_f, (1,), (3, 2))[-1; 1 2] * τ[1 3; -3 -4] * bp[2; 3 -2] hamdat[k, map_2[2, i, 2, j], map_4[1, l]] += V[l, k, i, j] * Rpij # p R j i @@ -622,8 +633,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 2, j], map_4[1, l]] += V[k, l, j, i] * pRji # p R i j - @plansor pRij[-1 -2; -3 -4] := permute(mm_f, (1,), (3, 2))[-1; 1 2] * - τ[3 2; -4 -2] * bp[1; -3 3] + @plansor pRij[-1 -2; -3 -4] := + permute(mm_f, (1,), (3, 2))[-1; 1 2] * τ[3 2; -4 -2] * bp[1; -3 3] hamdat[k, map_2[2, i, 2, j], map_4[1, l]] += V[k, l, i, j] * pRij end diff --git a/src/models/transfermatrices.jl b/src/models/transfermatrices.jl index 84a49b7..e62e7fc 100644 --- a/src/models/transfermatrices.jl +++ b/src/models/transfermatrices.jl @@ -17,8 +17,9 @@ function classical_ising end function classical_ising(symmetry::Type{<:Sector}; kwargs...) return classical_ising(ComplexF64, symmetry; kwargs...) end -function classical_ising(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; - beta=log(1 + sqrt(2)) / 2) +function classical_ising( + elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; beta=log(1 + sqrt(2)) / 2 +) t = elt[exp(beta) exp(-beta); exp(-beta) exp(beta)] r = eigen(t) @@ -57,16 +58,19 @@ MPO for the partition function of the two-dimensional six vertex model. """ function sixvertex end sixvertex(symmetry::Type{<:Sector}; kwargs...) = sixvertex(ComplexF64, symmetry; kwargs...) -function sixvertex(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; a=1.0, b=1.0, - c=1.0) - d = elt[a 0 0 0 - 0 c b 0 - 0 b c 0 - 0 0 0 a] +function sixvertex( + elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; a=1.0, b=1.0, c=1.0 +) + d = elt[ + a 0 0 0 + 0 c b 0 + 0 b c 0 + 0 0 0 a + ] return DenseMPO(permute(TensorMap(d, ℂ^2 ⊗ ℂ^2, ℂ^2 ⊗ ℂ^2), ((1, 2), (4, 3)))) end function sixvertex(elt::Type{<:Number}, ::Type{U1Irrep}; a=1.0, b=1.0, c=1.0) - pspace = U1Space(-1 // 2 => 1, 1 // 2 => 1) + pspace = U1Space(-1//2 => 1, 1//2 => 1) mpo = TensorMap(zeros, elt, pspace ⊗ pspace, pspace ⊗ pspace) blocks(mpo)[Irrep[U₁](0)] = [b c; c b] blocks(mpo)[Irrep[U₁](1)] = reshape([a], (1, 1)) @@ -74,7 +78,7 @@ function sixvertex(elt::Type{<:Number}, ::Type{U1Irrep}; a=1.0, b=1.0, c=1.0) return DenseMPO(permute(mpo, ((1, 2), (4, 3)))) end function sixvertex(elt::Type{<:Number}, ::Type{CU1Irrep}; a=1.0, b=1.0, c=1.0) - pspace = CU1Space(1 // 2 => 1) + pspace = CU1Space(1//2 => 1) mpo = TensorMap(zeros, elt, pspace ⊗ pspace, pspace ⊗ pspace) blocks(mpo)[Irrep[CU₁](0, 0)] = reshape([b + c], (1, 1)) blocks(mpo)[Irrep[CU₁](0, 1)] = reshape([-b + c], (1, 1)) @@ -107,13 +111,15 @@ end MPO for the partition function of the two-dimensional discrete clock model with ``q`` states. """ -function qstate_clock(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; - beta::Number=1.0, q::Integer=3) +function qstate_clock( + elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; beta::Number=1.0, q::Integer=3 +) comega(d) = cos(2 * pi * d / q) O = zeros(elt, q, q, q, q) for i in 1:q, j in 1:q, k in 1:q, l in 1:q - O[i, j, k, l] = exp(beta * - (comega(i - j) + comega(j - k) + comega(k - l) + comega(l - i))) + O[i, j, k, l] = exp( + beta * (comega(i - j) + comega(j - k) + comega(k - l) + comega(l - i)) + ) end return DenseMPO(TensorMap(O, ℂ^q * ℂ^q, ℂ^q * ℂ^q)) diff --git a/src/operators/bosonoperators.jl b/src/operators/bosonoperators.jl index 6960d83..4058489 100644 --- a/src/operators/bosonoperators.jl +++ b/src/operators/bosonoperators.jl @@ -93,23 +93,27 @@ end const a⁻ = a_min a_plusmin(symmetry::Type{<:Sector}; kwargs...) = a_plusmin(ComplexF64, symmetry; kwargs...) -function a_plusmin(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; - cutoff::Integer=5) +function a_plusmin( + elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; cutoff::Integer=5 +) return contract_twosite(a⁺(elt; cutoff=cutoff), a⁻(elt; cutoff=cutoff)) end function a_plusmin(elt::Type{<:Number}, ::Type{U1Irrep}; cutoff::Integer=5) - return contract_twosite(a⁺(elt, U1Irrep; cutoff=cutoff, side=:L), - a⁻(elt, U1Irrep; cutoff=cutoff, side=:R)) + return contract_twosite( + a⁺(elt, U1Irrep; cutoff=cutoff, side=:L), a⁻(elt, U1Irrep; cutoff=cutoff, side=:R) + ) end a_minplus(symmetry::Type{<:Sector}; kwargs...) = a_minplus(ComplexF64, symmetry; kwargs...) -function a_minplus(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; - cutoff::Integer=5) +function a_minplus( + elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; cutoff::Integer=5 +) return contract_twosite(a⁻(elt; cutoff=cutoff), a⁺(elt; cutoff=cutoff)) end function a_minplus(elt::Type{<:Number}, ::Type{U1Irrep}; cutoff::Integer=5) - return contract_twosite(a⁻(elt, U1Irrep; cutoff=cutoff, side=:L), - a⁺(elt, U1Irrep; cutoff=cutoff, side=:R)) + return contract_twosite( + a⁻(elt, U1Irrep; cutoff=cutoff, side=:L), a⁺(elt, U1Irrep; cutoff=cutoff, side=:R) + ) end """ diff --git a/src/operators/hubbardoperators.jl b/src/operators/hubbardoperators.jl index 6b60c9f..cf6c5ab 100644 --- a/src/operators/hubbardoperators.jl +++ b/src/operators/hubbardoperators.jl @@ -23,40 +23,44 @@ function hubbard_space(::Type{Trivial}=Trivial, ::Type{Trivial}=Trivial) return Vect[FermionParity](0 => 2, 1 => 2) end function hubbard_space(::Type{Trivial}, ::Type{U1Irrep}) - return Vect[FermionParity ⊠ U1Irrep]((0, 0) => 2, (1, 1 // 2) => 1, (1, -1 // 2) => 1) + return Vect[FermionParity ⊠ U1Irrep]((0, 0) => 2, (1, 1//2) => 1, (1, -1//2) => 1) end function hubbard_space(::Type{Trivial}, ::Type{SU2Irrep}) - return Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 2, (1, 1 // 2) => 1) + return Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 2, (1, 1//2) => 1) end function hubbard_space(::Type{U1Irrep}, ::Type{Trivial}) return Vect[FermionParity ⊠ U1Irrep]((0, 0) => 1, (1, 1) => 2, (0, 2) => 1) end function hubbard_space(::Type{U1Irrep}, ::Type{U1Irrep}) - return Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]((0, 0, 0) => 1, (1, 1, 1 // 2) => 1, - (1, 1, -1 // 2) => 1, (0, 2, 0) => 1) + return Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]( + (0, 0, 0) => 1, (1, 1, 1//2) => 1, (1, 1, -1//2) => 1, (0, 2, 0) => 1 + ) end function hubbard_space(::Type{U1Irrep}, ::Type{SU2Irrep}) - return Vect[FermionParity ⊠ U1Irrep ⊠ SU2Irrep]((0, 0, 0) => 1, (1, 1, 1 // 2) => 1, - (0, 2, 0) => 1) + return Vect[FermionParity ⊠ U1Irrep ⊠ SU2Irrep]( + (0, 0, 0) => 1, (1, 1, 1//2) => 1, (0, 2, 0) => 1 + ) end function hubbard_space(::Type{SU2Irrep}, ::Type{Trivial}) - return Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 2, (1, 1 // 2) => 1) + return Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 2, (1, 1//2) => 1) end function hubbard_space(::Type{SU2Irrep}, ::Type{U1Irrep}) - return Vect[FermionParity ⊠ SU2Irrep ⊠ U1Irrep]((0, 0, 0) => 1, (1, 1 // 2, 1) => 1) + return Vect[FermionParity ⊠ SU2Irrep ⊠ U1Irrep]((0, 0, 0) => 1, (1, 1//2, 1) => 1) end function hubbard_space(::Type{SU2Irrep}, ::Type{SU2Irrep}) - return Vect[FermionParity ⊠ SU2Irrep ⊠ SU2Irrep]((1, 1 // 2, 1 // 2) => 1) + return Vect[FermionParity ⊠ SU2Irrep ⊠ SU2Irrep]((1, 1//2, 1//2) => 1) end -function single_site_operator(T, particle_symmetry::Type{<:Sector}, - spin_symmetry::Type{<:Sector}) +function single_site_operator( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector} +) V = hubbard_space(particle_symmetry, spin_symmetry) return TensorMap(zeros, T, V ← V) end -function two_site_operator(T, particle_symmetry::Type{<:Sector}, - spin_symmetry::Type{<:Sector}) +function two_site_operator( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector} +) V = hubbard_space(particle_symmetry, spin_symmetry) return TensorMap(zeros, T, V ⊗ V ← V ⊗ V) end @@ -88,10 +92,10 @@ end function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}) t = two_site_operator(T, U1Irrep, U1Irrep) I = sectortype(t) - t[(I(1, 1, 1 // 2), I(0, 0, 0), dual(I(0, 0, 0)), dual(I(1, 1, 1 // 2)))] .= 1 - t[(I(1, 1, 1 // 2), I(1, 1, -1 // 2), dual(I(0, 0, 0)), dual(I(0, 2, 0)))] .= 1 - t[(I(0, 2, 0), I(0, 0, 0), dual(I(1, 1, -1 // 2)), dual(I(1, 1, 1 // 2)))] .= -1 - t[(I(0, 2, 0), I(1, 1, -1 // 2), dual(I(1, 1, -1 // 2)), dual(I(0, 2, 0)))] .= -1 + t[(I(1, 1, 1//2), I(0, 0, 0), dual(I(0, 0, 0)), dual(I(1, 1, 1//2)))] .= 1 + t[(I(1, 1, 1//2), I(1, 1, -1//2), dual(I(0, 0, 0)), dual(I(0, 2, 0)))] .= 1 + t[(I(0, 2, 0), I(0, 0, 0), dual(I(1, 1, -1//2)), dual(I(1, 1, 1//2)))] .= -1 + t[(I(0, 2, 0), I(1, 1, -1//2), dual(I(1, 1, -1//2)), dual(I(0, 2, 0)))] .= -1 return t end function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}) @@ -135,10 +139,10 @@ end function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}) t = two_site_operator(T, U1Irrep, U1Irrep) I = sectortype(t) - t[(I(1, 1, -1 // 2), I(0, 0, 0), dual(I(0, 0, 0)), dual(I(1, 1, -1 // 2)))] .= 1 - t[(I(1, 1, -1 // 2), I(1, 1, 1 // 2), dual(I(0, 0, 0)), dual(I(0, 2, 0)))] .= -1 - t[(I(0, 2, 0), I(0, 0, 0), dual(I(1, 1, 1 // 2)), dual(I(1, 1, -1 // 2)))] .= 1 - t[(I(0, 2, 0), I(1, 1, 1 // 2), dual(I(1, 1, 1 // 2)), dual(I(0, 2, 0)))] .= -1 + t[(I(1, 1, -1//2), I(0, 0, 0), dual(I(0, 0, 0)), dual(I(1, 1, -1//2)))] .= 1 + t[(I(1, 1, -1//2), I(1, 1, 1//2), dual(I(0, 0, 0)), dual(I(0, 2, 0)))] .= -1 + t[(I(0, 2, 0), I(0, 0, 0), dual(I(1, 1, 1//2)), dual(I(1, 1, -1//2)))] .= 1 + t[(I(0, 2, 0), I(1, 1, 1//2), dual(I(1, 1, 1//2)), dual(I(0, 2, 0)))] .= -1 return t end function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}) @@ -191,16 +195,16 @@ end function e_plusmin(T, ::Type{U1Irrep}, ::Type{SU2Irrep}) t = two_site_operator(T, U1Irrep, SU2Irrep) I = sectortype(t) - 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))) + 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 - f3 = only(fusiontrees((I(1, 1, 1 // 2), I(0, 2, 0)), I(1, 3, 1 // 2))) - f4 = only(fusiontrees((I(0, 2, 0), I(1, 1, 1 // 2)), I(1, 3, 1 // 2))) + f3 = only(fusiontrees((I(1, 1, 1//2), I(0, 2, 0)), I(1, 3, 1//2))) + f4 = only(fusiontrees((I(0, 2, 0), I(1, 1, 1//2)), I(1, 3, 1//2))) t[f3, f4] .= -1 f5 = only(fusiontrees((I(0, 0, 0), I(0, 2, 0)), I(0, 2, 0))) - f6 = only(fusiontrees((I(1, 1, 1 // 2), I(1, 1, 1 // 2)), I(0, 2, 0))) + f6 = only(fusiontrees((I(1, 1, 1//2), I(1, 1, 1//2)), I(0, 2, 0))) t[f5, f6] .= sqrt(2) - f7 = only(fusiontrees((I(1, 1, 1 // 2), I(1, 1, 1 // 2)), I(0, 2, 0))) + f7 = only(fusiontrees((I(1, 1, 1//2), I(1, 1, 1//2)), I(0, 2, 0))) f8 = only(fusiontrees((I(0, 2, 0), I(0, 0, 0)), I(0, 2, 0))) t[f7, f8] .= sqrt(2) return t @@ -244,7 +248,7 @@ end function e_number_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}) t = single_site_operator(T, U1Irrep, U1Irrep) I = sectortype(t) - block(t, I(1, 1, 1 // 2)) .= 1 + block(t, I(1, 1, 1//2)) .= 1 block(t, I(0, 2, 0)) .= 1 return t end @@ -287,7 +291,7 @@ end function e_number_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}) t = single_site_operator(T, U1Irrep, U1Irrep) I = sectortype(t) - block(t, I(1, 1, -1 // 2)) .= 1 + block(t, I(1, 1, -1//2)) .= 1 block(t, I(0, 2, 0)) .= 1 return t end @@ -318,7 +322,7 @@ end function e_number(T, ::Type{U1Irrep}, ::Type{SU2Irrep}) t = single_site_operator(T, U1Irrep, SU2Irrep) I = sectortype(t) - block(t, I(1, 1, 1 // 2)) .= 1 + block(t, I(1, 1, 1//2)) .= 1 block(t, I(0, 2, 0)) .= 2 return t end @@ -330,8 +334,9 @@ const n = e_number Return the one-body operator that counts the number of doubly occupied sites. """ e_number_updown(P::Type{<:Sector}, S::Type{<:Sector}) = e_number_updown(ComplexF64, P, S) -function e_number_updown(T, particle_symmetry::Type{<:Sector}, - spin_symmetry::Type{<:Sector}) +function e_number_updown( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector} +) return e_number_up(T, particle_symmetry, spin_symmetry) * e_number_down(T, particle_symmetry, spin_symmetry) end diff --git a/src/operators/localoperators.jl b/src/operators/localoperators.jl index 9e99b1e..3c779a7 100644 --- a/src/operators/localoperators.jl +++ b/src/operators/localoperators.jl @@ -11,9 +11,9 @@ operator is represented as a vector of `MPOTensor`s, each of which acts on a sin struct LocalOperator{T<:AbstractTensorMap{<:Any,2,2},G<:LatticePoint} opp::Vector{T} inds::Vector{G} - function LocalOperator{T,G}(O::Vector{T}, - inds::Vector{G}) where {T<:AbstractTensorMap{<:Any,2,2}, - G<:LatticePoint} + function LocalOperator{T,G}( + O::Vector{T}, inds::Vector{G} + ) where {T<:AbstractTensorMap{<:Any,2,2},G<:LatticePoint} length(O) == length(inds) || throw(ArgumentError("number of operators and indices should be the same")) issorted(inds) && allunique(inds) || @@ -24,8 +24,9 @@ struct LocalOperator{T<:AbstractTensorMap{<:Any,2,2},G<:LatticePoint} end end -function LocalOperator(t::AbstractTensorMap{<:Any,N,N}, - inds::Vararg{G,N}) where {N,G<:LatticePoint} +function LocalOperator( + t::AbstractTensorMap{<:Any,N,N}, inds::Vararg{G,N} +) where {N,G<:LatticePoint} p = TupleTools.sortperm(linearize_index.(inds)) t = permute(t, (p, p .+ N)) t_mpo = collect(MPSKit.decompose_localmpo(MPSKit.add_util_leg(t))) @@ -85,26 +86,31 @@ function Base.:*(a::LocalOperator{T₁,G}, b::LocalOperator{T₂,G}) where {T₁ right_vspace_A = isnothing(i_A) ? left_vspace_A : space(a.opp[i_A], 4)' right_vspace_B = isnothing(i_B) ? left_vspace_B : space(b.opp[i_B], 4)' - left_fuse = unitary(M, fuse(left_vspace_B, left_vspace_A), - left_vspace_B ⊗ left_vspace_A) - right_fuse = unitary(M, fuse(right_vspace_B, right_vspace_A), - right_vspace_B ⊗ right_vspace_A) + left_fuse = unitary( + M, fuse(left_vspace_B, left_vspace_A), left_vspace_B ⊗ left_vspace_A + ) + right_fuse = unitary( + M, fuse(right_vspace_B, right_vspace_A), right_vspace_B ⊗ right_vspace_A + ) if !isnothing(i_A) && !isnothing(i_B) - @plansor operators[i][-1 -2; -3 -4] := b.opp[i_B][1 2; -3 4] * - a.opp[i_A][3 -2; 2 5] * - left_fuse[-1; 1 3] * - conj(right_fuse[-4; 4 5]) + @plansor operators[i][-1 -2; -3 -4] := + b.opp[i_B][1 2; -3 4] * + a.opp[i_A][3 -2; 2 5] * + left_fuse[-1; 1 3] * + conj(right_fuse[-4; 4 5]) elseif !isnothing(i_A) - @plansor operators[i][-1 -2; -3 -4] := τ[1 2; -3 4] * - a.opp[i_A][3 -2; 2 5] * - left_fuse[-1; 1 3] * - conj(right_fuse[-4; 4 5]) + @plansor operators[i][-1 -2; -3 -4] := + τ[1 2; -3 4] * + a.opp[i_A][3 -2; 2 5] * + left_fuse[-1; 1 3] * + conj(right_fuse[-4; 4 5]) elseif !isnothing(i_B) - @plansor operators[i][-1 -2; -3 -4] := b.opp[i_B][1 2; -3 4] * - τ[3 -2; 2 5] * - left_fuse[-1; 1 3] * - conj(right_fuse[-4; 4 5]) + @plansor operators[i][-1 -2; -3 -4] := + b.opp[i_B][1 2; -3 4] * + τ[3 -2; 2 5] * + left_fuse[-1; 1 3] * + conj(right_fuse[-4; 4 5]) else error("this should not happen") end diff --git a/src/operators/mpoham.jl b/src/operators/mpoham.jl index 35d2fe6..24d2ab9 100644 --- a/src/operators/mpoham.jl +++ b/src/operators/mpoham.jl @@ -58,16 +58,16 @@ addoperations(ex) = ex import MPSKit: MPOHamiltonian MPSKitModels.MPOHamiltonian(args...) = MPSKit.MPOHamiltonian(args...) -function _find_free_channel(data::Array{Union{E,T},3}, - loc)::Tuple{Int, - Array{Union{E,T},3}} where {E<:Number, - T<:AbstractTensorMap} +function _find_free_channel( + data::Array{Union{E,T},3}, loc +)::Tuple{Int,Array{Union{E,T},3}} where {E<:Number,T<:AbstractTensorMap} hit = findfirst(map(x -> _is_free_channel(data, loc, x), 2:(size(data, 2) - 1))) #hit = findfirst(ismissing.(data[loc,1,2:end-1])); if isnothing(hit) - ndata = fill!(Array{Union{E,T},3}(undef, size(data, 1), size(data, 2) + 1, - size(data, 2) + 1), - zero(E)) + ndata = fill!( + Array{Union{E,T},3}(undef, size(data, 1), size(data, 2) + 1, size(data, 2) + 1), + zero(E), + ) ndata[:, 1:(end - 1), 1:(end - 2)] .= data[:, :, 1:(end - 1)] ndata[:, 1:(end - 2), end] .= data[:, 1:(end - 1), end] ndata[:, end, end] .= data[:, end, end] diff --git a/src/operators/spinoperators.jl b/src/operators/spinoperators.jl index 6ccdd27..57097d1 100644 --- a/src/operators/spinoperators.jl +++ b/src/operators/spinoperators.jl @@ -6,8 +6,10 @@ end function _pauliterm(spin, i::U1Irrep, j::U1Irrep) -spin <= i.charge <= spin || return 0.0 -spin <= j.charge <= spin || return 0.0 - return sqrt((spin + 1) * (i.charge + j.charge + 2 * spin + 1) - - (i.charge + spin + 1) * (j.charge + spin + 1)) / 2.0 + return sqrt( + (spin + 1) * (i.charge + j.charge + 2 * spin + 1) - + (i.charge + spin + 1) * (j.charge + spin + 1), + ) / 2.0 end """ @@ -57,14 +59,14 @@ S_x(; kwargs...) = S_x(ComplexF64, Trivial; kwargs...) S_x(elt::Type{<:Number}; kwargs...) = S_x(elt, Trivial; kwargs...) S_x(symm::Type{<:Sector}; kwargs...) = S_x(ComplexF64, symm; kwargs...) -function S_x(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) +function S_x(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) S_x_mat, _, _ = spinmatrices(spin, elt) pspace = ComplexSpace(size(S_x_mat, 1)) return TensorMap(S_x_mat, pspace ← pspace) end -function S_x(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2) - spin == 1 // 2 || error("not implemented") +function S_x(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2) + spin == 1//2 || error("not implemented") pspace = Z2Space(0 => 1, 1 => 1) X = TensorMap(zeros, elt, pspace, pspace) blocks(X)[Z2Irrep(0)] .= one(elt) / 2 @@ -72,7 +74,7 @@ function S_x(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2) return X end -function S_x(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2, side=:L) +function S_x(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2, side=:L) pspace = U1Space(i => 1 for i in (-spin):spin) vspace = U1Space(1 => 1, -1 => 1) if side == :L @@ -115,14 +117,14 @@ S_y(; kwargs...) = S_y(ComplexF64, Trivial; kwargs...) S_y(elt::Type{<:Complex}; kwargs...) = S_y(elt, Trivial; kwargs...) S_y(symm::Type{<:Sector}; kwargs...) = S_y(ComplexF64, symm; kwargs...) -function S_y(elt::Type{<:Complex}, ::Type{Trivial}; spin=1 // 2) +function S_y(elt::Type{<:Complex}, ::Type{Trivial}; spin=1//2) _, Y, _, _ = spinmatrices(spin, elt) pspace = ComplexSpace(size(Y, 1)) return TensorMap(Y, pspace ← pspace) end -function S_y(elt::Type{<:Complex}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) - spin == 1 // 2 || error("not implemented") +function S_y(elt::Type{<:Complex}, ::Type{Z2Irrep}; spin=1//2, side=:L) + spin == 1//2 || error("not implemented") pspace = Z2Space(0 => 1, 1 => 1) vspace = Z2Space(1 => 1) if side == :L @@ -139,7 +141,7 @@ function S_y(elt::Type{<:Complex}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) return Y end -function S_y(elt::Type{<:Complex}, ::Type{U1Irrep}; spin=1 // 2, side=:L) +function S_y(elt::Type{<:Complex}, ::Type{U1Irrep}; spin=1//2, side=:L) pspace = U1Space(i => 1 for i in (-spin):spin) vspace = U1Space(1 => 1, -1 => 1) if side == :L @@ -187,14 +189,14 @@ S_z(; kwargs...) = S_z(ComplexF64, Trivial; kwargs...) S_z(elt::Type{<:Number}; kwargs...) = S_z(elt, Trivial; kwargs...) S_z(symm::Type{<:Sector}; kwargs...) = S_z(ComplexF64, symm; kwargs...) -function S_z(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) +function S_z(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) _, _, S_z_mat = spinmatrices(spin, elt) pspace = ComplexSpace(size(S_z_mat, 1)) return TensorMap(S_z_mat, pspace ← pspace) end -function S_z(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) - spin == 1 // 2 || error("Z2 symmetry only implemented for spin 1 // 2") +function S_z(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) + spin == 1//2 || error("Z2 symmetry only implemented for spin 1 // 2") pspace = Z2Space(0 => 1, 1 => 1) vspace = Z2Space(1 => 1) if side == :L @@ -211,7 +213,7 @@ function S_z(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) return Z end -function S_z(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2) +function S_z(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2) charges = U1Irrep.((-spin):spin) pspace = U1Space((v => 1 for v in charges)) Z = TensorMap(zeros, elt, pspace ← pspace) @@ -239,13 +241,13 @@ S_plus(; kwargs...) = S_plus(ComplexF64, Trivial; kwargs...) S_plus(elt::Type{<:Number}; kwargs...) = S_plus(elt, Trivial; kwargs...) S_plus(symm::Type{<:Sector}; kwargs...) = S_plus(ComplexF64, symm; kwargs...) -function S_plus(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) +function S_plus(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) S⁺ = S_x(elt, Trivial; spin=spin) + 1im * S_y(complex(elt), Trivial; spin=spin) return elt <: Real ? real(S⁺) : S⁺ end -function S_plus(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) - spin == 1 // 2 || error("Z2 symmetry only implemented for spin 1 // 2") +function S_plus(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) + spin == 1//2 || error("Z2 symmetry only implemented for spin 1 // 2") pspace = Z2Space(0 => 1, 1 => 1) vspace = Z2Space(0 => 1, 1 => 1) if side == :L @@ -262,7 +264,7 @@ function S_plus(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) return S⁺ end -function S_plus(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2, side=:L) +function S_plus(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2, side=:L) pspace = U1Space(i => 1 for i in (-spin):spin) if side == :L vspace = U1Space(1 => 1) @@ -300,13 +302,13 @@ S_min(; kwargs...) = S_min(ComplexF64, Trivial; kwargs...) S_min(elt::Type{<:Number}; kwargs...) = S_min(elt, Trivial; kwargs...) S_min(symm::Type{<:Sector}; kwargs...) = S_min(ComplexF64, symm; kwargs...) -function S_min(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) +function S_min(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) S⁻ = S_x(elt, Trivial; spin=spin) - 1im * S_y(complex(elt), Trivial; spin=spin) return elt <: Real ? real(S⁻) : S⁻ end -function S_min(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) - spin == 1 // 2 || error("Z2 symmetry only implemented for spin 1 // 2") +function S_min(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) + spin == 1//2 || error("Z2 symmetry only implemented for spin 1 // 2") pspace = Z2Space(0 => 1, 1 => 1) vspace = Z2Space(0 => 1, 1 => 1) if side == :L @@ -323,7 +325,7 @@ function S_min(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) return S⁻ end -function S_min(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2, side=:L) +function S_min(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2, side=:L) pspace = U1Space(i => 1 for i in (-spin):spin) if side == :L vspace = U1Space(-1 => 1) @@ -378,14 +380,17 @@ for (L, R) in ((:x, :x), (:y, :y), (:z, :z), (:plus, :min), (:min, :plus)) ($f)(elt::Type{<:Number}; kwargs...) = ($f)(elt, Trivial; kwargs...) ($f)(symmetry::Type{<:Sector}; kwargs...) = ($f)(ComplexF64, symmetry; kwargs...) - function ($f)(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) - return contract_twosite($(fₗ)(elt, Trivial; spin=spin), - $(fᵣ)(elt, Trivial; spin=spin)) + function ($f)(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) + return contract_twosite( + $(fₗ)(elt, Trivial; spin=spin), $(fᵣ)(elt, Trivial; spin=spin) + ) end - function ($f)(elt::Type{<:Number}, symmetry::Type{<:Sector}; spin=1 // 2) - return contract_twosite($(fₗ)(elt, symmetry; spin=spin, side=:L), - $(fᵣ)(elt, symmetry; spin=spin, side=:R)) + function ($f)(elt::Type{<:Number}, symmetry::Type{<:Sector}; spin=1//2) + return contract_twosite( + $(fₗ)(elt, symmetry; spin=spin, side=:L), + $(fᵣ)(elt, symmetry; spin=spin, side=:R), + ) end const $f_unicode = $f @@ -396,10 +401,10 @@ for (L, R) in ((:x, :x), (:y, :y), (:z, :z), (:plus, :min), (:min, :plus)) end end -function S_xx(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2) +function S_xx(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2) return contract_twosite(S_x(elt, Z2Irrep; spin=spin), S_x(elt, Z2Irrep; spin=spin)) end -function S_zz(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2) +function S_zz(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2) return contract_twosite(S_z(elt, U1Irrep; spin=spin), S_z(elt, U1Irrep; spin=spin)) end @@ -418,13 +423,13 @@ function S_exchange(symmetry::Type{<:Sector}; kwargs...) return S_exchange(ComplexF64, symmetry; kwargs...) end -function S_exchange(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) +function S_exchange(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) return S_xx(elt, Trivial; spin=spin) + S_yy(elt, Trivial; spin=spin) + S_zz(elt, Trivial; spin=spin) end -function S_exchange(elt::Type{<:Number}, ::Type{SU2Irrep}; spin=1 // 2) +function S_exchange(elt::Type{<:Number}, ::Type{SU2Irrep}; spin=1//2) pspace = SU2Space(spin => 1) aspace = SU2Space(1 => 1) @@ -435,7 +440,7 @@ function S_exchange(elt::Type{<:Number}, ::Type{SU2Irrep}; spin=1 // 2) return SS end -function S_exchange(elt::Type{<:Number}, symmetry::Type{<:Sector}; spin=1 // 2) +function S_exchange(elt::Type{<:Number}, symmetry::Type{<:Sector}; spin=1//2) return (S_plusmin(elt, symmetry; spin=spin) + S_minplus(elt, symmetry; spin=spin)) / 2 + S_zz(elt, symmetry; spin=spin) end diff --git a/test/bosonoperators.jl b/test/bosonoperators.jl index 0b6ae7c..c385b67 100644 --- a/test/bosonoperators.jl +++ b/test/bosonoperators.jl @@ -15,9 +15,9 @@ end @testset "U1-symmetric bosonic operators" begin @test convert(Array, a_number(U1Irrep; cutoff=cutoff)) ≈ - convert(Array, a_number(; cutoff=cutoff)) + convert(Array, a_number(; cutoff=cutoff)) @test permute(a_plus(U1Irrep; cutoff=cutoff, side=:L)', ((2, 1), (3,))) ≈ - a_min(U1Irrep; cutoff=cutoff, side=:R) + a_min(U1Irrep; cutoff=cutoff, side=:R) @test permute(a_min(U1Irrep; cutoff=cutoff, side=:L)', ((2, 1), (3,))) ≈ - a_plus(U1Irrep; cutoff=cutoff, side=:R) + a_plus(U1Irrep; cutoff=cutoff, side=:R) end diff --git a/test/heisenberg.jl b/test/heisenberg.jl index 791eb3b..babee18 100644 --- a/test/heisenberg.jl +++ b/test/heisenberg.jl @@ -18,26 +18,29 @@ end @testset "xxx SU2" begin H = @inferred heisenberg_XXX(SU2Irrep) - ψ = InfiniteMPS([Rep[SU₂](1 => 1)], [Rep[SU₂](1 // 2 => 5, 3 // 2 => 5, 5 // 2 => 1)]) + ψ = InfiniteMPS([Rep[SU₂](1 => 1)], [Rep[SU₂](1//2 => 5, 3//2 => 5, 5//2 => 1)]) @test imag(expectation_value(ψ, H)) ≈ 0 atol = 1e-10 ψ, envs, δ = find_groundstate(ψ, H, alg) @test E₀ ≈ expectation_value(ψ, H, envs) atol = 1e-2 - ΔEs, qps = excitations(H, QuasiparticleAnsatz(), Float64(pi), ψ, envs; - sector=SU2Irrep(1)) + ΔEs, qps = excitations( + H, QuasiparticleAnsatz(), Float64(pi), ψ, envs; sector=SU2Irrep(1) + ) @test E₁ ≈ first(ΔEs) atol = 1e-2 end @testset "xxx U1" begin H = @inferred heisenberg_XXX(U1Irrep) - ψ = InfiniteMPS([Rep[U₁](0 => 1, 1 => 1, -1 => 1)], - [Rep[U₁](1 // 2 => 10, -1 // 2 => 10, 3 // 2 => 5, -3 // 2 => 5, - 5 // 2 => 3, -5 // 2 => 3)]) + ψ = InfiniteMPS( + [Rep[U₁](0 => 1, 1 => 1, -1 => 1)], + [Rep[U₁](1//2 => 10, -1//2 => 10, 3//2 => 5, -3//2 => 5, 5//2 => 3, -5//2 => 3)], + ) @test imag(expectation_value(ψ, H)) ≈ 0 atol = 1e-10 ψ, envs, δ = find_groundstate(ψ, H, alg) @test E₀ ≈ expectation_value(ψ, H, envs) atol = 1e-2 - ΔEs, qps = excitations(H, QuasiparticleAnsatz(), Float64(pi), ψ, envs; - sector=U1Irrep(1)) + ΔEs, qps = excitations( + H, QuasiparticleAnsatz(), Float64(pi), ψ, envs; sector=U1Irrep(1) + ) @test E₁ ≈ first(ΔEs) atol = 1e-2 end diff --git a/test/hubbardoperators.jl b/test/hubbardoperators.jl index 105ac22..82247c1 100644 --- a/test/hubbardoperators.jl +++ b/test/hubbardoperators.jl @@ -3,9 +3,7 @@ using TensorKit using MPSKitModels.HubbardOperators using LinearAlgebra: eigvals -implemented_symmetries = [(Trivial, Trivial), - (U1Irrep, U1Irrep), - (U1Irrep, SU2Irrep)] +implemented_symmetries = [(Trivial, Trivial), (U1Irrep, U1Irrep), (U1Irrep, SU2Irrep)] @testset "basic properties" begin for particle_symmetry in (Trivial, U1Irrep, SU2Irrep), spin_symmetry in (Trivial, U1Irrep, SU2Irrep) @@ -13,28 +11,28 @@ implemented_symmetries = [(Trivial, Trivial), if (particle_symmetry, spin_symmetry) in implemented_symmetries # test hermiticity @test e_plusmin(particle_symmetry, spin_symmetry)' ≈ - e_minplus(particle_symmetry, spin_symmetry) + e_minplus(particle_symmetry, spin_symmetry) if spin_symmetry !== SU2Irrep @test e_plusmin_down(particle_symmetry, spin_symmetry)' ≈ - e_minplus_down(particle_symmetry, spin_symmetry) + e_minplus_down(particle_symmetry, spin_symmetry) @test e_plusmin_up(particle_symmetry, spin_symmetry)' ≈ - e_minplus_up(particle_symmetry, spin_symmetry) + e_minplus_up(particle_symmetry, spin_symmetry) @test e_plusmin_down(particle_symmetry, spin_symmetry)' ≈ - e_minplus_down(particle_symmetry, spin_symmetry) + e_minplus_down(particle_symmetry, spin_symmetry) @test e_plusmin_up(particle_symmetry, spin_symmetry)' ≈ - e_minplus_up(particle_symmetry, spin_symmetry) + e_minplus_up(particle_symmetry, spin_symmetry) end # test number operator if spin_symmetry !== SU2Irrep @test e_number(particle_symmetry, spin_symmetry) ≈ - e_number_up(particle_symmetry, spin_symmetry) + + e_number_up(particle_symmetry, spin_symmetry) + e_number_down(particle_symmetry, spin_symmetry) @test e_number_updown(particle_symmetry, spin_symmetry) ≈ - e_number_up(particle_symmetry, spin_symmetry) * - e_number_down(particle_symmetry, spin_symmetry) ≈ - e_number_down(particle_symmetry, spin_symmetry) * - e_number_up(particle_symmetry, spin_symmetry) + e_number_up(particle_symmetry, spin_symmetry) * + e_number_down(particle_symmetry, spin_symmetry) ≈ + e_number_down(particle_symmetry, spin_symmetry) * + e_number_up(particle_symmetry, spin_symmetry) end else @test_broken e_plusmin(particle_symmetry, spin_symmetry) @@ -44,14 +42,19 @@ implemented_symmetries = [(Trivial, Trivial), end function hamiltonian(particle_symmetry, spin_symmetry; t, U, mu, L) - hopping = t * (e_plusmin(particle_symmetry, spin_symmetry) + - e_minplus(particle_symmetry, spin_symmetry)) + hopping = + t * ( + e_plusmin(particle_symmetry, spin_symmetry) + + e_minplus(particle_symmetry, spin_symmetry) + ) interaction = U * e_number_updown(particle_symmetry, spin_symmetry) chemical_potential = mu * e_number(particle_symmetry, spin_symmetry) I = id(hubbard_space(particle_symmetry, spin_symmetry)) - H = sum(1:(L - 1)) do i + H = + sum(1:(L - 1)) do i return reduce(⊗, insert!(collect(Any, fill(I, L - 2)), i, hopping)) - end + sum(1:L) do i + end + + sum(1:L) do i return reduce(⊗, insert!(collect(Any, fill(I, L - 1)), i, interaction)) end + sum(1:L) do i diff --git a/test/potts.jl b/test/potts.jl index 1526563..2d2161d 100644 --- a/test/potts.jl +++ b/test/potts.jl @@ -7,8 +7,9 @@ alg = VUMPS(; maxiter=25, verbosity=0) function E₀(Q::Int, maxiter::Int=1000) Q == 3 && return -(4 / 3 + 2sqrt(3) / π) Q == 4 && return 2 - 8 * log(2) - summation = sum((-1)^n / (sqrt(Q) / 2 - cosh((2 * n + 1) * acosh(sqrt(Q) / 2))) - for n in 1:maxiter) + summation = sum( + (-1)^n / (sqrt(Q) / 2 - cosh((2 * n + 1) * acosh(sqrt(Q) / 2))) for n in 1:maxiter + ) limit = 2 - Q - sqrt(Q) * (Q - 4) * summation return limit end @@ -58,8 +59,9 @@ end @testset "ZNIrrep{5}" begin H = quantum_potts(ZNIrrep{5}; q=5) - ψ = InfiniteMPS(Vect[ZNIrrep{5}](i => 1 for i in 0:4), - Vect[ZNIrrep{5}](i => 12 for i in 0:4)) + ψ = InfiniteMPS( + Vect[ZNIrrep{5}](i => 1 for i in 0:4), Vect[ZNIrrep{5}](i => 12 for i in 0:4) + ) @test imag(expectation_value(ψ, H)) ≈ 0 atol = 1e-10 ψ, envs, δ = find_groundstate(ψ, H, alg) @test E₀(5) ≈ expectation_value(ψ, H, envs) atol = 1e-2 diff --git a/test/sixvertex.jl b/test/sixvertex.jl index ac0d73a..bb72c75 100644 --- a/test/sixvertex.jl +++ b/test/sixvertex.jl @@ -17,8 +17,10 @@ end @testset "U₁" begin mpo = @inferred sixvertex(ComplexF64, U1Irrep) mpo2 = MPOMultiline([mpo.opp mpo.opp; mpo.opp mpo.opp]) - vspaces = [U1Space(0 => 20, 1 => 10, -1 => 10, 2 => 5, -2 => 5), - U1Space(1 // 2 => 15, -1 // 2 => 15, 3 // 2 => 5, -3 // 2 => 5)] + vspaces = [ + U1Space(0 => 20, 1 => 10, -1 => 10, 2 => 5, -2 => 5), + U1Space(1//2 => 15, -1//2 => 15, 3//2 => 5, -3//2 => 5), + ] ψ = MPSMultiline(repeat(space.(mpo.opp, 2), 2, 2), [vspaces circshift(vspaces, 1)]) ψ, _ = leading_boundary(ψ, mpo2, alg) F = prod(expectation_value(ψ, mpo2)) @@ -28,8 +30,10 @@ end @testset "CU₁" begin mpo = @inferred sixvertex(ComplexF64, CU1Irrep) mpo2 = MPOMultiline([mpo.opp mpo.opp; mpo.opp mpo.opp]) - vspaces = [CU1Space((0, 0) => 10, (0, 1) => 10, (1, 2) => 5, (2, 2) => 5), - CU1Space((1 // 2, 2) => 15, (3 // 2, 2) => 5)] + vspaces = [ + CU1Space((0, 0) => 10, (0, 1) => 10, (1, 2) => 5, (2, 2) => 5), + CU1Space((1//2, 2) => 15, (3//2, 2) => 5), + ] ψ = MPSMultiline(repeat(space.(mpo.opp, 2), 2, 2), [vspaces circshift(vspaces, 1)]) ψ, _ = leading_boundary(ψ, mpo2, alg) F = prod(expectation_value(ψ, mpo2)) diff --git a/test/spinoperators.jl b/test/spinoperators.jl index 51c29c3..fb8130c 100644 --- a/test/spinoperators.jl +++ b/test/spinoperators.jl @@ -11,7 +11,7 @@ for i in 1:3 ε[mod1(i, 3), mod1(i - 1, 3), mod1(i - 2, 3)] = -1 end -@testset "non-symmetric spin $(Int(2S))/2 operators" for S in (1 // 2):(1 // 2):4 +@testset "non-symmetric spin $(Int(2S))/2 operators" for S in (1//2):(1//2):4 # inferrability X = @inferred S_x(; spin=S) Y = @inferred S_y(; spin=S) @@ -37,7 +37,7 @@ end # commutation relations for i in 1:3, j in 1:3 @test Svec[i] * Svec[j] - Svec[j] * Svec[i] ≈ - sum(im * ε[i, j, k] * Svec[k] for k in 1:3) + sum(im * ε[i, j, k] * Svec[k] for k in 1:3) end # definition of +- @@ -94,23 +94,23 @@ end @test (S⁺⁻ + S⁻⁺) / 2 ≈ XX + YY rtol = 1e-3 end -@testset "U1-symmetric spin $(Int(2spin))/2 operators" for spin in (1 // 2):(1 // 2):4 +@testset "U1-symmetric spin $(Int(2spin))/2 operators" for spin in (1//2):(1//2):4 # array conversion N = Int(2spin + 1) p = sortperm(reverse((-spin):spin); by=x -> abs(x - 0.1)) # sort as 0, 1, -1, 2, -2, ... H = one(zeros(N, N))[p, :] @test H * convert(Array, S_z(; spin=spin)) * H' ≈ - convert(Array, S_z(U1Irrep; spin=spin)) + convert(Array, S_z(U1Irrep; spin=spin)) for S in (S_x, S_y, S_plus, S_min) array1 = convert(Array, S(; spin=spin)) - arrayL = H' * - reshape(sum(convert(Array, S(U1Irrep; side=:L, spin=spin)); dims=3), N, - N) * - H - arrayR = H' * - reshape(sum(convert(Array, S(U1Irrep; side=:R, spin=spin)); dims=1), N, - N) * - H + arrayL = + H' * + reshape(sum(convert(Array, S(U1Irrep; side=:L, spin=spin)); dims=3), N, N) * + H + arrayR = + H' * + reshape(sum(convert(Array, S(U1Irrep; side=:R, spin=spin)); dims=1), N, N) * + H @test array1 ≈ arrayL @test array1 ≈ arrayR end @@ -118,19 +118,20 @@ end # # hermiticity @test S_z(U1Irrep; spin=spin)' ≈ S_z(U1Irrep; spin=spin) @test permute(S_x(U1Irrep; spin=spin, side=:L)', ((2, 1), (3,))) ≈ - S_x(U1Irrep; spin=spin, side=:R) + S_x(U1Irrep; spin=spin, side=:R) @test permute(S_y(U1Irrep; spin=spin, side=:L)', ((2, 1), (3,))) ≈ - S_y(U1Irrep; spin=spin, side=:R) + S_y(U1Irrep; spin=spin, side=:R) @test permute(S_plus(U1Irrep; spin=spin, side=:L)', ((2, 1), (3,))) ≈ - S_min(U1Irrep; spin=spin, side=:R) + S_min(U1Irrep; spin=spin, side=:R) @test permute(S_min(U1Irrep; spin=spin, side=:L)', ((2, 1), (3,))) ≈ - S_plus(U1Irrep; spin=spin, side=:R) + S_plus(U1Irrep; spin=spin, side=:R) # # composite operators @test (S_plusmin(U1Irrep; spin=spin) + S_minplus(U1Irrep; spin=spin)) / 2 ≈ - S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) rtol = 1e-3 + S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) rtol = 1e-3 @test S_exchange(U1Irrep; spin=spin) ≈ - S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) + S_zz(U1Irrep; spin=spin) rtol = 1e-3 + S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) + S_zz(U1Irrep; spin=spin) rtol = + 1e-3 end # potts_ZZ test? From a3abf74c065d347f935ca6b838d9f68da86ee727 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sat, 30 Nov 2024 16:02:54 +0800 Subject: [PATCH 02/14] Add t-J hopping, spin and number operators --- src/MPSKitModels.jl | 6 + src/operators/tjoperators.jl | 419 +++++++++++++++++++++++++++++++++++ test/hubbardoperators.jl | 5 - test/runtests.jl | 4 + test/tjoperators.jl | 107 +++++++++ 5 files changed, 536 insertions(+), 5 deletions(-) create mode 100644 src/operators/tjoperators.jl create mode 100644 test/tjoperators.jl diff --git a/src/MPSKitModels.jl b/src/MPSKitModels.jl index bf61ede..d8d65ae 100644 --- a/src/MPSKitModels.jl +++ b/src/MPSKitModels.jl @@ -35,6 +35,7 @@ export c⁺, c⁻, c⁺⁺, c⁻⁻, c⁺⁻, c⁻⁺ export e_plus, e_min, e_plusplus, e_minmin, e_plusmin, e_minplus export e_number, e_number_up, e_number_down, e_number_updown export e⁺⁺, e⁻⁻, e⁺⁻, e⁻⁺ +export tJ export transverse_field_ising export kitaev_model @@ -42,6 +43,7 @@ export quantum_potts export heisenberg_XXX, heisenberg_XXZ, heisenberg_XYZ export bilinear_biquadratic_model export hubbard_model, bose_hubbard_model +export tj_model export quantum_chemistry_hamiltonian export classical_ising @@ -65,6 +67,10 @@ include("operators/spinoperators.jl") include("operators/fermionoperators.jl") include("operators/hubbardoperators.jl") using .HubbardOperators +# TJOperators share operator names with HubbardOperators +# and is only imported to avoid name conflicts +include("operators/tjoperators.jl") +import .TJOperators as tJ include("operators/bosonoperators.jl") include("models/hamiltonians.jl") diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl new file mode 100644 index 0000000..648e45b --- /dev/null +++ b/src/operators/tjoperators.jl @@ -0,0 +1,419 @@ +#= Operators that act on t-J-type models +i.e. the local hilbert space consists of + +- usual basis states: + |∅⟩, |↑⟩, |↓⟩ +- slave-fermion basis states (c_σ = h† b_σ; holon h is fermionic, spinon b_σ is bosonic): + |h⟩ = h†|∅⟩, |↑'⟩ = (b↑)†|∅⟩, |↓'⟩ = (b↓)†|∅⟩ +=# +module TJOperators + +using TensorKit + +export tj_space +export e_plusmin, e_plusmin_up, e_plusmin_down +export e_minplus, e_minplus_up, e_minplus_down +export e_number, e_number_up, e_number_down +export S_x, S_y, S_z +export S_plusmin, S_minplus, S_exchange + +export e⁺e⁻, e⁺e⁻ꜛ, e⁺e⁻ꜜ, e⁻e⁺, e⁻e⁺ꜛ, e⁻e⁺ꜜ +export nꜛ, nꜜ +# not exported because namespace: export n + +""" + tj_space(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the local hilbert space for a t-J-type model with the given particle and spin symmetries. +The possible symmetries are +- Particle number: `Trivial`, `U1Irrep`; +- Spin: `Trivial`, `U1Irrep`, `SU2Irrep`. + +Setting `sf = true` switches to the slave-fermion basis. +""" +function tj_space(::Type{Trivial}=Trivial, ::Type{Trivial}=Trivial; sf::Bool=false) + return sf ? Vect[FermionParity](0 => 2, 1 => 1) : Vect[FermionParity](0 => 1, 1 => 2) +end +function tj_space(::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + return if sf + Vect[FermionParity ⊠ U1Irrep]((1, 0) => 1, (0, 1//2) => 1, (0, -1//2) => 1) + else + Vect[FermionParity ⊠ U1Irrep]((0, 0) => 1, (1, 1//2) => 1, (1, -1//2) => 1) + end +end +function tj_space(::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) + return error("Not implemented") +end +function tj_space(::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + return if sf + Vect[FermionParity ⊠ U1Irrep]((1, 0) => 1, (0, 1) => 2) + else + Vect[FermionParity ⊠ U1Irrep]((0, 0) => 1, (1, 1) => 2) + end +end +function tj_space(::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + return if sf + Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]( + (1, 0, 0) => 1, (0, 1, 1//2) => 1, (0, 1, -1//2) => 1 + ) + else + Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]( + (0, 0, 0) => 1, (1, 1, 1//2) => 1, (1, 1, -1//2) => 1 + ) + end +end +function tj_space(::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) + return error("Not implemented") +end + +function single_site_operator( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + V = tj_space(particle_symmetry, spin_symmetry; sf=sf) + return TensorMap(zeros, T, V ← V) +end + +function two_site_operator( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + V = tj_space(particle_symmetry, spin_symmetry; sf=sf) + return TensorMap(zeros, T, V ⊗ V ← V ⊗ V) +end + +""" + e_plusmin_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. +The only nonzero matrix element corresponds to `|↑0⟩ <-- |0↑⟩`. +""" +e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_plusmin_up(ComplexF64, P, S; sf=sf) +function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = two_site_operator(T, Trivial, Trivial; sf=sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + #= The extra minus sign in slave-fermion basis: + c†_{1,↑} c_{2,↑} |0↑⟩ + = h_1 b†_{1,↑} h†_2 b_{2,↑} h†_1 b†_{2,↑}|vac⟩ + = -b†_{1,↑} h†_2 h_1 h†_1 b_{2,↑} b†_{2,↑}|vac⟩ + = -b†_{1,↑} h†_2 |vac⟩ + = -|↑0⟩ + =# + t[(I(b), I(h), dual(I(h)), dual(I(b)))][1, 1, 1, 1] = sgn * 1 + return t +end +function e_plusmin_up(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; sf=sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(b, 1//2), I(h, 0), dual(I(h, 0)), dual(I(b, 1//2)))] .= sgn * 1 + return t +end +function e_plusmin_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) + return error("Not implemented") +end +function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + return error("Not implemented") +end +function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + return error("Not implemented") +end +function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) + return error("Not implemented") +end +const e⁺e⁻ꜛ = e_plusmin_up + +""" + e_plusmin_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. +The only nonzero matrix element corresponds to `|↓0⟩ <-- |0↓⟩`. +""" +e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_plusmin_down(ComplexF64, P, S; sf=sf) +function e_plusmin_down(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = two_site_operator(T, Trivial, Trivial; sf=sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(b), I(h), dual(I(h)), dual(I(b)))][2, 1, 1, 2] = sgn * 1 + return t +end +function e_plusmin_down(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; sf=sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(b, -1//2), I(h, 0), dual(I(h, 0)), dual(I(b, -1//2)))] .= sgn * 1 + return t +end +function e_plusmin_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) + return error("Not implemented") +end +function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + return error("Not implemented") +end +function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + return error("Not implemented") +end +function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) + return error("Not implemented") +end +const e⁺e⁻ꜜ = e_plusmin_down + +""" + e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator that annihilates a spin-up electron at the first site and creates a spin-up electron at the second. +The only nonzero matrix element corresponds to `|0↑⟩ <-- |↑0⟩`. +""" +e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_minplus_up(ComplexF64, P, S; sf=sf) +function e_minplus_up( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + return copy(adjoint(e_plusmin_up(T, particle_symmetry, spin_symmetry; sf=sf))) +end +const e⁻⁺ꜛ = e_minplus_up + +""" + e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator that annihilates a spin-down electron at the first site and creates a spin-down electron at the second. +The only nonzero matrix element corresponds to `|0↓⟩ <-- |↓0⟩`. +""" +e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_minplus_down(ComplexF64, P, S; sf=sf) +function e_minplus_down( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + return copy(adjoint(e_plusmin_down(T, particle_symmetry, spin_symmetry; sf=sf))) +end +const e⁻e⁺ꜜ = e_minplus_down + +""" + e_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator that creates a particle at the first site and annihilates a particle at the second. +This is the sum of `e_plusmin_up` and `e_plusmin_down`. +""" +e_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_plusmin(ComplexF64, P, S; sf=sf) +function e_plusmin( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + return e_plusmin_up(T, particle_symmetry, spin_symmetry; sf=sf) + + e_plusmin_down(T, particle_symmetry, spin_symmetry; sf=sf) +end +const e⁺e⁻ = e_plusmin + +""" + e_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator that annihilates a particle at the first site and creates a particle at the second. +This is the sum of `e_minplus_up` and `e_minplus_down`. +""" +e_minplus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_minplus(ComplexF64, P, S; sf=sf) +function e_minplus( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + return copy(adjoint(e_plusmin(T, particle_symmetry, spin_symmetry; sf=sf))) +end +const e⁻e⁺ = e_minplus + +""" + e_number_up(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the one-body operator that counts the number of spin-up electrons. +""" +e_number_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_number_up(ComplexF64, P, S; sf=sf) +function e_number_up(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = single_site_operator(T, Trivial, Trivial; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b), dual(I(b)))][1, 1] = 1 + return t +end +function e_number_up(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + t = single_site_operator(T, Trivial, U1Irrep; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1//2), dual(I(b, 1//2)))][1, 1] = 1 + return t +end +function e_number_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) + throw(ArgumentError("`e_number_up` is not symmetric under `SU2Irrep` spin symmetry")) +end +function e_number_up(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + return error("Not implemented") +end +function e_number_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + return error("Not implemented") +end +function e_number_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) + throw(ArgumentError("`e_number_up` is not symmetric under `SU2Irrep` spin symmetry")) +end +const nꜛ = e_number_up + +""" + e_number_down(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + +Return the one-body operator that counts the number of spin-down electrons. +""" +e_number_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_number_down(ComplexF64, P, S; sf=sf) +function e_number_down(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = single_site_operator(T, Trivial, Trivial; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b), dual(I(b)))][2, 2] = 1 + return t +end +function e_number_down(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + t = single_site_operator(T, Trivial, U1Irrep; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, -1//2), dual(I(b, -1//2)))][1, 1] = 1 + return t +end +function e_number_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) + throw(ArgumentError("`e_number_down` is not symmetric under `SU2Irrep` spin symmetry")) +end +function e_number_down(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + return error("Not implemented") +end +function e_number_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + return error("Not implemented") +end +function e_number_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) + throw(ArgumentError("`e_number_down` is not symmetric under `SU2Irrep` spin symmetry")) +end +const nꜜ = e_number_down + +""" + e_number(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + +Return the one-body operator that counts the number of particles. +""" +e_number(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + e_number(ComplexF64, P, S; sf=sf) +function e_number( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + return e_number_up(T, particle_symmetry, spin_symmetry; sf=sf) + + e_number_down(T, particle_symmetry, spin_symmetry; sf=sf) +end +const n = e_number + +""" + S_x(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + +Return the one-body spin-1/2 x-operator on the electrons. +""" +S_x(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_x(ComplexF64, P, S; sf=sf) +S_x(; sf::Bool=false) = S_x(ComplexF64, Trivial, Trivial; sf=sf) +function S_x(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = single_site_operator(T, Trivial, Trivial; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b), dual(I(b)))][1, 2] = 0.5 + t[(I(b), dual(I(b)))][2, 1] = 0.5 + return t +end + +""" + S_y(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + +Return the one-body spin-1/2 x-operator on the electrons (only defined for `Trivial` symmetry). +""" +S_y(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_y(ComplexF64, P, S; sf=sf) +S_y(; sf::Bool=false) = S_y(ComplexF64, Trivial, Trivial; sf=sf) +function S_y(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = single_site_operator(T, Trivial, Trivial; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b), dual(I(b)))][1, 2] = -0.5im + t[(I(b), dual(I(b)))][2, 1] = 0.5im + return t +end + +""" + S_z(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + +Return the one-body spin-1/2 z-operator on the electrons. +""" +S_z(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_z(ComplexF64, P, S; sf=sf) +S_z(; sf::Bool=false) = S_z(ComplexF64, Trivial, Trivial; sf=sf) +function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = single_site_operator(T, Trivial, Trivial; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b), dual(I(b)))][1, 1] = 0.5 + t[(I(b), dual(I(b)))][2, 2] = -0.5 + return t +end +function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + t = single_site_operator(T, Trivial, U1Irrep; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1//2), dual(I(b, 1//2)))] .= 0.5 + t[(I(b, -1//2), dual(I(b, -1//2)))] .= -0.5 + return t +end + +""" + S_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator S⁺S⁻. +The only nonzero matrix element corresponds to `|↑↓⟩ <-- |↓↑⟩`. +""" +S_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + S_plusmin(ComplexF64, P, S; sf=sf) +function S_plusmin(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = two_site_operator(T, Trivial, Trivial; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b), I(b), dual(I(b)), dual(I(b)))][1, 2, 2, 1] = 1 + return t +end +function S_plusmin(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; sf=sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1//2), I(b, -1//2), dual(I(b, -1//2)), dual(I(b, 1//2)))] .= 1 + return t +end + +""" + S_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator S⁻S⁺. +The only nonzero matrix element corresponds to `|↓↑⟩ <-- |↑↓⟩`. +""" +S_minplus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + S_minplus(ComplexF64, P, S; sf=sf) +function S_minplus( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + return copy(adjoint(S_plusmin(T, particle_symmetry, spin_symmetry; sf=sf))) +end + +""" + S_exchange(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the spin exchange operator S⁻S⁺. +The only nonzero matrix element corresponds to `|↓↑⟩ <-- |↑↓⟩`. +""" +S_exchange(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = + S_exchange(ComplexF64, P, S; sf=sf) +function S_exchange( + T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false +) + Sz = S_z(T, particle_symmetry, spin_symmetry; sf=sf) + return (1/2) * ( + S_plusmin(T, particle_symmetry, spin_symmetry; sf=sf) + + S_minplus(T, particle_symmetry, spin_symmetry; sf=sf) + ) + Sz ⊗ Sz +end + +end diff --git a/test/hubbardoperators.jl b/test/hubbardoperators.jl index 82247c1..ee10ef7 100644 --- a/test/hubbardoperators.jl +++ b/test/hubbardoperators.jl @@ -69,11 +69,6 @@ end U = randn() mu = randn() - hopping = t * (e_plusmin(Trivial, Trivial) + e_minplus(Trivial, Trivial)) - interaction = U * e_number_updown(Trivial, Trivial) - chemical_potential = mu * e_number(Trivial, Trivial) - I = id(domain(interaction)) - H_triv = hamiltonian(Trivial, Trivial; t, U, mu, L) vals_triv = mapreduce(vcat, eigvals(H_triv)) do (c, v) return repeat(real.(v), dim(c)) diff --git a/test/runtests.jl b/test/runtests.jl index c897426..08e9b52 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,6 +21,10 @@ end include("hubbardoperators.jl") end +@testset "t-J operators" begin + include("tjoperators.jl") +end + @testset "mpoham" begin include("mpoham.jl") end diff --git a/test/tjoperators.jl b/test/tjoperators.jl new file mode 100644 index 0000000..bdf99f1 --- /dev/null +++ b/test/tjoperators.jl @@ -0,0 +1,107 @@ +using Test +using TensorKit +using MPSKitModels.TJOperators +using LinearAlgebra: eigvals + +implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] +@testset "basic properties" begin + for sf in (false, true), + particle_symmetry in (Trivial, U1Irrep), + spin_symmetry in (Trivial, U1Irrep, SU2Irrep) + + if (particle_symmetry, spin_symmetry) in implemented_symmetries + # test hermiticity + @test e_plusmin(particle_symmetry, spin_symmetry; sf=sf)' ≈ + e_minplus(particle_symmetry, spin_symmetry; sf=sf) + if spin_symmetry !== SU2Irrep + @test e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ + e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) + @test e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ + e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) + @test e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ + e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) + @test e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ + e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) + end + + # test number operator + if spin_symmetry !== SU2Irrep + pspace = tj_space(particle_symmetry, spin_symmetry; sf=sf) + @test e_number(particle_symmetry, spin_symmetry; sf=sf) ≈ + e_number_up(particle_symmetry, spin_symmetry; sf=sf) + + e_number_down(particle_symmetry, spin_symmetry; sf=sf) + @test TensorMap(zeros, pspace, pspace) ≈ + e_number_up(particle_symmetry, spin_symmetry; sf=sf) * + e_number_down(particle_symmetry, spin_symmetry; sf=sf) ≈ + e_number_down(particle_symmetry, spin_symmetry; sf=sf) * + e_number_up(particle_symmetry, spin_symmetry; sf=sf) + end + + # test spin operator + if (particle_symmetry, spin_symmetry) == (Trivial, Trivial) + ε = zeros(ComplexF64, 3, 3, 3) + for i in 1:3 + ε[mod1(i, 3), mod1(i + 1, 3), mod1(i + 2, 3)] = 1 + ε[mod1(i, 3), mod1(i - 1, 3), mod1(i - 2, 3)] = -1 + end + Svec = [S_x(; sf), S_y(; sf), S_z(; sf)] + # Hermiticity + for s in Svec + @test s' ≈ s + end + # operators should be normalized + S = 1 / 2 + @test sum(tr(Svec[i]^2) for i in 1:3) / (2S + 1) ≈ S * (S + 1) + # commutation relations + for i in 1:3, j in 1:3 + @test Svec[i] * Svec[j] - Svec[j] * Svec[i] ≈ + sum(im * ε[i, j, k] * Svec[k] for k in 1:3) + end + end + else + @test_broken e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + @test_broken e_minplus(particle_symmetry, spin_symmetry; sf=sf) + end + end +end + +function hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, sf) + num = e_number(particle_symmetry, spin_symmetry; sf=sf) + hop_heis = + (-t) * ( + e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + + e_minplus(particle_symmetry, spin_symmetry; sf=sf) + ) + + J * (S_exchange(particle_symmetry, spin_symmetry; sf=sf) - (1 / 4) * (num ⊗ num)) + chemical_potential = (-mu) * num + I = id(tj_space(particle_symmetry, spin_symmetry; sf=sf)) + H = + sum(1:(L - 1)) do i + return reduce(⊗, insert!(collect(Any, fill(I, L - 2)), i, hop_heis)) + end + sum(1:L) do i + return reduce(⊗, insert!(collect(Any, fill(I, L - 1)), i, chemical_potential)) + end + return H +end + +@testset "spectrum" begin + L = 4 + t = randn() + J = randn() + mu = randn() + + for sf in (false, true) + H_triv = hamiltonian(Trivial, Trivial; t, J, mu, L, sf) + vals_triv = mapreduce(vcat, eigvals(H_triv)) do (c, v) + return repeat(real.(v), dim(c)) + end + sort!(vals_triv) + + H_u1 = hamiltonian(Trivial, U1Irrep; t, J, mu, L, sf) + vals_u1 = mapreduce(vcat, eigvals(H_u1)) do (c, v) + return repeat(real.(v), dim(c)) + end + sort!(vals_u1) + @test vals_triv ≈ vals_u1 + end +end From 5bc3eb83f42014c10db8a59ab1c40d7be6f735dd Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sat, 30 Nov 2024 16:49:31 +0800 Subject: [PATCH 03/14] Add t-J model MPOHamiltonian; revert style to `yas` --- .JuliaFormatter.toml | 2 +- docs/make.jl | 23 ++- src/lattices/lattices.jl | 5 +- src/lattices/squarelattice.jl | 68 ++++---- src/models/hamiltonians.jl | 280 ++++++++++++++++-------------- src/models/quantum_chemistry.jl | 210 +++++++++++----------- src/models/transfermatrices.jl | 34 ++-- src/operators/bosonoperators.jl | 20 +-- src/operators/hubbardoperators.jl | 69 ++++---- src/operators/localoperators.jl | 48 +++-- src/operators/mpoham.jl | 14 +- src/operators/spinoperators.jl | 71 ++++---- src/operators/tjoperators.jl | 193 ++++++++++---------- test/bosonoperators.jl | 6 +- test/heisenberg.jl | 19 +- test/hubbardoperators.jl | 30 ++-- test/potts.jl | 10 +- test/sixvertex.jl | 12 +- test/spinoperators.jl | 37 ++-- test/tjoperators.jl | 43 +++-- 20 files changed, 570 insertions(+), 624 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index c743950..9613e05 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -1 +1 @@ -style = "blue" \ No newline at end of file +style = "yas" \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index c3c789e..0d1d4c8 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,18 +2,15 @@ using Documenter using MPSKitModels makedocs(; - modules=[MPSKitModels], - sitename="MPSKitModels.jl", - authors="Maarten Vandamme", - format=Documenter.HTML(; - prettyurls=get(ENV, "CI", nothing) == "true", mathengine=MathJax() - ), - pages=[ - "Home" => "index.md", - "Manual" => - ["man/operators.md", "man/mpoham.md", "man/lattices.md", "man/models.md"], - "Index" => "package_index.md", - ], -) + modules=[MPSKitModels], + sitename="MPSKitModels.jl", + authors="Maarten Vandamme", + format=Documenter.HTML(; + prettyurls=get(ENV, "CI", nothing) == "true", + mathengine=MathJax()), + pages=["Home" => "index.md", + "Manual" => ["man/operators.md", "man/mpoham.md", "man/lattices.md", + "man/models.md"], + "Index" => "package_index.md"],) deploydocs(; repo="github.com/QuantumKitHub/MPSKitModels.jl.git") diff --git a/src/lattices/lattices.jl b/src/lattices/lattices.jl index 84a5694..fa69c8b 100644 --- a/src/lattices/lattices.jl +++ b/src/lattices/lattices.jl @@ -48,8 +48,7 @@ function Base.checkbounds(L::AbstractLattice{N}, inds::Vararg{Int,N}) where {N} return checkbounds(Bool, L, inds...) || throw(BoundsError(L, inds)) end -function Base.checkbounds( - ::Type{Bool}, L::AbstractLattice{N}, inds::Vararg{Int,N} -) where {N} +function Base.checkbounds(::Type{Bool}, L::AbstractLattice{N}, + inds::Vararg{Int,N}) where {N} return Base.checkbounds_indices(Bool, axes(L), inds) end diff --git a/src/lattices/squarelattice.jl b/src/lattices/squarelattice.jl index fbdf036..e917810 100644 --- a/src/lattices/squarelattice.jl +++ b/src/lattices/squarelattice.jl @@ -139,9 +139,8 @@ function linearize_index(helix::InfiniteHelix, i::Int, j::Int) end function vertices(lattice::Union{FiniteStrip,InfiniteStrip,FiniteCylinder,InfiniteCylinder}) - return ( - LatticePoint((i, j), lattice) for i in 1:(lattice.L), j in 1:(lattice.N ÷ lattice.L) - ) + return (LatticePoint((i, j), lattice) for i in 1:(lattice.L), + j in 1:(lattice.N ÷ lattice.L)) end function vertices(lattice::Union{FiniteHelix,InfiniteHelix}) return (LatticePoint((i, 1), lattice) for i in 1:(lattice.N)) @@ -150,40 +149,36 @@ end function nearest_neighbours(lattice::FiniteStrip) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = ( - LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in 1:rows, - j in 1:(cols - 1) - ) - vertical = ( - LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for - i in 1:(rows - 1), j in 1:cols - ) + horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in + 1:rows, + j in + 1:(cols - 1)) + vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for + i in 1:(rows - 1), j in 1:cols) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::FiniteCylinder) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = ( - LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in 1:rows, - j in 1:(cols - 1) - ) - vertical = ( - LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for i in 1:rows, - j in 1:cols - ) + horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in + 1:rows, + j in + 1:(cols - 1)) + vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for i in + 1:rows, + j in + 1:cols) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::FiniteHelix) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = ( - LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in 1:rows, - j in 1:(cols - 1) - ) - vertical = ( - LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for - i in 1:rows, j in 1:cols if (i != rows && j != cols) - ) + horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in + 1:rows, + j in + 1:(cols - 1)) + vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for + i in 1:rows, j in 1:cols if (i != rows && j != cols)) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::Union{InfiniteStrip,InfiniteCylinder,InfiniteHelix}) @@ -192,23 +187,22 @@ function nearest_neighbours(lattice::Union{InfiniteStrip,InfiniteCylinder,Infini for v in V push!(neighbours, v => v + (0, 1)) if v.coordinates[1] < lattice.L || - lattice isa InfiniteCylinder || - lattice isa InfiniteHelix + lattice isa InfiniteCylinder || + lattice isa InfiniteHelix push!(neighbours, v => v + (1, 0)) end end return neighbours end -function next_nearest_neighbours( - lattice::Union{InfiniteStrip,InfiniteCylinder,InfiniteHelix} -) +function next_nearest_neighbours(lattice::Union{InfiniteStrip,InfiniteCylinder, + InfiniteHelix}) V = vertices(lattice) neighbours = Pair{eltype(V),eltype(V)}[] for v in V if v.coordinates[1] < lattice.L || - lattice isa InfiniteCylinder || - lattice isa InfiniteHelix + lattice isa InfiniteCylinder || + lattice isa InfiniteHelix push!(neighbours, v => v + (1, 1)) end if v.coordinates[1] > 1 || lattice isa InfiniteCylinder || lattice isa InfiniteHelix @@ -220,10 +214,8 @@ end LinearAlgebra.norm(p::LatticePoint{2,InfiniteStrip}) = LinearAlgebra.norm(p.coordinates) function LinearAlgebra.norm(p::LatticePoint{2,InfiniteCylinder}) - return min( - sqrt(mod(p.coordinates[1], p.lattice.L)^2 + p.coordinates[2]^2), - sqrt(mod(-p.coordinates[1], p.lattice.L)^2 + p.coordinates[2]^2), - ) + return min(sqrt(mod(p.coordinates[1], p.lattice.L)^2 + p.coordinates[2]^2), + sqrt(mod(-p.coordinates[1], p.lattice.L)^2 + p.coordinates[2]^2)) end function LinearAlgebra.norm(p::LatticePoint{2,InfiniteHelix}) x₁ = mod(p.coordinates[1], p.lattice.L) diff --git a/src/models/hamiltonians.jl b/src/models/hamiltonians.jl index c132bd6..acd3ab9 100644 --- a/src/models/hamiltonians.jl +++ b/src/models/hamiltonians.jl @@ -22,28 +22,22 @@ function transverse_field_ising end function transverse_field_ising(lattice::AbstractLattice; kwargs...) return transverse_field_ising(ComplexF64, Trivial, lattice; kwargs...) end -function transverse_field_ising( - S::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... -) +function transverse_field_ising(S::Type{<:Sector}, + lattice::AbstractLattice=InfiniteChain(1); kwargs...) return transverse_field_ising(ComplexF64, S, lattice; kwargs...) end function transverse_field_ising(T::Type{<:Number}, lattice::AbstractLattice; kwargs...) return transverse_field_ising(T, Trivial, lattice; kwargs...) end -function transverse_field_ising( - T::Type{<:Number}, S::Type{<:Sector}, lattice::AbstractLattice; kwargs... -) - throw( - ArgumentError("`symmetry` must be either `Trivial`, `Z2Irrep` or `FermionParity`") - ) -end -function transverse_field_ising( - T::Type{<:Number}=ComplexF64, - S::Union{Type{Trivial},Type{Z2Irrep}}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - J=1.0, - g=1.0, -) +function transverse_field_ising(T::Type{<:Number}, S::Type{<:Sector}, + lattice::AbstractLattice; kwargs...) + throw(ArgumentError("`symmetry` must be either `Trivial`, `Z2Irrep` or `FermionParity`")) +end +function transverse_field_ising(T::Type{<:Number}=ComplexF64, + S::Union{Type{Trivial},Type{Z2Irrep}}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + J=1.0, + g=1.0,) ZZ = rmul!(σᶻᶻ(T, S), -J) X = rmul!(σˣ(T, S), g * -J) return @mpoham begin @@ -54,9 +48,8 @@ function transverse_field_ising( end end end -function transverse_field_ising( - T::Type{<:Number}, ::Type{fℤ₂}, lattice::AbstractLattice=InfiniteChain(1); J=1.0, g=1.0 -) +function transverse_field_ising(T::Type{<:Number}, ::Type{fℤ₂}, + lattice::AbstractLattice=InfiniteChain(1); J=1.0, g=1.0) twosite = axpby!(-J, c_plusmin(T) + c_minplus(T), J, c_plusplus(T) + c_minmin(T)) onesite = axpby!(2g * J, c_number(T), -g * J, id(Matrix{T}, space(twosite, 1))) @@ -88,13 +81,11 @@ function kitaev_model end function kitaev_model(lattice::AbstractLattice; kwargs...) return kitaev_model(ComplexF64, lattice; kwargs...) end -function kitaev_model( - elt::Type{<:Number}=ComplexF64, - lattice::AbstractLattice=InfiniteChain(1); - t=1.0, - mu=1.0, - Delta=1.0, -) +function kitaev_model(elt::Type{<:Number}=ComplexF64, + lattice::AbstractLattice=InfiniteChain(1); + t=1.0, + mu=1.0, + Delta=1.0,) TB = rmul!(c_plusmin(elt) + c_minplus(elt), -t / 2) # tight-binding term SC = rmul!(c_plusplus(elt) + c_minmin(elt), Delta / 2) # superconducting term CP = rmul!(c_number(elt), -mu) # chemical potential term @@ -130,21 +121,18 @@ function heisenberg_XXX end function heisenberg_XXX(lattice::AbstractLattice; kwargs...) return heisenberg_XXX(ComplexF64, Trivial, lattice; kwargs...) end -function heisenberg_XXX( - symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... -) +function heisenberg_XXX(symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); + kwargs...) return heisenberg_XXX(ComplexF64, symmetry, lattice; kwargs...) end function heisenberg_XXX(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) return heisenberg_XXX(elt, Trivial, lattice; kwargs...) end -function heisenberg_XXX( - T::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - J::Real=1.0, - spin::Real=1, -) +function heisenberg_XXX(T::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + J::Real=1.0, + spin::Real=1,) term = rmul!(S_exchange(T, symmetry; spin=spin), J) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return term{i,j} @@ -166,26 +154,22 @@ function heisenberg_XXZ end function heisenberg_XXZ(lattice::AbstractLattice; kwargs...) return heisenberg_XXZ(ComplexF64, Trivial, lattice; kwargs...) end -function heisenberg_XXZ( - symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... -) +function heisenberg_XXZ(symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); + kwargs...) return heisenberg_XXZ(ComplexF64, symmetry, lattice; kwargs...) end function heisenberg_XXZ(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) return heisenberg_XXZ(elt, Trivial, lattice; kwargs...) end -function heisenberg_XXZ( - elt::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - J=1.0, - Delta=1.0, - spin=1, -) - term = - rmul!(S_xx(elt, symmetry; spin=spin), J) + - rmul!(S_yy(elt, symmetry; spin=spin), J) + - rmul!(S_zz(elt, symmetry; spin=spin), Delta * J) +function heisenberg_XXZ(elt::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + J=1.0, + Delta=1.0, + spin=1,) + term = rmul!(S_xx(elt, symmetry; spin=spin), J) + + rmul!(S_yy(elt, symmetry; spin=spin), J) + + rmul!(S_zz(elt, symmetry; spin=spin), Delta * J) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return term{i,j} end @@ -206,18 +190,15 @@ function heisenberg_XYZ end function heisenberg_XYZ(lattice::AbstractLattice; kwargs...) return heisenberg_XYZ(ComplexF64, lattice; kwargs...) end -function heisenberg_XYZ( - T::Type{<:Number}=ComplexF64, - lattice::AbstractLattice=InfiniteChain(1); - Jx=1.0, - Jy=1.0, - Jz=1.0, - spin=1, -) - term = - rmul!(S_xx(T, Trivial; spin=spin), Jx) + - rmul!(S_yy(T, Trivial; spin=spin), Jy) + - rmul!(S_zz(T, Trivial; spin=spin), Jz) +function heisenberg_XYZ(T::Type{<:Number}=ComplexF64, + lattice::AbstractLattice=InfiniteChain(1); + Jx=1.0, + Jy=1.0, + Jz=1.0, + spin=1,) + term = rmul!(S_xx(T, Trivial; spin=spin), Jx) + + rmul!(S_yy(T, Trivial; spin=spin), Jy) + + rmul!(S_zz(T, Trivial; spin=spin), Jz) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return term{i,j} end @@ -239,24 +220,20 @@ function bilinear_biquadratic_model end function bilinear_biquadratic_model(lattice::AbstractLattice; kwargs...) return bilinear_biquadratic_model(ComplexF64, Trivial, lattice; kwargs...) end -function bilinear_biquadratic_model( - symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... -) +function bilinear_biquadratic_model(symmetry::Type{<:Sector}, + lattice::AbstractLattice=InfiniteChain(1); kwargs...) return bilinear_biquadratic_model(ComplexF64, symmetry, lattice; kwargs...) end -function bilinear_biquadratic_model( - elt::Type{<:Number}, lattice::AbstractLattice; kwargs... -) +function bilinear_biquadratic_model(elt::Type{<:Number}, lattice::AbstractLattice; + kwargs...) return bilinear_biquadratic_model(elt, Trivial, lattice; kwargs...) end -function bilinear_biquadratic_model( - elt::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - spin=1, - J=1.0, - θ=0.0, -) +function bilinear_biquadratic_model(elt::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + spin=1, + J=1.0, + θ=0.0,) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return J * cos(θ) * S_exchange(elt, symmetry; spin=spin){i,j} + J * sin(θ) * (S_exchange(elt, symmetry; spin=spin)^2){i,j} @@ -282,29 +259,24 @@ function quantum_potts end function quantum_potts(lattice::AbstractLattice; kwargs...) return quantum_potts(ComplexF64, Trivial, lattice; kwargs...) end -function quantum_potts( - symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... -) +function quantum_potts(symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); + kwargs...) return quantum_potts(ComplexF64, symmetry, lattice; kwargs...) end function quantum_potts(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) return quantum_potts(elt, Trivial, lattice; kwargs...) end -function quantum_potts( - elt::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - q=3, - J=1.0, - g=1.0, -) - return @mpoham sum( - sum(nearest_neighbours(lattice)) do (i, j) - return -J * (potts_ZZ(elt, symmetry; q)^k){i,j} - end - sum(vertices(lattice)) do i - return g * (potts_field(elt, symmetry; q)^k){i} - end for k in 1:(q - 1) - ) +function quantum_potts(elt::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + q=3, + J=1.0, + g=1.0,) + return @mpoham sum(sum(nearest_neighbours(lattice)) do (i, j) + return -J * (potts_ZZ(elt, symmetry; q)^k){i,j} + end - sum(vertices(lattice)) do i + return g * (potts_field(elt, symmetry; q)^k){i} + end for k in 1:(q - 1)) end #=========================================================================================== @@ -329,35 +301,31 @@ function hubbard_model end function hubbard_model(lattice::AbstractLattice; kwargs...) return hubbard_model(ComplexF64, Trivial, Trivial, lattice; kwargs...) end -function hubbard_model( - particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; kwargs... -) +function hubbard_model(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + kwargs...) return hubbard_model(ComplexF64, particle_symmetry, spin_symmetry; kwargs...) end function hubbard_model(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) return hubbard_model(elt, Trivial, Trivial, lattice; kwargs...) end -function hubbard_model( - T::Type{<:Number}=ComplexF64, - particle_symmetry::Type{<:Sector}=Trivial, - spin_symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - t=1.0, - U=1.0, - mu=0.0, - n::Integer=0, -) - hopping = - e⁺e⁻(T, particle_symmetry, spin_symmetry) + - e⁻e⁺(T, particle_symmetry, spin_symmetry) +function hubbard_model(T::Type{<:Number}=ComplexF64, + particle_symmetry::Type{<:Sector}=Trivial, + spin_symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + t=1.0, + U=1.0, + mu=0.0, + n::Integer=0,) + hopping = e⁺e⁻(T, particle_symmetry, spin_symmetry) + + e⁻e⁺(T, particle_symmetry, spin_symmetry) interaction_term = nꜛnꜜ(T, particle_symmetry, spin_symmetry) N = e_number(T, particle_symmetry, spin_symmetry) return @mpoham begin sum(nearest_neighbours(lattice)) do (i, j) return -t * hopping{i,j} end + sum(vertices(lattice)) do i - return U * interaction_term{i} - mu * N{i} - end + return U * interaction_term{i} - mu * N{i} + end end end @@ -378,23 +346,20 @@ function bose_hubbard_model end function bose_hubbard_model(lattice::AbstractLattice; kwargs...) return bose_hubbard_model(ComplexF64, Trivial, lattice; kwargs...) end -function bose_hubbard_model( - symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); kwargs... -) +function bose_hubbard_model(symmetry::Type{<:Sector}, + lattice::AbstractLattice=InfiniteChain(1); kwargs...) return bose_hubbard_model(ComplexF64, symmetry, lattice; kwargs...) end -function bose_hubbard_model( - elt::Type{<:Number}=ComplexF64, - symmetry::Type{<:Sector}=Trivial, - lattice::AbstractLattice=InfiniteChain(1); - cutoff::Integer=5, - t=1.0, - U=1.0, - mu=0.0, - n::Integer=0, -) - hopping_term = - a_plusmin(elt, symmetry; cutoff=cutoff) + a_minplus(elt, symmetry; cutoff=cutoff) +function bose_hubbard_model(elt::Type{<:Number}=ComplexF64, + symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + cutoff::Integer=5, + t=1.0, + U=1.0, + mu=0.0, + n::Integer=0,) + hopping_term = a_plusmin(elt, symmetry; cutoff=cutoff) + + a_minplus(elt, symmetry; cutoff=cutoff) N = a_number(elt, symmetry; cutoff=cutoff) interaction_term = contract_onesite(N, N - id(domain(N))) @@ -402,8 +367,8 @@ function bose_hubbard_model( sum(nearest_neighbours(lattice)) do (i, j) return -t * hopping_term{i,j} end + sum(vertices(lattice)) do i - return U / 2 * interaction_term{i} - mu * N{i} - end + return U / 2 * interaction_term{i} - mu * N{i} + end end if symmetry === Trivial @@ -418,3 +383,56 @@ function bose_hubbard_model( return H end + +#=========================================================================================== + t-J models +===========================================================================================# + +""" + tj_model([elt::Type{<:Number}], [particle_symmetry::Type{<:Sector}], + [spin_symmetry::Type{<:Sector}], [lattice::AbstractLattice]; + t, J, mu, sf::Bool=false) + +MPO for the hamiltonian of the t-J model, as defined by +```math +H = -t \\sum_{\\langle i,j \\rangle, \\sigma} + (\\tilde{e}^\\dagger_{i,\\sigma} \\tilde{e}_{j,\\sigma} + h.c.) + + J \\sum_{\\langle i,j \\rangle}(\\mathbf{S}_i \\cdot \\mathbf{S}_j - \\frac{1}{4} n_i n_j) + - \\mu \\sum_i n_i +``` +where ``\\tilde{e}_{i,\\sigma}`` is the electron operator with spin ``\\sigma`` restrict to the no-double-occupancy subspace. +""" +function tj_model end +function tj_model(lattice::AbstractLattice; kwargs...) + return tj_model(ComplexF64, Trivial, Trivial, lattice; kwargs...) +end +function tj_model(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + kwargs...) + return tj_model(ComplexF64, particle_symmetry, spin_symmetry; kwargs...) +end +function tj_model(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) + return tj_model(elt, Trivial, Trivial, lattice; kwargs...) +end +function tj_model(T::Type{<:Number}=ComplexF64, + particle_symmetry::Type{<:Sector}=Trivial, + spin_symmetry::Type{<:Sector}=Trivial, + lattice::AbstractLattice=InfiniteChain(1); + t=2.5, + J=1.0, + mu=0.0, + sf::Bool=false,) + hopping = tJ.e_plusmin(T, particle_symmetry, spin_symmetry; sf) + + tJ.e_minplus(T, particle_symmetry, spin_symmetry; sf) + num = tJ.e_number(T, particle_symmetry, spin_symmetry; sf) + heisenberg = tJ.S_exchange(T, particle_symmetry, spin_symmetry; sf) - + (1 / 4) * (num ⊗ num) + return @mpoham begin + sum(nearest_neighbours(lattice)) do (i, j) + return (-t) * hopping{i,j} + J * heisenberg{i,j} + end + sum(vertices(lattice)) do i + return (-mu) * num{i} + end + end +end + +# TODO: add (hardcore) bosonic t-J model (https://arxiv.org/abs/2409.15424) diff --git a/src/models/quantum_chemistry.jl b/src/models/quantum_chemistry.jl index 468c8e3..f00d977 100644 --- a/src/models/quantum_chemistry.jl +++ b/src/models/quantum_chemistry.jl @@ -38,27 +38,25 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) half_basis_size = Int(ceil(basis_size / 2)) # the phsyical space - psp = Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]( - (0, 0, 0) => 1, (1, 1//2, 1) => 1, (2, 0, 0) => 1 - ) - - ap = TensorMap( - ones, - Elt, - psp * Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1//2, 1) => 1), - psp, - ) + psp = Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((0, 0, 0) => 1, + (1, 1 // 2, 1) => 1, + (2, 0, 0) => 1) + + ap = TensorMap(ones, + Elt, + psp * + Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1 // 2, 1) => 1), + psp) blocks(ap)[(U₁(0) ⊠ SU₂(0) ⊠ FermionParity(0))] .*= -sqrt(2) - blocks(ap)[(U₁(1) ⊠ SU₂(1//2) ⊠ FermionParity(1))] .*= 1 - - bm = TensorMap( - ones, - Elt, - psp, - Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1//2, 1) => 1) * psp, - ) + blocks(ap)[(U₁(1) ⊠ SU₂(1 // 2) ⊠ FermionParity(1))] .*= 1 + + bm = TensorMap(ones, + Elt, + psp, + Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1 // 2, 1) => 1) * + psp) blocks(bm)[(U₁(0) ⊠ SU₂(0) ⊠ FermionParity(0))] .*= sqrt(2) - blocks(bm)[(U₁(1) ⊠ SU₂(1//2) ⊠ FermionParity(1))] .*= -1 + blocks(bm)[(U₁(1) ⊠ SU₂(1 // 2) ⊠ FermionParity(1))] .*= -1 # this transposition is easier to reason about in a planar way am = transpose(ap', (2, 1), (3,)) @@ -82,7 +80,7 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) h_pm = TensorMap(ones, Elt, psp, psp) blocks(h_pm)[(U₁(0) ⊠ SU₂(0) ⊠ FermionParity(0))] .= 0 - blocks(h_pm)[(U₁(1) ⊠ SU₂(1//2) ⊠ FermionParity(1))] .= 1 + blocks(h_pm)[(U₁(1) ⊠ SU₂(1 // 2) ⊠ FermionParity(1))] .= 1 blocks(h_pm)[(U₁(2) ⊠ SU₂(0) ⊠ FermionParity(0))] .= 2 @plansor o_derp[-1 -2; -3 -4] := am[-1 1; -3] * ap[1 -2; -4] @@ -162,36 +160,32 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) # indmap_2 onsite part # we need pp, mm, pm - pp_f = isometry( - fuse(_lastspace(ap)' * _lastspace(ap)'), _lastspace(ap)' * _lastspace(ap)' - ) - mm_f = isometry( - fuse(_lastspace(am)' * _lastspace(am)'), _lastspace(am)' * _lastspace(am)' - ) - mp_f = isometry( - fuse(_lastspace(am)' * _lastspace(ap)'), _lastspace(am)' * _lastspace(ap)' - ) - pm_f = isometry( - fuse(_lastspace(ap)' * _lastspace(am)'), _lastspace(ap)' * _lastspace(am)' - ) - - @plansor ut_apap[-1 -2; -3 -4] := - ut[-1] * ap[-3 1; 3] * ap[1 -2; 4] * conj(pp_f[-4; 3 4]) - @plansor ut_amam[-1 -2; -3 -4] := - ut[-1] * am[-3 1; 3] * am[1 -2; 4] * conj(mm_f[-4; 3 4]) - @plansor ut_amap[-1 -2; -3 -4] := - ut[-1] * am[-3 1; 3] * ap[1 -2; 4] * conj(mp_f[-4; 3 4]) - @plansor ut_apam[-1 -2; -3 -4] := - ut[-1] * ap[-3 1; 3] * am[1 -2; 4] * conj(pm_f[-4; 3 4]) - - @plansor bpbp_ut[-1 -2; -3 -4] := - mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) - @plansor bmbm_ut[-1 -2; -3 -4] := - pp_f[-1; 1 2] * bm[1; -3 3] * bm[2; 3 -2] * conj(ut[-4]) - @plansor bmbp_ut[-1 -2; -3 -4] := - pm_f[-1; 1 2] * bm[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) - @plansor bpbm_ut[-1 -2; -3 -4] := - mp_f[-1; 1 2] * bp[1; -3 3] * bm[2; 3 -2] * conj(ut[-4]) + pp_f = isometry(fuse(_lastspace(ap)' * _lastspace(ap)'), + _lastspace(ap)' * _lastspace(ap)') + mm_f = isometry(fuse(_lastspace(am)' * _lastspace(am)'), + _lastspace(am)' * _lastspace(am)') + mp_f = isometry(fuse(_lastspace(am)' * _lastspace(ap)'), + _lastspace(am)' * _lastspace(ap)') + pm_f = isometry(fuse(_lastspace(ap)' * _lastspace(am)'), + _lastspace(ap)' * _lastspace(am)') + + @plansor ut_apap[-1 -2; -3 -4] := ut[-1] * ap[-3 1; 3] * ap[1 -2; 4] * + conj(pp_f[-4; 3 4]) + @plansor ut_amam[-1 -2; -3 -4] := ut[-1] * am[-3 1; 3] * am[1 -2; 4] * + conj(mm_f[-4; 3 4]) + @plansor ut_amap[-1 -2; -3 -4] := ut[-1] * am[-3 1; 3] * ap[1 -2; 4] * + conj(mp_f[-4; 3 4]) + @plansor ut_apam[-1 -2; -3 -4] := ut[-1] * ap[-3 1; 3] * am[1 -2; 4] * + conj(pm_f[-4; 3 4]) + + @plansor bpbp_ut[-1 -2; -3 -4] := mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * + conj(ut[-4]) + @plansor bmbm_ut[-1 -2; -3 -4] := pp_f[-1; 1 2] * bm[1; -3 3] * bm[2; 3 -2] * + conj(ut[-4]) + @plansor bmbp_ut[-1 -2; -3 -4] := pm_f[-1; 1 2] * bm[1; -3 3] * bp[2; 3 -2] * + conj(ut[-4]) + @plansor bpbm_ut[-1 -2; -3 -4] := mp_f[-1; 1 2] * bp[1; -3 3] * bm[2; 3 -2] * + conj(ut[-4]) for i in 1:basis_size if i < half_basis_size @@ -223,23 +217,23 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) iso_pp = isomorphism(_lastspace(ap)', _lastspace(ap)') iso_mm = isomorphism(_lastspace(am)', _lastspace(am)') - @plansor p_ap[-1 -2; -3 -4] := - iso_pp[-1; 1] * τ[1 2; -3 3] * ap[2 -2; 4] * conj(pp_f[-4; 3 4]) - @plansor m_ap[-1 -2; -3 -4] := - iso_mm[-1; 1] * τ[1 2; -3 3] * ap[2 -2; 4] * conj(mp_f[-4; 3 4]) - @plansor p_am[-1 -2; -3 -4] := - iso_pp[-1; 1] * τ[1 2; -3 3] * am[2 -2; 4] * conj(pm_f[-4; 3 4]) - @plansor m_am[-1 -2; -3 -4] := - iso_mm[-1; 1] * τ[1 2; -3 3] * am[2 -2; 4] * conj(mm_f[-4; 3 4]) - - @plansor bp_p[-1 -2; -3 -4] := - bp[2; -3 3] * iso_mm[1; -4] * τ[4 -2; 3 1] * mm_f[-1; 2 4] - @plansor bm_p[-1 -2; -3 -4] := - bm[2; -3 3] * iso_mm[1; -4] * τ[4 -2; 3 1] * pm_f[-1; 2 4] - @plansor bm_m[-1 -2; -3 -4] := - bm[2; -3 3] * iso_pp[1; -4] * τ[4 -2; 3 1] * pp_f[-1; 2 4] - @plansor bp_m[-1 -2; -3 -4] := - bp[2; -3 3] * iso_pp[1; -4] * τ[4 -2; 3 1] * mp_f[-1; 2 4] + @plansor p_ap[-1 -2; -3 -4] := iso_pp[-1; 1] * τ[1 2; -3 3] * ap[2 -2; 4] * + conj(pp_f[-4; 3 4]) + @plansor m_ap[-1 -2; -3 -4] := iso_mm[-1; 1] * τ[1 2; -3 3] * ap[2 -2; 4] * + conj(mp_f[-4; 3 4]) + @plansor p_am[-1 -2; -3 -4] := iso_pp[-1; 1] * τ[1 2; -3 3] * am[2 -2; 4] * + conj(pm_f[-4; 3 4]) + @plansor m_am[-1 -2; -3 -4] := iso_mm[-1; 1] * τ[1 2; -3 3] * am[2 -2; 4] * + conj(mm_f[-4; 3 4]) + + @plansor bp_p[-1 -2; -3 -4] := bp[2; -3 3] * iso_mm[1; -4] * τ[4 -2; 3 1] * + mm_f[-1; 2 4] + @plansor bm_p[-1 -2; -3 -4] := bm[2; -3 3] * iso_mm[1; -4] * τ[4 -2; 3 1] * + pm_f[-1; 2 4] + @plansor bm_m[-1 -2; -3 -4] := bm[2; -3 3] * iso_pp[1; -4] * τ[4 -2; 3 1] * + pp_f[-1; 2 4] + @plansor bp_m[-1 -2; -3 -4] := bp[2; -3 3] * iso_pp[1; -4] * τ[4 -2; 3 1] * + mp_f[-1; 2 4] for i in 1:basis_size, j in (i + 1):basis_size if j < half_basis_size @@ -335,18 +329,18 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) # 2|2 for i in 1:basis_size, j in (i + 1):basis_size # p p | . . m m - @plansor __mm[-1 -2; -3 -4] := - pp_f[-1; 1 2] * bm[1; -3 3] * bm[2; 3 -2] * conj(ut[-4]) + @plansor __mm[-1 -2; -3 -4] := pp_f[-1; 1 2] * bm[1; -3 3] * bm[2; 3 -2] * + conj(ut[-4]) hamdat[j, map_2[1, i, 1, i], end] += V[i, i, j, j] * __mm # m m | p p . . - @plansor __pp[-1 -2; -3 -4] := - mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) + @plansor __pp[-1 -2; -3 -4] := mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * + conj(ut[-4]) hamdat[j, map_2[2, i, 2, i], end] += V[j, j, i, i] * __pp # p m | . p . m - @plansor _p_m[-1 -2; -3 -4] := - mp_f[-1; 1 2] * bp[1; -3 3] * bm[2; 3 -2] * conj(ut[-4]) + @plansor _p_m[-1 -2; -3 -4] := mp_f[-1; 1 2] * bp[1; -3 3] * bm[2; 3 -2] * + conj(ut[-4]) hamdat[j, map_2[2, i, 1, i], end] += V[i, j, i, j] * _p_m hamdat[i, 1, end] -= V[i, j, i, j] * h_pm @@ -472,29 +466,27 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) # (i,j) in map_2, 2 onsite for i in 1:basis_size, j in (i + 1):basis_size, k in (j + 1):basis_size # j i m m - @plansor jimm[-1 -2; -3 -4] := - bm[1; -3 2] * bm[3; 2 -2] * τ[4 5; 1 3] * pp_f[-1; 4 5] * conj(ut[-4]) + @plansor jimm[-1 -2; -3 -4] := bm[1; -3 2] * bm[3; 2 -2] * τ[4 5; 1 3] * + pp_f[-1; 4 5] * conj(ut[-4]) hamdat[k, map_2[1, i, 1, j], end] += V[j, i, k, k] * jimm # i j m m - @plansor ijmm[-1 -2; -3 -4] := - bm[1; -3 2] * - bm[3; 2 -2] * - τ[4 5; 1 3] * - permute(pp_f, (1,), (3, 2))[-1; 4 5] * - conj(ut[-4]) + @plansor ijmm[-1 -2; -3 -4] := bm[1; -3 2] * + bm[3; 2 -2] * + τ[4 5; 1 3] * + permute(pp_f, (1,), (3, 2))[-1; 4 5] * + conj(ut[-4]) hamdat[k, map_2[1, i, 1, j], end] += V[i, j, k, k] * ijmm # j p i m - @plansor jpim[-1 -2; -3 -4] := - bm[1; -3 2] * bp[3; 2 -2] * τ[4 5; 1 3] * mp_f[-1; 4 5] * conj(ut[-4]) + @plansor jpim[-1 -2; -3 -4] := bm[1; -3 2] * bp[3; 2 -2] * τ[4 5; 1 3] * + mp_f[-1; 4 5] * conj(ut[-4]) hamdat[k, map_2[2, i, 1, j], end] += V[j, k, i, k] * jpim # i p j m - @plansor ipjm[-1 -2; -3 -4] := - bm[1; -3 2] * - bp[3; 2 -2] * - τ[4 5; 1 3] * - permute(pm_f, (1,), (3, 2))[-1; 4 5] * - conj(ut[-4]) + @plansor ipjm[-1 -2; -3 -4] := bm[1; -3 2] * + bp[3; 2 -2] * + τ[4 5; 1 3] * + permute(pm_f, (1,), (3, 2))[-1; 4 5] * + conj(ut[-4]) hamdat[k, map_2[1, i, 2, j], end] += V[i, k, j, k] * ipjm # j p m i @@ -505,12 +497,12 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_3[1, i, 2, j], end] += V[i, k, k, j] * ipmj # p p j i - @plansor ppji[-1 -2; -3 -4] := - mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) + @plansor ppji[-1 -2; -3 -4] := mm_f[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * + conj(ut[-4]) hamdat[k, map_2[2, i, 2, j], end] += V[k, k, j, i] * ppji # p p i j - @plansor ppij[-1 -2; -3 -4] := - permute(mm_f, (1,), (3, 2))[-1; 1 2] * bp[1; -3 3] * bp[2; 3 -2] * conj(ut[-4]) + @plansor ppij[-1 -2; -3 -4] := permute(mm_f, (1,), (3, 2))[-1; 1 2] * bp[1; -3 3] * + bp[2; 3 -2] * conj(ut[-4]) hamdat[k, map_2[2, i, 2, j], end] += V[k, k, i, j] * ppij # p . . m @@ -570,8 +562,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[1, i, 1, j], map_4[2, l]] += V[j, i, k, l] * jimR # i j m R - @plansor ijmR[-1 -2; -3 -4] := - permute(pp_f, (1,), (3, 2))[-1; 1 2] * τ[3 2; -4 -2] * bm[1; -3 3] + @plansor ijmR[-1 -2; -3 -4] := permute(pp_f, (1,), (3, 2))[-1; 1 2] * + τ[3 2; -4 -2] * bm[1; -3 3] hamdat[k, map_2[1, i, 1, j], map_4[2, l]] += V[i, j, k, l] * ijmR # j i R m @@ -579,8 +571,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[1, i, 1, j], map_4[2, l]] += V[j, i, l, k] * jiRm # i j R m - @plansor ijRm[-1 -2; -3 -4] := - permute(pp_f, (1,), (3, 2))[-1; 1 2] * τ[1 3; -3 -4] * bm[2; 3 -2] + @plansor ijRm[-1 -2; -3 -4] := permute(pp_f, (1,), (3, 2))[-1; 1 2] * + τ[1 3; -3 -4] * bm[2; 3 -2] hamdat[k, map_2[1, i, 1, j], map_4[2, l]] += V[i, j, l, k] * ijRm # j p i R @@ -588,8 +580,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 1, j], map_4[2, l]] += V[j, k, i, l] * jpiR # i p j R - @plansor ipjR[-1 -2; -3 -4] := - permute(pm_f, (1,), (3, 2))[-1; 1 2] * τ[3 2; -4 -2] * bp[1; -3 3] + @plansor ipjR[-1 -2; -3 -4] := permute(pm_f, (1,), (3, 2))[-1; 1 2] * + τ[3 2; -4 -2] * bp[1; -3 3] hamdat[k, map_2[1, i, 2, j], map_4[2, l]] += V[i, k, j, l] * ipjR # j R i m @@ -597,8 +589,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 1, j], map_4[1, l]] += V[j, l, i, k] * jRim # i R j m - @plansor iRjm[-1 -2; -3 -4] := - permute(pm_f, (1,), (3, 2))[-1; 1 2] * τ[1 3; -3 -4] * bm[2; 3 -2] + @plansor iRjm[-1 -2; -3 -4] := permute(pm_f, (1,), (3, 2))[-1; 1 2] * + τ[1 3; -3 -4] * bm[2; 3 -2] hamdat[k, map_2[1, i, 2, j], map_4[1, l]] += V[i, l, j, k] * iRjm # p j R i @@ -606,8 +598,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 1, j], map_4[2, l]] += V[k, j, l, i] * pjRi # p i R j - @plansor piRj[-1 -2; -3 -4] := - permute(pm_f, (1,), (3, 2))[-1; 1 2] * τ[3 2; -4 -2] * bp[1; -3 3] + @plansor piRj[-1 -2; -3 -4] := permute(pm_f, (1,), (3, 2))[-1; 1 2] * + τ[3 2; -4 -2] * bp[1; -3 3] hamdat[k, map_2[1, i, 2, j], map_4[2, l]] += V[k, i, l, j] * piRj # R j m i @@ -615,8 +607,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 1, j], map_4[1, l]] += V[l, j, k, i] * Rjmi # R i m j - @plansor Rimj[-1 -2; -3 -4] := - permute(pm_f, (1,), (3, 2))[-1; 1 2] * τ[1 3; -3 -4] * bm[2; 3 -2] + @plansor Rimj[-1 -2; -3 -4] := permute(pm_f, (1,), (3, 2))[-1; 1 2] * + τ[1 3; -3 -4] * bm[2; 3 -2] hamdat[k, map_2[1, i, 2, j], map_4[1, l]] += V[l, i, k, j] * Rimj # R p j i @@ -624,8 +616,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 2, j], map_4[1, l]] += V[l, k, j, i] * Rpji # R p i j - @plansor Rpij[-1 -2; -3 -4] := - permute(mm_f, (1,), (3, 2))[-1; 1 2] * τ[1 3; -3 -4] * bp[2; 3 -2] + @plansor Rpij[-1 -2; -3 -4] := permute(mm_f, (1,), (3, 2))[-1; 1 2] * + τ[1 3; -3 -4] * bp[2; 3 -2] hamdat[k, map_2[2, i, 2, j], map_4[1, l]] += V[l, k, i, j] * Rpij # p R j i @@ -633,8 +625,8 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) hamdat[k, map_2[2, i, 2, j], map_4[1, l]] += V[k, l, j, i] * pRji # p R i j - @plansor pRij[-1 -2; -3 -4] := - permute(mm_f, (1,), (3, 2))[-1; 1 2] * τ[3 2; -4 -2] * bp[1; -3 3] + @plansor pRij[-1 -2; -3 -4] := permute(mm_f, (1,), (3, 2))[-1; 1 2] * + τ[3 2; -4 -2] * bp[1; -3 3] hamdat[k, map_2[2, i, 2, j], map_4[1, l]] += V[k, l, i, j] * pRij end diff --git a/src/models/transfermatrices.jl b/src/models/transfermatrices.jl index e62e7fc..84a49b7 100644 --- a/src/models/transfermatrices.jl +++ b/src/models/transfermatrices.jl @@ -17,9 +17,8 @@ function classical_ising end function classical_ising(symmetry::Type{<:Sector}; kwargs...) return classical_ising(ComplexF64, symmetry; kwargs...) end -function classical_ising( - elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; beta=log(1 + sqrt(2)) / 2 -) +function classical_ising(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; + beta=log(1 + sqrt(2)) / 2) t = elt[exp(beta) exp(-beta); exp(-beta) exp(beta)] r = eigen(t) @@ -58,19 +57,16 @@ MPO for the partition function of the two-dimensional six vertex model. """ function sixvertex end sixvertex(symmetry::Type{<:Sector}; kwargs...) = sixvertex(ComplexF64, symmetry; kwargs...) -function sixvertex( - elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; a=1.0, b=1.0, c=1.0 -) - d = elt[ - a 0 0 0 - 0 c b 0 - 0 b c 0 - 0 0 0 a - ] +function sixvertex(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; a=1.0, b=1.0, + c=1.0) + d = elt[a 0 0 0 + 0 c b 0 + 0 b c 0 + 0 0 0 a] return DenseMPO(permute(TensorMap(d, ℂ^2 ⊗ ℂ^2, ℂ^2 ⊗ ℂ^2), ((1, 2), (4, 3)))) end function sixvertex(elt::Type{<:Number}, ::Type{U1Irrep}; a=1.0, b=1.0, c=1.0) - pspace = U1Space(-1//2 => 1, 1//2 => 1) + pspace = U1Space(-1 // 2 => 1, 1 // 2 => 1) mpo = TensorMap(zeros, elt, pspace ⊗ pspace, pspace ⊗ pspace) blocks(mpo)[Irrep[U₁](0)] = [b c; c b] blocks(mpo)[Irrep[U₁](1)] = reshape([a], (1, 1)) @@ -78,7 +74,7 @@ function sixvertex(elt::Type{<:Number}, ::Type{U1Irrep}; a=1.0, b=1.0, c=1.0) return DenseMPO(permute(mpo, ((1, 2), (4, 3)))) end function sixvertex(elt::Type{<:Number}, ::Type{CU1Irrep}; a=1.0, b=1.0, c=1.0) - pspace = CU1Space(1//2 => 1) + pspace = CU1Space(1 // 2 => 1) mpo = TensorMap(zeros, elt, pspace ⊗ pspace, pspace ⊗ pspace) blocks(mpo)[Irrep[CU₁](0, 0)] = reshape([b + c], (1, 1)) blocks(mpo)[Irrep[CU₁](0, 1)] = reshape([-b + c], (1, 1)) @@ -111,15 +107,13 @@ end MPO for the partition function of the two-dimensional discrete clock model with ``q`` states. """ -function qstate_clock( - elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; beta::Number=1.0, q::Integer=3 -) +function qstate_clock(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; + beta::Number=1.0, q::Integer=3) comega(d) = cos(2 * pi * d / q) O = zeros(elt, q, q, q, q) for i in 1:q, j in 1:q, k in 1:q, l in 1:q - O[i, j, k, l] = exp( - beta * (comega(i - j) + comega(j - k) + comega(k - l) + comega(l - i)) - ) + O[i, j, k, l] = exp(beta * + (comega(i - j) + comega(j - k) + comega(k - l) + comega(l - i))) end return DenseMPO(TensorMap(O, ℂ^q * ℂ^q, ℂ^q * ℂ^q)) diff --git a/src/operators/bosonoperators.jl b/src/operators/bosonoperators.jl index 4058489..6960d83 100644 --- a/src/operators/bosonoperators.jl +++ b/src/operators/bosonoperators.jl @@ -93,27 +93,23 @@ end const a⁻ = a_min a_plusmin(symmetry::Type{<:Sector}; kwargs...) = a_plusmin(ComplexF64, symmetry; kwargs...) -function a_plusmin( - elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; cutoff::Integer=5 -) +function a_plusmin(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; + cutoff::Integer=5) return contract_twosite(a⁺(elt; cutoff=cutoff), a⁻(elt; cutoff=cutoff)) end function a_plusmin(elt::Type{<:Number}, ::Type{U1Irrep}; cutoff::Integer=5) - return contract_twosite( - a⁺(elt, U1Irrep; cutoff=cutoff, side=:L), a⁻(elt, U1Irrep; cutoff=cutoff, side=:R) - ) + return contract_twosite(a⁺(elt, U1Irrep; cutoff=cutoff, side=:L), + a⁻(elt, U1Irrep; cutoff=cutoff, side=:R)) end a_minplus(symmetry::Type{<:Sector}; kwargs...) = a_minplus(ComplexF64, symmetry; kwargs...) -function a_minplus( - elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; cutoff::Integer=5 -) +function a_minplus(elt::Type{<:Number}=ComplexF64, ::Type{Trivial}=Trivial; + cutoff::Integer=5) return contract_twosite(a⁻(elt; cutoff=cutoff), a⁺(elt; cutoff=cutoff)) end function a_minplus(elt::Type{<:Number}, ::Type{U1Irrep}; cutoff::Integer=5) - return contract_twosite( - a⁻(elt, U1Irrep; cutoff=cutoff, side=:L), a⁺(elt, U1Irrep; cutoff=cutoff, side=:R) - ) + return contract_twosite(a⁻(elt, U1Irrep; cutoff=cutoff, side=:L), + a⁺(elt, U1Irrep; cutoff=cutoff, side=:R)) end """ diff --git a/src/operators/hubbardoperators.jl b/src/operators/hubbardoperators.jl index cf6c5ab..6b60c9f 100644 --- a/src/operators/hubbardoperators.jl +++ b/src/operators/hubbardoperators.jl @@ -23,44 +23,40 @@ function hubbard_space(::Type{Trivial}=Trivial, ::Type{Trivial}=Trivial) return Vect[FermionParity](0 => 2, 1 => 2) end function hubbard_space(::Type{Trivial}, ::Type{U1Irrep}) - return Vect[FermionParity ⊠ U1Irrep]((0, 0) => 2, (1, 1//2) => 1, (1, -1//2) => 1) + return Vect[FermionParity ⊠ U1Irrep]((0, 0) => 2, (1, 1 // 2) => 1, (1, -1 // 2) => 1) end function hubbard_space(::Type{Trivial}, ::Type{SU2Irrep}) - return Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 2, (1, 1//2) => 1) + return Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 2, (1, 1 // 2) => 1) end function hubbard_space(::Type{U1Irrep}, ::Type{Trivial}) return Vect[FermionParity ⊠ U1Irrep]((0, 0) => 1, (1, 1) => 2, (0, 2) => 1) end function hubbard_space(::Type{U1Irrep}, ::Type{U1Irrep}) - return Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]( - (0, 0, 0) => 1, (1, 1, 1//2) => 1, (1, 1, -1//2) => 1, (0, 2, 0) => 1 - ) + return Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]((0, 0, 0) => 1, (1, 1, 1 // 2) => 1, + (1, 1, -1 // 2) => 1, (0, 2, 0) => 1) end function hubbard_space(::Type{U1Irrep}, ::Type{SU2Irrep}) - return Vect[FermionParity ⊠ U1Irrep ⊠ SU2Irrep]( - (0, 0, 0) => 1, (1, 1, 1//2) => 1, (0, 2, 0) => 1 - ) + return Vect[FermionParity ⊠ U1Irrep ⊠ SU2Irrep]((0, 0, 0) => 1, (1, 1, 1 // 2) => 1, + (0, 2, 0) => 1) end function hubbard_space(::Type{SU2Irrep}, ::Type{Trivial}) - return Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 2, (1, 1//2) => 1) + return Vect[FermionParity ⊠ SU2Irrep]((0, 0) => 2, (1, 1 // 2) => 1) end function hubbard_space(::Type{SU2Irrep}, ::Type{U1Irrep}) - return Vect[FermionParity ⊠ SU2Irrep ⊠ U1Irrep]((0, 0, 0) => 1, (1, 1//2, 1) => 1) + return Vect[FermionParity ⊠ SU2Irrep ⊠ U1Irrep]((0, 0, 0) => 1, (1, 1 // 2, 1) => 1) end function hubbard_space(::Type{SU2Irrep}, ::Type{SU2Irrep}) - return Vect[FermionParity ⊠ SU2Irrep ⊠ SU2Irrep]((1, 1//2, 1//2) => 1) + return Vect[FermionParity ⊠ SU2Irrep ⊠ SU2Irrep]((1, 1 // 2, 1 // 2) => 1) end -function single_site_operator( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector} -) +function single_site_operator(T, particle_symmetry::Type{<:Sector}, + spin_symmetry::Type{<:Sector}) V = hubbard_space(particle_symmetry, spin_symmetry) return TensorMap(zeros, T, V ← V) end -function two_site_operator( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector} -) +function two_site_operator(T, particle_symmetry::Type{<:Sector}, + spin_symmetry::Type{<:Sector}) V = hubbard_space(particle_symmetry, spin_symmetry) return TensorMap(zeros, T, V ⊗ V ← V ⊗ V) end @@ -92,10 +88,10 @@ end function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}) t = two_site_operator(T, U1Irrep, U1Irrep) I = sectortype(t) - t[(I(1, 1, 1//2), I(0, 0, 0), dual(I(0, 0, 0)), dual(I(1, 1, 1//2)))] .= 1 - t[(I(1, 1, 1//2), I(1, 1, -1//2), dual(I(0, 0, 0)), dual(I(0, 2, 0)))] .= 1 - t[(I(0, 2, 0), I(0, 0, 0), dual(I(1, 1, -1//2)), dual(I(1, 1, 1//2)))] .= -1 - t[(I(0, 2, 0), I(1, 1, -1//2), dual(I(1, 1, -1//2)), dual(I(0, 2, 0)))] .= -1 + t[(I(1, 1, 1 // 2), I(0, 0, 0), dual(I(0, 0, 0)), dual(I(1, 1, 1 // 2)))] .= 1 + t[(I(1, 1, 1 // 2), I(1, 1, -1 // 2), dual(I(0, 0, 0)), dual(I(0, 2, 0)))] .= 1 + t[(I(0, 2, 0), I(0, 0, 0), dual(I(1, 1, -1 // 2)), dual(I(1, 1, 1 // 2)))] .= -1 + t[(I(0, 2, 0), I(1, 1, -1 // 2), dual(I(1, 1, -1 // 2)), dual(I(0, 2, 0)))] .= -1 return t end function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}) @@ -139,10 +135,10 @@ end function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}) t = two_site_operator(T, U1Irrep, U1Irrep) I = sectortype(t) - t[(I(1, 1, -1//2), I(0, 0, 0), dual(I(0, 0, 0)), dual(I(1, 1, -1//2)))] .= 1 - t[(I(1, 1, -1//2), I(1, 1, 1//2), dual(I(0, 0, 0)), dual(I(0, 2, 0)))] .= -1 - t[(I(0, 2, 0), I(0, 0, 0), dual(I(1, 1, 1//2)), dual(I(1, 1, -1//2)))] .= 1 - t[(I(0, 2, 0), I(1, 1, 1//2), dual(I(1, 1, 1//2)), dual(I(0, 2, 0)))] .= -1 + t[(I(1, 1, -1 // 2), I(0, 0, 0), dual(I(0, 0, 0)), dual(I(1, 1, -1 // 2)))] .= 1 + t[(I(1, 1, -1 // 2), I(1, 1, 1 // 2), dual(I(0, 0, 0)), dual(I(0, 2, 0)))] .= -1 + t[(I(0, 2, 0), I(0, 0, 0), dual(I(1, 1, 1 // 2)), dual(I(1, 1, -1 // 2)))] .= 1 + t[(I(0, 2, 0), I(1, 1, 1 // 2), dual(I(1, 1, 1 // 2)), dual(I(0, 2, 0)))] .= -1 return t end function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}) @@ -195,16 +191,16 @@ end function e_plusmin(T, ::Type{U1Irrep}, ::Type{SU2Irrep}) t = two_site_operator(T, U1Irrep, SU2Irrep) I = sectortype(t) - 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))) + 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 - f3 = only(fusiontrees((I(1, 1, 1//2), I(0, 2, 0)), I(1, 3, 1//2))) - f4 = only(fusiontrees((I(0, 2, 0), I(1, 1, 1//2)), I(1, 3, 1//2))) + f3 = only(fusiontrees((I(1, 1, 1 // 2), I(0, 2, 0)), I(1, 3, 1 // 2))) + f4 = only(fusiontrees((I(0, 2, 0), I(1, 1, 1 // 2)), I(1, 3, 1 // 2))) t[f3, f4] .= -1 f5 = only(fusiontrees((I(0, 0, 0), I(0, 2, 0)), I(0, 2, 0))) - f6 = only(fusiontrees((I(1, 1, 1//2), I(1, 1, 1//2)), I(0, 2, 0))) + f6 = only(fusiontrees((I(1, 1, 1 // 2), I(1, 1, 1 // 2)), I(0, 2, 0))) t[f5, f6] .= sqrt(2) - f7 = only(fusiontrees((I(1, 1, 1//2), I(1, 1, 1//2)), I(0, 2, 0))) + f7 = only(fusiontrees((I(1, 1, 1 // 2), I(1, 1, 1 // 2)), I(0, 2, 0))) f8 = only(fusiontrees((I(0, 2, 0), I(0, 0, 0)), I(0, 2, 0))) t[f7, f8] .= sqrt(2) return t @@ -248,7 +244,7 @@ end function e_number_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}) t = single_site_operator(T, U1Irrep, U1Irrep) I = sectortype(t) - block(t, I(1, 1, 1//2)) .= 1 + block(t, I(1, 1, 1 // 2)) .= 1 block(t, I(0, 2, 0)) .= 1 return t end @@ -291,7 +287,7 @@ end function e_number_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}) t = single_site_operator(T, U1Irrep, U1Irrep) I = sectortype(t) - block(t, I(1, 1, -1//2)) .= 1 + block(t, I(1, 1, -1 // 2)) .= 1 block(t, I(0, 2, 0)) .= 1 return t end @@ -322,7 +318,7 @@ end function e_number(T, ::Type{U1Irrep}, ::Type{SU2Irrep}) t = single_site_operator(T, U1Irrep, SU2Irrep) I = sectortype(t) - block(t, I(1, 1, 1//2)) .= 1 + block(t, I(1, 1, 1 // 2)) .= 1 block(t, I(0, 2, 0)) .= 2 return t end @@ -334,9 +330,8 @@ const n = e_number Return the one-body operator that counts the number of doubly occupied sites. """ e_number_updown(P::Type{<:Sector}, S::Type{<:Sector}) = e_number_updown(ComplexF64, P, S) -function e_number_updown( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector} -) +function e_number_updown(T, particle_symmetry::Type{<:Sector}, + spin_symmetry::Type{<:Sector}) return e_number_up(T, particle_symmetry, spin_symmetry) * e_number_down(T, particle_symmetry, spin_symmetry) end diff --git a/src/operators/localoperators.jl b/src/operators/localoperators.jl index 3c779a7..9e99b1e 100644 --- a/src/operators/localoperators.jl +++ b/src/operators/localoperators.jl @@ -11,9 +11,9 @@ operator is represented as a vector of `MPOTensor`s, each of which acts on a sin struct LocalOperator{T<:AbstractTensorMap{<:Any,2,2},G<:LatticePoint} opp::Vector{T} inds::Vector{G} - function LocalOperator{T,G}( - O::Vector{T}, inds::Vector{G} - ) where {T<:AbstractTensorMap{<:Any,2,2},G<:LatticePoint} + function LocalOperator{T,G}(O::Vector{T}, + inds::Vector{G}) where {T<:AbstractTensorMap{<:Any,2,2}, + G<:LatticePoint} length(O) == length(inds) || throw(ArgumentError("number of operators and indices should be the same")) issorted(inds) && allunique(inds) || @@ -24,9 +24,8 @@ struct LocalOperator{T<:AbstractTensorMap{<:Any,2,2},G<:LatticePoint} end end -function LocalOperator( - t::AbstractTensorMap{<:Any,N,N}, inds::Vararg{G,N} -) where {N,G<:LatticePoint} +function LocalOperator(t::AbstractTensorMap{<:Any,N,N}, + inds::Vararg{G,N}) where {N,G<:LatticePoint} p = TupleTools.sortperm(linearize_index.(inds)) t = permute(t, (p, p .+ N)) t_mpo = collect(MPSKit.decompose_localmpo(MPSKit.add_util_leg(t))) @@ -86,31 +85,26 @@ function Base.:*(a::LocalOperator{T₁,G}, b::LocalOperator{T₂,G}) where {T₁ right_vspace_A = isnothing(i_A) ? left_vspace_A : space(a.opp[i_A], 4)' right_vspace_B = isnothing(i_B) ? left_vspace_B : space(b.opp[i_B], 4)' - left_fuse = unitary( - M, fuse(left_vspace_B, left_vspace_A), left_vspace_B ⊗ left_vspace_A - ) - right_fuse = unitary( - M, fuse(right_vspace_B, right_vspace_A), right_vspace_B ⊗ right_vspace_A - ) + left_fuse = unitary(M, fuse(left_vspace_B, left_vspace_A), + left_vspace_B ⊗ left_vspace_A) + right_fuse = unitary(M, fuse(right_vspace_B, right_vspace_A), + right_vspace_B ⊗ right_vspace_A) if !isnothing(i_A) && !isnothing(i_B) - @plansor operators[i][-1 -2; -3 -4] := - b.opp[i_B][1 2; -3 4] * - a.opp[i_A][3 -2; 2 5] * - left_fuse[-1; 1 3] * - conj(right_fuse[-4; 4 5]) + @plansor operators[i][-1 -2; -3 -4] := b.opp[i_B][1 2; -3 4] * + a.opp[i_A][3 -2; 2 5] * + left_fuse[-1; 1 3] * + conj(right_fuse[-4; 4 5]) elseif !isnothing(i_A) - @plansor operators[i][-1 -2; -3 -4] := - τ[1 2; -3 4] * - a.opp[i_A][3 -2; 2 5] * - left_fuse[-1; 1 3] * - conj(right_fuse[-4; 4 5]) + @plansor operators[i][-1 -2; -3 -4] := τ[1 2; -3 4] * + a.opp[i_A][3 -2; 2 5] * + left_fuse[-1; 1 3] * + conj(right_fuse[-4; 4 5]) elseif !isnothing(i_B) - @plansor operators[i][-1 -2; -3 -4] := - b.opp[i_B][1 2; -3 4] * - τ[3 -2; 2 5] * - left_fuse[-1; 1 3] * - conj(right_fuse[-4; 4 5]) + @plansor operators[i][-1 -2; -3 -4] := b.opp[i_B][1 2; -3 4] * + τ[3 -2; 2 5] * + left_fuse[-1; 1 3] * + conj(right_fuse[-4; 4 5]) else error("this should not happen") end diff --git a/src/operators/mpoham.jl b/src/operators/mpoham.jl index 24d2ab9..35d2fe6 100644 --- a/src/operators/mpoham.jl +++ b/src/operators/mpoham.jl @@ -58,16 +58,16 @@ addoperations(ex) = ex import MPSKit: MPOHamiltonian MPSKitModels.MPOHamiltonian(args...) = MPSKit.MPOHamiltonian(args...) -function _find_free_channel( - data::Array{Union{E,T},3}, loc -)::Tuple{Int,Array{Union{E,T},3}} where {E<:Number,T<:AbstractTensorMap} +function _find_free_channel(data::Array{Union{E,T},3}, + loc)::Tuple{Int, + Array{Union{E,T},3}} where {E<:Number, + T<:AbstractTensorMap} hit = findfirst(map(x -> _is_free_channel(data, loc, x), 2:(size(data, 2) - 1))) #hit = findfirst(ismissing.(data[loc,1,2:end-1])); if isnothing(hit) - ndata = fill!( - Array{Union{E,T},3}(undef, size(data, 1), size(data, 2) + 1, size(data, 2) + 1), - zero(E), - ) + ndata = fill!(Array{Union{E,T},3}(undef, size(data, 1), size(data, 2) + 1, + size(data, 2) + 1), + zero(E)) ndata[:, 1:(end - 1), 1:(end - 2)] .= data[:, :, 1:(end - 1)] ndata[:, 1:(end - 2), end] .= data[:, 1:(end - 1), end] ndata[:, end, end] .= data[:, end, end] diff --git a/src/operators/spinoperators.jl b/src/operators/spinoperators.jl index 57097d1..6ccdd27 100644 --- a/src/operators/spinoperators.jl +++ b/src/operators/spinoperators.jl @@ -6,10 +6,8 @@ end function _pauliterm(spin, i::U1Irrep, j::U1Irrep) -spin <= i.charge <= spin || return 0.0 -spin <= j.charge <= spin || return 0.0 - return sqrt( - (spin + 1) * (i.charge + j.charge + 2 * spin + 1) - - (i.charge + spin + 1) * (j.charge + spin + 1), - ) / 2.0 + return sqrt((spin + 1) * (i.charge + j.charge + 2 * spin + 1) - + (i.charge + spin + 1) * (j.charge + spin + 1)) / 2.0 end """ @@ -59,14 +57,14 @@ S_x(; kwargs...) = S_x(ComplexF64, Trivial; kwargs...) S_x(elt::Type{<:Number}; kwargs...) = S_x(elt, Trivial; kwargs...) S_x(symm::Type{<:Sector}; kwargs...) = S_x(ComplexF64, symm; kwargs...) -function S_x(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) +function S_x(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) S_x_mat, _, _ = spinmatrices(spin, elt) pspace = ComplexSpace(size(S_x_mat, 1)) return TensorMap(S_x_mat, pspace ← pspace) end -function S_x(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2) - spin == 1//2 || error("not implemented") +function S_x(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2) + spin == 1 // 2 || error("not implemented") pspace = Z2Space(0 => 1, 1 => 1) X = TensorMap(zeros, elt, pspace, pspace) blocks(X)[Z2Irrep(0)] .= one(elt) / 2 @@ -74,7 +72,7 @@ function S_x(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2) return X end -function S_x(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2, side=:L) +function S_x(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2, side=:L) pspace = U1Space(i => 1 for i in (-spin):spin) vspace = U1Space(1 => 1, -1 => 1) if side == :L @@ -117,14 +115,14 @@ S_y(; kwargs...) = S_y(ComplexF64, Trivial; kwargs...) S_y(elt::Type{<:Complex}; kwargs...) = S_y(elt, Trivial; kwargs...) S_y(symm::Type{<:Sector}; kwargs...) = S_y(ComplexF64, symm; kwargs...) -function S_y(elt::Type{<:Complex}, ::Type{Trivial}; spin=1//2) +function S_y(elt::Type{<:Complex}, ::Type{Trivial}; spin=1 // 2) _, Y, _, _ = spinmatrices(spin, elt) pspace = ComplexSpace(size(Y, 1)) return TensorMap(Y, pspace ← pspace) end -function S_y(elt::Type{<:Complex}, ::Type{Z2Irrep}; spin=1//2, side=:L) - spin == 1//2 || error("not implemented") +function S_y(elt::Type{<:Complex}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) + spin == 1 // 2 || error("not implemented") pspace = Z2Space(0 => 1, 1 => 1) vspace = Z2Space(1 => 1) if side == :L @@ -141,7 +139,7 @@ function S_y(elt::Type{<:Complex}, ::Type{Z2Irrep}; spin=1//2, side=:L) return Y end -function S_y(elt::Type{<:Complex}, ::Type{U1Irrep}; spin=1//2, side=:L) +function S_y(elt::Type{<:Complex}, ::Type{U1Irrep}; spin=1 // 2, side=:L) pspace = U1Space(i => 1 for i in (-spin):spin) vspace = U1Space(1 => 1, -1 => 1) if side == :L @@ -189,14 +187,14 @@ S_z(; kwargs...) = S_z(ComplexF64, Trivial; kwargs...) S_z(elt::Type{<:Number}; kwargs...) = S_z(elt, Trivial; kwargs...) S_z(symm::Type{<:Sector}; kwargs...) = S_z(ComplexF64, symm; kwargs...) -function S_z(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) +function S_z(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) _, _, S_z_mat = spinmatrices(spin, elt) pspace = ComplexSpace(size(S_z_mat, 1)) return TensorMap(S_z_mat, pspace ← pspace) end -function S_z(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) - spin == 1//2 || error("Z2 symmetry only implemented for spin 1 // 2") +function S_z(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) + spin == 1 // 2 || error("Z2 symmetry only implemented for spin 1 // 2") pspace = Z2Space(0 => 1, 1 => 1) vspace = Z2Space(1 => 1) if side == :L @@ -213,7 +211,7 @@ function S_z(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) return Z end -function S_z(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2) +function S_z(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2) charges = U1Irrep.((-spin):spin) pspace = U1Space((v => 1 for v in charges)) Z = TensorMap(zeros, elt, pspace ← pspace) @@ -241,13 +239,13 @@ S_plus(; kwargs...) = S_plus(ComplexF64, Trivial; kwargs...) S_plus(elt::Type{<:Number}; kwargs...) = S_plus(elt, Trivial; kwargs...) S_plus(symm::Type{<:Sector}; kwargs...) = S_plus(ComplexF64, symm; kwargs...) -function S_plus(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) +function S_plus(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) S⁺ = S_x(elt, Trivial; spin=spin) + 1im * S_y(complex(elt), Trivial; spin=spin) return elt <: Real ? real(S⁺) : S⁺ end -function S_plus(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) - spin == 1//2 || error("Z2 symmetry only implemented for spin 1 // 2") +function S_plus(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) + spin == 1 // 2 || error("Z2 symmetry only implemented for spin 1 // 2") pspace = Z2Space(0 => 1, 1 => 1) vspace = Z2Space(0 => 1, 1 => 1) if side == :L @@ -264,7 +262,7 @@ function S_plus(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) return S⁺ end -function S_plus(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2, side=:L) +function S_plus(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2, side=:L) pspace = U1Space(i => 1 for i in (-spin):spin) if side == :L vspace = U1Space(1 => 1) @@ -302,13 +300,13 @@ S_min(; kwargs...) = S_min(ComplexF64, Trivial; kwargs...) S_min(elt::Type{<:Number}; kwargs...) = S_min(elt, Trivial; kwargs...) S_min(symm::Type{<:Sector}; kwargs...) = S_min(ComplexF64, symm; kwargs...) -function S_min(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) +function S_min(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) S⁻ = S_x(elt, Trivial; spin=spin) - 1im * S_y(complex(elt), Trivial; spin=spin) return elt <: Real ? real(S⁻) : S⁻ end -function S_min(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) - spin == 1//2 || error("Z2 symmetry only implemented for spin 1 // 2") +function S_min(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2, side=:L) + spin == 1 // 2 || error("Z2 symmetry only implemented for spin 1 // 2") pspace = Z2Space(0 => 1, 1 => 1) vspace = Z2Space(0 => 1, 1 => 1) if side == :L @@ -325,7 +323,7 @@ function S_min(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2, side=:L) return S⁻ end -function S_min(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2, side=:L) +function S_min(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2, side=:L) pspace = U1Space(i => 1 for i in (-spin):spin) if side == :L vspace = U1Space(-1 => 1) @@ -380,17 +378,14 @@ for (L, R) in ((:x, :x), (:y, :y), (:z, :z), (:plus, :min), (:min, :plus)) ($f)(elt::Type{<:Number}; kwargs...) = ($f)(elt, Trivial; kwargs...) ($f)(symmetry::Type{<:Sector}; kwargs...) = ($f)(ComplexF64, symmetry; kwargs...) - function ($f)(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) - return contract_twosite( - $(fₗ)(elt, Trivial; spin=spin), $(fᵣ)(elt, Trivial; spin=spin) - ) + function ($f)(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) + return contract_twosite($(fₗ)(elt, Trivial; spin=spin), + $(fᵣ)(elt, Trivial; spin=spin)) end - function ($f)(elt::Type{<:Number}, symmetry::Type{<:Sector}; spin=1//2) - return contract_twosite( - $(fₗ)(elt, symmetry; spin=spin, side=:L), - $(fᵣ)(elt, symmetry; spin=spin, side=:R), - ) + function ($f)(elt::Type{<:Number}, symmetry::Type{<:Sector}; spin=1 // 2) + return contract_twosite($(fₗ)(elt, symmetry; spin=spin, side=:L), + $(fᵣ)(elt, symmetry; spin=spin, side=:R)) end const $f_unicode = $f @@ -401,10 +396,10 @@ for (L, R) in ((:x, :x), (:y, :y), (:z, :z), (:plus, :min), (:min, :plus)) end end -function S_xx(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1//2) +function S_xx(elt::Type{<:Number}, ::Type{Z2Irrep}; spin=1 // 2) return contract_twosite(S_x(elt, Z2Irrep; spin=spin), S_x(elt, Z2Irrep; spin=spin)) end -function S_zz(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1//2) +function S_zz(elt::Type{<:Number}, ::Type{U1Irrep}; spin=1 // 2) return contract_twosite(S_z(elt, U1Irrep; spin=spin), S_z(elt, U1Irrep; spin=spin)) end @@ -423,13 +418,13 @@ function S_exchange(symmetry::Type{<:Sector}; kwargs...) return S_exchange(ComplexF64, symmetry; kwargs...) end -function S_exchange(elt::Type{<:Number}, ::Type{Trivial}; spin=1//2) +function S_exchange(elt::Type{<:Number}, ::Type{Trivial}; spin=1 // 2) return S_xx(elt, Trivial; spin=spin) + S_yy(elt, Trivial; spin=spin) + S_zz(elt, Trivial; spin=spin) end -function S_exchange(elt::Type{<:Number}, ::Type{SU2Irrep}; spin=1//2) +function S_exchange(elt::Type{<:Number}, ::Type{SU2Irrep}; spin=1 // 2) pspace = SU2Space(spin => 1) aspace = SU2Space(1 => 1) @@ -440,7 +435,7 @@ function S_exchange(elt::Type{<:Number}, ::Type{SU2Irrep}; spin=1//2) return SS end -function S_exchange(elt::Type{<:Number}, symmetry::Type{<:Sector}; spin=1//2) +function S_exchange(elt::Type{<:Number}, symmetry::Type{<:Sector}; spin=1 // 2) return (S_plusmin(elt, symmetry; spin=spin) + S_minplus(elt, symmetry; spin=spin)) / 2 + S_zz(elt, symmetry; spin=spin) end diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index 648e45b..c99e85f 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -36,9 +36,9 @@ function tj_space(::Type{Trivial}=Trivial, ::Type{Trivial}=Trivial; sf::Bool=fal end function tj_space(::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) return if sf - Vect[FermionParity ⊠ U1Irrep]((1, 0) => 1, (0, 1//2) => 1, (0, -1//2) => 1) + Vect[FermionParity ⊠ U1Irrep]((1, 0) => 1, (0, 1 // 2) => 1, (0, -1 // 2) => 1) else - Vect[FermionParity ⊠ U1Irrep]((0, 0) => 1, (1, 1//2) => 1, (1, -1//2) => 1) + Vect[FermionParity ⊠ U1Irrep]((0, 0) => 1, (1, 1 // 2) => 1, (1, -1 // 2) => 1) end end function tj_space(::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) @@ -53,30 +53,26 @@ function tj_space(::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) end function tj_space(::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) return if sf - Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]( - (1, 0, 0) => 1, (0, 1, 1//2) => 1, (0, 1, -1//2) => 1 - ) + Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]((1, 0, 0) => 1, (0, 1, 1 // 2) => 1, + (0, 1, -1 // 2) => 1) else - Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]( - (0, 0, 0) => 1, (1, 1, 1//2) => 1, (1, 1, -1//2) => 1 - ) + Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]((0, 0, 0) => 1, (1, 1, 1 // 2) => 1, + (1, 1, -1 // 2) => 1) end end function tj_space(::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) return error("Not implemented") end -function single_site_operator( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - V = tj_space(particle_symmetry, spin_symmetry; sf=sf) +function single_site_operator(T, particle_symmetry::Type{<:Sector}, + spin_symmetry::Type{<:Sector}; sf::Bool=false) + V = tj_space(particle_symmetry, spin_symmetry; sf) return TensorMap(zeros, T, V ← V) end -function two_site_operator( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - V = tj_space(particle_symmetry, spin_symmetry; sf=sf) +function two_site_operator(T, particle_symmetry::Type{<:Sector}, + spin_symmetry::Type{<:Sector}; sf::Bool=false) + V = tj_space(particle_symmetry, spin_symmetry; sf) return TensorMap(zeros, T, V ⊗ V ← V ⊗ V) end @@ -86,10 +82,10 @@ end Return the two-body operator that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. The only nonzero matrix element corresponds to `|↑0⟩ <-- |0↑⟩`. """ -e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_plusmin_up(ComplexF64, P, S; sf=sf) +e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin_up(ComplexF64, + P, S; sf) function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, Trivial, Trivial; sf=sf) + t = two_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) #= The extra minus sign in slave-fermion basis: @@ -103,10 +99,10 @@ function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) return t end function e_plusmin_up(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, Trivial, U1Irrep; sf=sf) + t = two_site_operator(T, Trivial, U1Irrep; sf) I = sectortype(t) (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) - t[(I(b, 1//2), I(h, 0), dual(I(h, 0)), dual(I(b, 1//2)))] .= sgn * 1 + t[(I(b, 1 // 2), I(h, 0), dual(I(h, 0)), dual(I(b, 1 // 2)))] .= sgn * 1 return t end function e_plusmin_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) @@ -129,20 +125,21 @@ const e⁺e⁻ꜛ = e_plusmin_up Return the two-body operator that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. The only nonzero matrix element corresponds to `|↓0⟩ <-- |0↓⟩`. """ -e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_plusmin_down(ComplexF64, P, S; sf=sf) +e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin_down(ComplexF64, + P, S; + sf) function e_plusmin_down(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, Trivial, Trivial; sf=sf) + t = two_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) t[(I(b), I(h), dual(I(h)), dual(I(b)))][2, 1, 1, 2] = sgn * 1 return t end function e_plusmin_down(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, Trivial, U1Irrep; sf=sf) + t = two_site_operator(T, Trivial, U1Irrep; sf) I = sectortype(t) (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) - t[(I(b, -1//2), I(h, 0), dual(I(h, 0)), dual(I(b, -1//2)))] .= sgn * 1 + t[(I(b, -1 // 2), I(h, 0), dual(I(h, 0)), dual(I(b, -1 // 2)))] .= sgn * 1 return t end function e_plusmin_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) @@ -165,12 +162,11 @@ const e⁺e⁻ꜜ = e_plusmin_down Return the two-body operator that annihilates a spin-up electron at the first site and creates a spin-up electron at the second. The only nonzero matrix element corresponds to `|0↑⟩ <-- |↑0⟩`. """ -e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_minplus_up(ComplexF64, P, S; sf=sf) -function e_minplus_up( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - return copy(adjoint(e_plusmin_up(T, particle_symmetry, spin_symmetry; sf=sf))) +e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minplus_up(ComplexF64, + P, S; sf) +function e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return copy(adjoint(e_plusmin_up(T, particle_symmetry, spin_symmetry; sf))) end const e⁻⁺ꜛ = e_minplus_up @@ -180,12 +176,12 @@ const e⁻⁺ꜛ = e_minplus_up Return the two-body operator that annihilates a spin-down electron at the first site and creates a spin-down electron at the second. The only nonzero matrix element corresponds to `|0↓⟩ <-- |↓0⟩`. """ -e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_minplus_down(ComplexF64, P, S; sf=sf) -function e_minplus_down( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - return copy(adjoint(e_plusmin_down(T, particle_symmetry, spin_symmetry; sf=sf))) +e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minplus_down(ComplexF64, + P, S; + sf) +function e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return copy(adjoint(e_plusmin_down(T, particle_symmetry, spin_symmetry; sf))) end const e⁻e⁺ꜜ = e_minplus_down @@ -195,13 +191,12 @@ const e⁻e⁺ꜜ = e_minplus_down Return the two-body operator that creates a particle at the first site and annihilates a particle at the second. This is the sum of `e_plusmin_up` and `e_plusmin_down`. """ -e_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_plusmin(ComplexF64, P, S; sf=sf) -function e_plusmin( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - return e_plusmin_up(T, particle_symmetry, spin_symmetry; sf=sf) + - e_plusmin_down(T, particle_symmetry, spin_symmetry; sf=sf) +e_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin(ComplexF64, P, + S; sf) +function e_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return e_plusmin_up(T, particle_symmetry, spin_symmetry; sf) + + e_plusmin_down(T, particle_symmetry, spin_symmetry; sf) end const e⁺e⁻ = e_plusmin @@ -211,12 +206,11 @@ const e⁺e⁻ = e_plusmin Return the two-body operator that annihilates a particle at the first site and creates a particle at the second. This is the sum of `e_minplus_up` and `e_minplus_down`. """ -e_minplus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_minplus(ComplexF64, P, S; sf=sf) -function e_minplus( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - return copy(adjoint(e_plusmin(T, particle_symmetry, spin_symmetry; sf=sf))) +e_minplus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minplus(ComplexF64, P, + S; sf) +function e_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return copy(adjoint(e_plusmin(T, particle_symmetry, spin_symmetry; sf))) end const e⁻e⁺ = e_minplus @@ -225,20 +219,20 @@ const e⁻e⁺ = e_minplus Return the one-body operator that counts the number of spin-up electrons. """ -e_number_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_number_up(ComplexF64, P, S; sf=sf) +e_number_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_number_up(ComplexF64, + P, S; sf) function e_number_up(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf=sf) + t = single_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) b = sf ? 0 : 1 t[(I(b), dual(I(b)))][1, 1] = 1 return t end function e_number_up(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, Trivial, U1Irrep; sf=sf) + t = single_site_operator(T, Trivial, U1Irrep; sf) I = sectortype(t) b = sf ? 0 : 1 - t[(I(b, 1//2), dual(I(b, 1//2)))][1, 1] = 1 + t[(I(b, 1 // 2), dual(I(b, 1 // 2)))][1, 1] = 1 return t end function e_number_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) @@ -260,20 +254,21 @@ const nꜛ = e_number_up Return the one-body operator that counts the number of spin-down electrons. """ -e_number_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_number_down(ComplexF64, P, S; sf=sf) +e_number_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_number_down(ComplexF64, + P, S; + sf) function e_number_down(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf=sf) + t = single_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) b = sf ? 0 : 1 t[(I(b), dual(I(b)))][2, 2] = 1 return t end function e_number_down(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, Trivial, U1Irrep; sf=sf) + t = single_site_operator(T, Trivial, U1Irrep; sf) I = sectortype(t) b = sf ? 0 : 1 - t[(I(b, -1//2), dual(I(b, -1//2)))][1, 1] = 1 + t[(I(b, -1 // 2), dual(I(b, -1 // 2)))][1, 1] = 1 return t end function e_number_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) @@ -295,13 +290,12 @@ const nꜜ = e_number_down Return the one-body operator that counts the number of particles. """ -e_number(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - e_number(ComplexF64, P, S; sf=sf) -function e_number( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - return e_number_up(T, particle_symmetry, spin_symmetry; sf=sf) + - e_number_down(T, particle_symmetry, spin_symmetry; sf=sf) +e_number(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_number(ComplexF64, P, S; + sf) +function e_number(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return e_number_up(T, particle_symmetry, spin_symmetry; sf) + + e_number_down(T, particle_symmetry, spin_symmetry; sf) end const n = e_number @@ -310,10 +304,10 @@ const n = e_number Return the one-body spin-1/2 x-operator on the electrons. """ -S_x(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_x(ComplexF64, P, S; sf=sf) -S_x(; sf::Bool=false) = S_x(ComplexF64, Trivial, Trivial; sf=sf) +S_x(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_x(ComplexF64, P, S; sf) +S_x(; sf::Bool=false) = S_x(ComplexF64, Trivial, Trivial; sf) function S_x(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf=sf) + t = single_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) b = sf ? 0 : 1 t[(I(b), dual(I(b)))][1, 2] = 0.5 @@ -326,10 +320,10 @@ end Return the one-body spin-1/2 x-operator on the electrons (only defined for `Trivial` symmetry). """ -S_y(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_y(ComplexF64, P, S; sf=sf) -S_y(; sf::Bool=false) = S_y(ComplexF64, Trivial, Trivial; sf=sf) +S_y(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_y(ComplexF64, P, S; sf) +S_y(; sf::Bool=false) = S_y(ComplexF64, Trivial, Trivial; sf) function S_y(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf=sf) + t = single_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) b = sf ? 0 : 1 t[(I(b), dual(I(b)))][1, 2] = -0.5im @@ -342,10 +336,10 @@ end Return the one-body spin-1/2 z-operator on the electrons. """ -S_z(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_z(ComplexF64, P, S; sf=sf) -S_z(; sf::Bool=false) = S_z(ComplexF64, Trivial, Trivial; sf=sf) +S_z(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_z(ComplexF64, P, S; sf) +S_z(; sf::Bool=false) = S_z(ComplexF64, Trivial, Trivial; sf) function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf=sf) + t = single_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) b = sf ? 0 : 1 t[(I(b), dual(I(b)))][1, 1] = 0.5 @@ -353,11 +347,11 @@ function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false return t end function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, Trivial, U1Irrep; sf=sf) + t = single_site_operator(T, Trivial, U1Irrep; sf) I = sectortype(t) b = sf ? 0 : 1 - t[(I(b, 1//2), dual(I(b, 1//2)))] .= 0.5 - t[(I(b, -1//2), dual(I(b, -1//2)))] .= -0.5 + t[(I(b, 1 // 2), dual(I(b, 1 // 2)))] .= 0.5 + t[(I(b, -1 // 2), dual(I(b, -1 // 2)))] .= -0.5 return t end @@ -367,20 +361,20 @@ end Return the two-body operator S⁺S⁻. The only nonzero matrix element corresponds to `|↑↓⟩ <-- |↓↑⟩`. """ -S_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - S_plusmin(ComplexF64, P, S; sf=sf) +S_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_plusmin(ComplexF64, P, + S; sf) function S_plusmin(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, Trivial, Trivial; sf=sf) + t = two_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) b = sf ? 0 : 1 t[(I(b), I(b), dual(I(b)), dual(I(b)))][1, 2, 2, 1] = 1 return t end function S_plusmin(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, Trivial, U1Irrep; sf=sf) + t = two_site_operator(T, Trivial, U1Irrep; sf) I = sectortype(t) b = sf ? 0 : 1 - t[(I(b, 1//2), I(b, -1//2), dual(I(b, -1//2)), dual(I(b, 1//2)))] .= 1 + t[(I(b, 1 // 2), I(b, -1 // 2), dual(I(b, -1 // 2)), dual(I(b, 1 // 2)))] .= 1 return t end @@ -390,12 +384,11 @@ end Return the two-body operator S⁻S⁺. The only nonzero matrix element corresponds to `|↓↑⟩ <-- |↑↓⟩`. """ -S_minplus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - S_minplus(ComplexF64, P, S; sf=sf) -function S_minplus( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - return copy(adjoint(S_plusmin(T, particle_symmetry, spin_symmetry; sf=sf))) +S_minplus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_minplus(ComplexF64, P, + S; sf) +function S_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return copy(adjoint(S_plusmin(T, particle_symmetry, spin_symmetry; sf))) end """ @@ -404,16 +397,14 @@ end Return the spin exchange operator S⁻S⁺. The only nonzero matrix element corresponds to `|↓↑⟩ <-- |↑↓⟩`. """ -S_exchange(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = - S_exchange(ComplexF64, P, S; sf=sf) -function S_exchange( - T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false -) - Sz = S_z(T, particle_symmetry, spin_symmetry; sf=sf) - return (1/2) * ( - S_plusmin(T, particle_symmetry, spin_symmetry; sf=sf) - + S_minplus(T, particle_symmetry, spin_symmetry; sf=sf) - ) + Sz ⊗ Sz +S_exchange(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_exchange(ComplexF64, P, + S; sf) +function S_exchange(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + Sz = S_z(T, particle_symmetry, spin_symmetry; sf) + return (1 / 2) * (S_plusmin(T, particle_symmetry, spin_symmetry; sf) + + + S_minplus(T, particle_symmetry, spin_symmetry; sf)) + Sz ⊗ Sz end end diff --git a/test/bosonoperators.jl b/test/bosonoperators.jl index c385b67..0b6ae7c 100644 --- a/test/bosonoperators.jl +++ b/test/bosonoperators.jl @@ -15,9 +15,9 @@ end @testset "U1-symmetric bosonic operators" begin @test convert(Array, a_number(U1Irrep; cutoff=cutoff)) ≈ - convert(Array, a_number(; cutoff=cutoff)) + convert(Array, a_number(; cutoff=cutoff)) @test permute(a_plus(U1Irrep; cutoff=cutoff, side=:L)', ((2, 1), (3,))) ≈ - a_min(U1Irrep; cutoff=cutoff, side=:R) + a_min(U1Irrep; cutoff=cutoff, side=:R) @test permute(a_min(U1Irrep; cutoff=cutoff, side=:L)', ((2, 1), (3,))) ≈ - a_plus(U1Irrep; cutoff=cutoff, side=:R) + a_plus(U1Irrep; cutoff=cutoff, side=:R) end diff --git a/test/heisenberg.jl b/test/heisenberg.jl index babee18..791eb3b 100644 --- a/test/heisenberg.jl +++ b/test/heisenberg.jl @@ -18,29 +18,26 @@ end @testset "xxx SU2" begin H = @inferred heisenberg_XXX(SU2Irrep) - ψ = InfiniteMPS([Rep[SU₂](1 => 1)], [Rep[SU₂](1//2 => 5, 3//2 => 5, 5//2 => 1)]) + ψ = InfiniteMPS([Rep[SU₂](1 => 1)], [Rep[SU₂](1 // 2 => 5, 3 // 2 => 5, 5 // 2 => 1)]) @test imag(expectation_value(ψ, H)) ≈ 0 atol = 1e-10 ψ, envs, δ = find_groundstate(ψ, H, alg) @test E₀ ≈ expectation_value(ψ, H, envs) atol = 1e-2 - ΔEs, qps = excitations( - H, QuasiparticleAnsatz(), Float64(pi), ψ, envs; sector=SU2Irrep(1) - ) + ΔEs, qps = excitations(H, QuasiparticleAnsatz(), Float64(pi), ψ, envs; + sector=SU2Irrep(1)) @test E₁ ≈ first(ΔEs) atol = 1e-2 end @testset "xxx U1" begin H = @inferred heisenberg_XXX(U1Irrep) - ψ = InfiniteMPS( - [Rep[U₁](0 => 1, 1 => 1, -1 => 1)], - [Rep[U₁](1//2 => 10, -1//2 => 10, 3//2 => 5, -3//2 => 5, 5//2 => 3, -5//2 => 3)], - ) + ψ = InfiniteMPS([Rep[U₁](0 => 1, 1 => 1, -1 => 1)], + [Rep[U₁](1 // 2 => 10, -1 // 2 => 10, 3 // 2 => 5, -3 // 2 => 5, + 5 // 2 => 3, -5 // 2 => 3)]) @test imag(expectation_value(ψ, H)) ≈ 0 atol = 1e-10 ψ, envs, δ = find_groundstate(ψ, H, alg) @test E₀ ≈ expectation_value(ψ, H, envs) atol = 1e-2 - ΔEs, qps = excitations( - H, QuasiparticleAnsatz(), Float64(pi), ψ, envs; sector=U1Irrep(1) - ) + ΔEs, qps = excitations(H, QuasiparticleAnsatz(), Float64(pi), ψ, envs; + sector=U1Irrep(1)) @test E₁ ≈ first(ΔEs) atol = 1e-2 end diff --git a/test/hubbardoperators.jl b/test/hubbardoperators.jl index ee10ef7..edf37b0 100644 --- a/test/hubbardoperators.jl +++ b/test/hubbardoperators.jl @@ -11,28 +11,28 @@ implemented_symmetries = [(Trivial, Trivial), (U1Irrep, U1Irrep), (U1Irrep, SU2I if (particle_symmetry, spin_symmetry) in implemented_symmetries # test hermiticity @test e_plusmin(particle_symmetry, spin_symmetry)' ≈ - e_minplus(particle_symmetry, spin_symmetry) + e_minplus(particle_symmetry, spin_symmetry) if spin_symmetry !== SU2Irrep @test e_plusmin_down(particle_symmetry, spin_symmetry)' ≈ - e_minplus_down(particle_symmetry, spin_symmetry) + e_minplus_down(particle_symmetry, spin_symmetry) @test e_plusmin_up(particle_symmetry, spin_symmetry)' ≈ - e_minplus_up(particle_symmetry, spin_symmetry) + e_minplus_up(particle_symmetry, spin_symmetry) @test e_plusmin_down(particle_symmetry, spin_symmetry)' ≈ - e_minplus_down(particle_symmetry, spin_symmetry) + e_minplus_down(particle_symmetry, spin_symmetry) @test e_plusmin_up(particle_symmetry, spin_symmetry)' ≈ - e_minplus_up(particle_symmetry, spin_symmetry) + e_minplus_up(particle_symmetry, spin_symmetry) end # test number operator if spin_symmetry !== SU2Irrep @test e_number(particle_symmetry, spin_symmetry) ≈ - e_number_up(particle_symmetry, spin_symmetry) + + e_number_up(particle_symmetry, spin_symmetry) + e_number_down(particle_symmetry, spin_symmetry) @test e_number_updown(particle_symmetry, spin_symmetry) ≈ - e_number_up(particle_symmetry, spin_symmetry) * - e_number_down(particle_symmetry, spin_symmetry) ≈ - e_number_down(particle_symmetry, spin_symmetry) * - e_number_up(particle_symmetry, spin_symmetry) + e_number_up(particle_symmetry, spin_symmetry) * + e_number_down(particle_symmetry, spin_symmetry) ≈ + e_number_down(particle_symmetry, spin_symmetry) * + e_number_up(particle_symmetry, spin_symmetry) end else @test_broken e_plusmin(particle_symmetry, spin_symmetry) @@ -42,16 +42,12 @@ implemented_symmetries = [(Trivial, Trivial), (U1Irrep, U1Irrep), (U1Irrep, SU2I end function hamiltonian(particle_symmetry, spin_symmetry; t, U, mu, L) - hopping = - t * ( - e_plusmin(particle_symmetry, spin_symmetry) + - e_minplus(particle_symmetry, spin_symmetry) - ) + hopping = t * (e_plusmin(particle_symmetry, spin_symmetry) + + e_minplus(particle_symmetry, spin_symmetry)) interaction = U * e_number_updown(particle_symmetry, spin_symmetry) chemical_potential = mu * e_number(particle_symmetry, spin_symmetry) I = id(hubbard_space(particle_symmetry, spin_symmetry)) - H = - sum(1:(L - 1)) do i + H = sum(1:(L - 1)) do i return reduce(⊗, insert!(collect(Any, fill(I, L - 2)), i, hopping)) end + sum(1:L) do i diff --git a/test/potts.jl b/test/potts.jl index 2d2161d..1526563 100644 --- a/test/potts.jl +++ b/test/potts.jl @@ -7,9 +7,8 @@ alg = VUMPS(; maxiter=25, verbosity=0) function E₀(Q::Int, maxiter::Int=1000) Q == 3 && return -(4 / 3 + 2sqrt(3) / π) Q == 4 && return 2 - 8 * log(2) - summation = sum( - (-1)^n / (sqrt(Q) / 2 - cosh((2 * n + 1) * acosh(sqrt(Q) / 2))) for n in 1:maxiter - ) + summation = sum((-1)^n / (sqrt(Q) / 2 - cosh((2 * n + 1) * acosh(sqrt(Q) / 2))) + for n in 1:maxiter) limit = 2 - Q - sqrt(Q) * (Q - 4) * summation return limit end @@ -59,9 +58,8 @@ end @testset "ZNIrrep{5}" begin H = quantum_potts(ZNIrrep{5}; q=5) - ψ = InfiniteMPS( - Vect[ZNIrrep{5}](i => 1 for i in 0:4), Vect[ZNIrrep{5}](i => 12 for i in 0:4) - ) + ψ = InfiniteMPS(Vect[ZNIrrep{5}](i => 1 for i in 0:4), + Vect[ZNIrrep{5}](i => 12 for i in 0:4)) @test imag(expectation_value(ψ, H)) ≈ 0 atol = 1e-10 ψ, envs, δ = find_groundstate(ψ, H, alg) @test E₀(5) ≈ expectation_value(ψ, H, envs) atol = 1e-2 diff --git a/test/sixvertex.jl b/test/sixvertex.jl index bb72c75..ac0d73a 100644 --- a/test/sixvertex.jl +++ b/test/sixvertex.jl @@ -17,10 +17,8 @@ end @testset "U₁" begin mpo = @inferred sixvertex(ComplexF64, U1Irrep) mpo2 = MPOMultiline([mpo.opp mpo.opp; mpo.opp mpo.opp]) - vspaces = [ - U1Space(0 => 20, 1 => 10, -1 => 10, 2 => 5, -2 => 5), - U1Space(1//2 => 15, -1//2 => 15, 3//2 => 5, -3//2 => 5), - ] + vspaces = [U1Space(0 => 20, 1 => 10, -1 => 10, 2 => 5, -2 => 5), + U1Space(1 // 2 => 15, -1 // 2 => 15, 3 // 2 => 5, -3 // 2 => 5)] ψ = MPSMultiline(repeat(space.(mpo.opp, 2), 2, 2), [vspaces circshift(vspaces, 1)]) ψ, _ = leading_boundary(ψ, mpo2, alg) F = prod(expectation_value(ψ, mpo2)) @@ -30,10 +28,8 @@ end @testset "CU₁" begin mpo = @inferred sixvertex(ComplexF64, CU1Irrep) mpo2 = MPOMultiline([mpo.opp mpo.opp; mpo.opp mpo.opp]) - vspaces = [ - CU1Space((0, 0) => 10, (0, 1) => 10, (1, 2) => 5, (2, 2) => 5), - CU1Space((1//2, 2) => 15, (3//2, 2) => 5), - ] + vspaces = [CU1Space((0, 0) => 10, (0, 1) => 10, (1, 2) => 5, (2, 2) => 5), + CU1Space((1 // 2, 2) => 15, (3 // 2, 2) => 5)] ψ = MPSMultiline(repeat(space.(mpo.opp, 2), 2, 2), [vspaces circshift(vspaces, 1)]) ψ, _ = leading_boundary(ψ, mpo2, alg) F = prod(expectation_value(ψ, mpo2)) diff --git a/test/spinoperators.jl b/test/spinoperators.jl index fb8130c..51c29c3 100644 --- a/test/spinoperators.jl +++ b/test/spinoperators.jl @@ -11,7 +11,7 @@ for i in 1:3 ε[mod1(i, 3), mod1(i - 1, 3), mod1(i - 2, 3)] = -1 end -@testset "non-symmetric spin $(Int(2S))/2 operators" for S in (1//2):(1//2):4 +@testset "non-symmetric spin $(Int(2S))/2 operators" for S in (1 // 2):(1 // 2):4 # inferrability X = @inferred S_x(; spin=S) Y = @inferred S_y(; spin=S) @@ -37,7 +37,7 @@ end # commutation relations for i in 1:3, j in 1:3 @test Svec[i] * Svec[j] - Svec[j] * Svec[i] ≈ - sum(im * ε[i, j, k] * Svec[k] for k in 1:3) + sum(im * ε[i, j, k] * Svec[k] for k in 1:3) end # definition of +- @@ -94,23 +94,23 @@ end @test (S⁺⁻ + S⁻⁺) / 2 ≈ XX + YY rtol = 1e-3 end -@testset "U1-symmetric spin $(Int(2spin))/2 operators" for spin in (1//2):(1//2):4 +@testset "U1-symmetric spin $(Int(2spin))/2 operators" for spin in (1 // 2):(1 // 2):4 # array conversion N = Int(2spin + 1) p = sortperm(reverse((-spin):spin); by=x -> abs(x - 0.1)) # sort as 0, 1, -1, 2, -2, ... H = one(zeros(N, N))[p, :] @test H * convert(Array, S_z(; spin=spin)) * H' ≈ - convert(Array, S_z(U1Irrep; spin=spin)) + convert(Array, S_z(U1Irrep; spin=spin)) for S in (S_x, S_y, S_plus, S_min) array1 = convert(Array, S(; spin=spin)) - arrayL = - H' * - reshape(sum(convert(Array, S(U1Irrep; side=:L, spin=spin)); dims=3), N, N) * - H - arrayR = - H' * - reshape(sum(convert(Array, S(U1Irrep; side=:R, spin=spin)); dims=1), N, N) * - H + arrayL = H' * + reshape(sum(convert(Array, S(U1Irrep; side=:L, spin=spin)); dims=3), N, + N) * + H + arrayR = H' * + reshape(sum(convert(Array, S(U1Irrep; side=:R, spin=spin)); dims=1), N, + N) * + H @test array1 ≈ arrayL @test array1 ≈ arrayR end @@ -118,20 +118,19 @@ end # # hermiticity @test S_z(U1Irrep; spin=spin)' ≈ S_z(U1Irrep; spin=spin) @test permute(S_x(U1Irrep; spin=spin, side=:L)', ((2, 1), (3,))) ≈ - S_x(U1Irrep; spin=spin, side=:R) + S_x(U1Irrep; spin=spin, side=:R) @test permute(S_y(U1Irrep; spin=spin, side=:L)', ((2, 1), (3,))) ≈ - S_y(U1Irrep; spin=spin, side=:R) + S_y(U1Irrep; spin=spin, side=:R) @test permute(S_plus(U1Irrep; spin=spin, side=:L)', ((2, 1), (3,))) ≈ - S_min(U1Irrep; spin=spin, side=:R) + S_min(U1Irrep; spin=spin, side=:R) @test permute(S_min(U1Irrep; spin=spin, side=:L)', ((2, 1), (3,))) ≈ - S_plus(U1Irrep; spin=spin, side=:R) + S_plus(U1Irrep; spin=spin, side=:R) # # composite operators @test (S_plusmin(U1Irrep; spin=spin) + S_minplus(U1Irrep; spin=spin)) / 2 ≈ - S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) rtol = 1e-3 + S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) rtol = 1e-3 @test S_exchange(U1Irrep; spin=spin) ≈ - S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) + S_zz(U1Irrep; spin=spin) rtol = - 1e-3 + S_xx(U1Irrep; spin=spin) + S_yy(U1Irrep; spin=spin) + S_zz(U1Irrep; spin=spin) rtol = 1e-3 end # potts_ZZ test? diff --git a/test/tjoperators.jl b/test/tjoperators.jl index bdf99f1..1c8edc7 100644 --- a/test/tjoperators.jl +++ b/test/tjoperators.jl @@ -12,29 +12,29 @@ implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] if (particle_symmetry, spin_symmetry) in implemented_symmetries # test hermiticity @test e_plusmin(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus(particle_symmetry, spin_symmetry; sf=sf) + e_minplus(particle_symmetry, spin_symmetry; sf=sf) if spin_symmetry !== SU2Irrep @test e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) + e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) @test e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) + e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) @test e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) + e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) @test e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) + e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) end # test number operator if spin_symmetry !== SU2Irrep pspace = tj_space(particle_symmetry, spin_symmetry; sf=sf) @test e_number(particle_symmetry, spin_symmetry; sf=sf) ≈ - e_number_up(particle_symmetry, spin_symmetry; sf=sf) + + e_number_up(particle_symmetry, spin_symmetry; sf=sf) + e_number_down(particle_symmetry, spin_symmetry; sf=sf) @test TensorMap(zeros, pspace, pspace) ≈ - e_number_up(particle_symmetry, spin_symmetry; sf=sf) * - e_number_down(particle_symmetry, spin_symmetry; sf=sf) ≈ - e_number_down(particle_symmetry, spin_symmetry; sf=sf) * - e_number_up(particle_symmetry, spin_symmetry; sf=sf) + e_number_up(particle_symmetry, spin_symmetry; sf=sf) * + e_number_down(particle_symmetry, spin_symmetry; sf=sf) ≈ + e_number_down(particle_symmetry, spin_symmetry; sf=sf) * + e_number_up(particle_symmetry, spin_symmetry; sf=sf) end # test spin operator @@ -55,7 +55,7 @@ implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] # commutation relations for i in 1:3, j in 1:3 @test Svec[i] * Svec[j] - Svec[j] * Svec[i] ≈ - sum(im * ε[i, j, k] * Svec[k] for k in 1:3) + sum(im * ε[i, j, k] * Svec[k] for k in 1:3) end end else @@ -67,20 +67,17 @@ end function hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, sf) num = e_number(particle_symmetry, spin_symmetry; sf=sf) - hop_heis = - (-t) * ( - e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + - e_minplus(particle_symmetry, spin_symmetry; sf=sf) - ) + - J * (S_exchange(particle_symmetry, spin_symmetry; sf=sf) - (1 / 4) * (num ⊗ num)) + hop_heis = (-t) * (e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + + e_minplus(particle_symmetry, spin_symmetry; sf=sf)) + + J * + (S_exchange(particle_symmetry, spin_symmetry; sf=sf) - (1 / 4) * (num ⊗ num)) chemical_potential = (-mu) * num I = id(tj_space(particle_symmetry, spin_symmetry; sf=sf)) - H = - sum(1:(L - 1)) do i - return reduce(⊗, insert!(collect(Any, fill(I, L - 2)), i, hop_heis)) - end + sum(1:L) do i - return reduce(⊗, insert!(collect(Any, fill(I, L - 1)), i, chemical_potential)) - end + H = sum(1:(L - 1)) do i + return reduce(⊗, insert!(collect(Any, fill(I, L - 2)), i, hop_heis)) + end + sum(1:L) do i + return reduce(⊗, insert!(collect(Any, fill(I, L - 1)), i, chemical_potential)) + end return H end From 1dd85e306cb7267582504216938b23d4663415d8 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sat, 30 Nov 2024 19:26:07 +0800 Subject: [PATCH 04/14] Fix name conflicts --- test/tjoperators.jl | 53 ++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/test/tjoperators.jl b/test/tjoperators.jl index 1c8edc7..fd5fc18 100644 --- a/test/tjoperators.jl +++ b/test/tjoperators.jl @@ -1,6 +1,5 @@ using Test using TensorKit -using MPSKitModels.TJOperators using LinearAlgebra: eigvals implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] @@ -11,30 +10,30 @@ implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] if (particle_symmetry, spin_symmetry) in implemented_symmetries # test hermiticity - @test e_plusmin(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus(particle_symmetry, spin_symmetry; sf=sf) + @test tJ.e_plusmin(particle_symmetry, spin_symmetry; sf=sf)' ≈ + tJ.e_minplus(particle_symmetry, spin_symmetry; sf=sf) if spin_symmetry !== SU2Irrep - @test e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) - @test e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) - @test e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) - @test e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ - e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) + @test tJ.e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ + tJ.e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) + @test tJ.e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ + tJ.e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) + @test tJ.e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ + tJ.e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) + @test tJ.e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ + tJ.e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) end # test number operator if spin_symmetry !== SU2Irrep - pspace = tj_space(particle_symmetry, spin_symmetry; sf=sf) - @test e_number(particle_symmetry, spin_symmetry; sf=sf) ≈ - e_number_up(particle_symmetry, spin_symmetry; sf=sf) + - e_number_down(particle_symmetry, spin_symmetry; sf=sf) + pspace = tJ.tj_space(particle_symmetry, spin_symmetry; sf=sf) + @test tJ.e_number(particle_symmetry, spin_symmetry; sf=sf) ≈ + tJ.e_number_up(particle_symmetry, spin_symmetry; sf=sf) + + tJ.e_number_down(particle_symmetry, spin_symmetry; sf=sf) @test TensorMap(zeros, pspace, pspace) ≈ - e_number_up(particle_symmetry, spin_symmetry; sf=sf) * - e_number_down(particle_symmetry, spin_symmetry; sf=sf) ≈ - e_number_down(particle_symmetry, spin_symmetry; sf=sf) * - e_number_up(particle_symmetry, spin_symmetry; sf=sf) + tJ.e_number_up(particle_symmetry, spin_symmetry; sf=sf) * + tJ.e_number_down(particle_symmetry, spin_symmetry; sf=sf) ≈ + tJ.e_number_down(particle_symmetry, spin_symmetry; sf=sf) * + tJ.e_number_up(particle_symmetry, spin_symmetry; sf=sf) end # test spin operator @@ -44,7 +43,7 @@ implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] ε[mod1(i, 3), mod1(i + 1, 3), mod1(i + 2, 3)] = 1 ε[mod1(i, 3), mod1(i - 1, 3), mod1(i - 2, 3)] = -1 end - Svec = [S_x(; sf), S_y(; sf), S_z(; sf)] + Svec = [tJ.S_x(; sf), tJ.S_y(; sf), tJ.S_z(; sf)] # Hermiticity for s in Svec @test s' ≈ s @@ -59,20 +58,20 @@ implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] end end else - @test_broken e_plusmin(particle_symmetry, spin_symmetry; sf=sf) - @test_broken e_minplus(particle_symmetry, spin_symmetry; sf=sf) + @test_broken tJ.e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + @test_broken tJ.e_minplus(particle_symmetry, spin_symmetry; sf=sf) end end end function hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, sf) - num = e_number(particle_symmetry, spin_symmetry; sf=sf) - hop_heis = (-t) * (e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + - e_minplus(particle_symmetry, spin_symmetry; sf=sf)) + + num = tJ.e_number(particle_symmetry, spin_symmetry; sf=sf) + hop_heis = (-t) * (tJ.e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + + tJ.e_minplus(particle_symmetry, spin_symmetry; sf=sf)) + J * - (S_exchange(particle_symmetry, spin_symmetry; sf=sf) - (1 / 4) * (num ⊗ num)) + (tJ.S_exchange(particle_symmetry, spin_symmetry; sf=sf) - (1 / 4) * (num ⊗ num)) chemical_potential = (-mu) * num - I = id(tj_space(particle_symmetry, spin_symmetry; sf=sf)) + I = id(tJ.tj_space(particle_symmetry, spin_symmetry; sf=sf)) H = sum(1:(L - 1)) do i return reduce(⊗, insert!(collect(Any, fill(I, L - 2)), i, hop_heis)) end + sum(1:L) do i From b15aa1b4e0dd224e68e451b90ac7dbfee6dcab66 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sat, 30 Nov 2024 21:07:30 +0800 Subject: [PATCH 05/14] Add more symmetries and tests for t-J model --- src/operators/tjoperators.jl | 94 +++++++++++++++++++++++++++++++++--- test/hubbardoperators.jl | 22 ++++----- test/tjoperators.jl | 33 +++++++++---- 3 files changed, 120 insertions(+), 29 deletions(-) diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index c99e85f..c9805d4 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -109,10 +109,18 @@ function e_plusmin_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) return error("Not implemented") end function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - return error("Not implemented") + t = two_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(b, 1), I(h, 0), dual(I(h, 0)), dual(I(b, 1)))][1, 1, 1, 1] = sgn * 1 + return t end function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - return error("Not implemented") + t = two_site_operator(T, U1Irrep, U1Irrep; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(b, 1, 1 // 2), I(h, 0, 0), dual(I(h, 0, 0)), dual(I(b, 1, 1 // 2)))] .= sgn * 1 + return t end function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) return error("Not implemented") @@ -146,10 +154,18 @@ function e_plusmin_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) return error("Not implemented") end function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - return error("Not implemented") + t = two_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(b, 1), I(h, 0), dual(I(h, 0)), dual(I(b, 1)))][2, 1, 1, 2] = sgn * 1 + return t end function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - return error("Not implemented") + t = two_site_operator(T, U1Irrep, U1Irrep; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(b, 1, -1 // 2), I(h, 0, 0), dual(I(h, 0, 0)), dual(I(b, 1, -1 // 2)))] .= sgn * 1 + return t end function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) return error("Not implemented") @@ -239,10 +255,18 @@ function e_number_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) throw(ArgumentError("`e_number_up` is not symmetric under `SU2Irrep` spin symmetry")) end function e_number_up(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - return error("Not implemented") + t = single_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1), dual(I(b, 1)))][1, 1] = 1 + return t end function e_number_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - return error("Not implemented") + t = single_site_operator(T, U1Irrep, U1Irrep; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1, 1 // 2), dual(I(b, 1, 1 // 2)))] .= 1 + return t end function e_number_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) throw(ArgumentError("`e_number_up` is not symmetric under `SU2Irrep` spin symmetry")) @@ -275,10 +299,18 @@ function e_number_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) throw(ArgumentError("`e_number_down` is not symmetric under `SU2Irrep` spin symmetry")) end function e_number_down(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - return error("Not implemented") + t = single_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1), dual(I(b, 1)))][2, 2] = 1 + return t end function e_number_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - return error("Not implemented") + t = single_site_operator(T, U1Irrep, U1Irrep; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1, -1 // 2), dual(I(b, 1, -1 // 2)))] .= 1 + return t end function e_number_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) throw(ArgumentError("`e_number_down` is not symmetric under `SU2Irrep` spin symmetry")) @@ -314,6 +346,14 @@ function S_x(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false t[(I(b), dual(I(b)))][2, 1] = 0.5 return t end +function S_x(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + t = single_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1), dual(I(b, 1)))][1, 2] = 0.5 + t[(I(b, 1), dual(I(b, 1)))][2, 1] = 0.5 + return t +end """ S_y(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) @@ -330,6 +370,14 @@ function S_y(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false t[(I(b), dual(I(b)))][2, 1] = 0.5im return t end +function S_y(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + t = single_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1), dual(I(b, 1)))][1, 2] = -0.5im + t[(I(b, 1), dual(I(b, 1)))][2, 1] = 0.5im + return t +end """ S_z(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) @@ -354,6 +402,22 @@ function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false t[(I(b, -1 // 2), dual(I(b, -1 // 2)))] .= -0.5 return t end +function S_z(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + t = single_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1), dual(I(b, 1)))][1, 1] = 0.5 + t[(I(b, 1), dual(I(b, 1)))][2, 2] = -0.5 + return t +end +function S_z(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + t = single_site_operator(T, U1Irrep, U1Irrep; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1, 1 // 2), dual(I(b, 1, 1 // 2)))] .= 0.5 + t[(I(b, 1, -1 // 2), dual(I(b, 1, -1 // 2)))] .= -0.5 + return t +end """ S_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) @@ -377,6 +441,20 @@ function S_plusmin(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) t[(I(b, 1 // 2), I(b, -1 // 2), dual(I(b, -1 // 2)), dual(I(b, 1 // 2)))] .= 1 return t end +function S_plusmin(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + t = two_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1), I(b, 1), dual(I(b, 1)), dual(I(b, 1)))][1, 2, 2, 1] = 1 + return t +end +function S_plusmin(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + t = two_site_operator(T, U1Irrep, U1Irrep; sf) + I = sectortype(t) + b = sf ? 0 : 1 + t[(I(b, 1, 1 // 2), I(b, 1, -1 // 2), dual(I(b, 1, -1 // 2)), dual(I(b, 1, 1 // 2)))] .= 1 + return t +end """ S_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) diff --git a/test/hubbardoperators.jl b/test/hubbardoperators.jl index edf37b0..1a92d87 100644 --- a/test/hubbardoperators.jl +++ b/test/hubbardoperators.jl @@ -71,17 +71,15 @@ end end sort!(vals_triv) - H_u1_u1 = hamiltonian(U1Irrep, U1Irrep; t, U, mu, L) - vals_u1_u1 = mapreduce(vcat, eigvals(H_u1_u1)) do (c, v) - return repeat(real.(v), dim(c)) - end - sort!(vals_u1_u1) - @test vals_triv ≈ vals_u1_u1 - - H_u1_su2 = hamiltonian(U1Irrep, SU2Irrep; t, U, mu, L) - vals_u1_su2 = mapreduce(vcat, eigvals(H_u1_su2)) do (c, v) - return repeat(real.(v), dim(c)) + for (particle_symmetry, spin_symmetry) in implemented_symmetries + if (particle_symmetry, spin_symmetry) == (Trivial, Trivial) + continue + end + H_symm = hamiltonian(particle_symmetry, spin_symmetry; t, U, mu, L) + vals_symm = mapreduce(vcat, eigvals(H_symm)) do (c, v) + return repeat(real.(v), dim(c)) + end + sort!(vals_symm) + @test vals_triv ≈ vals_symm end - sort!(vals_u1_su2) - @test vals_triv ≈ vals_u1_su2 end diff --git a/test/tjoperators.jl b/test/tjoperators.jl index fd5fc18..5a0e4b4 100644 --- a/test/tjoperators.jl +++ b/test/tjoperators.jl @@ -1,8 +1,12 @@ using Test using TensorKit using LinearAlgebra: eigvals +import MPSKitModels: tJ -implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] +implemented_symmetries = [(Trivial, Trivial), + (Trivial, U1Irrep), + (U1Irrep, Trivial), + (U1Irrep, U1Irrep)] @testset "basic properties" begin for sf in (false, true), particle_symmetry in (Trivial, U1Irrep), @@ -37,13 +41,15 @@ implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] end # test spin operator - if (particle_symmetry, spin_symmetry) == (Trivial, Trivial) + if spin_symmetry == Trivial ε = zeros(ComplexF64, 3, 3, 3) for i in 1:3 ε[mod1(i, 3), mod1(i + 1, 3), mod1(i + 2, 3)] = 1 ε[mod1(i, 3), mod1(i - 1, 3), mod1(i - 2, 3)] = -1 end - Svec = [tJ.S_x(; sf), tJ.S_y(; sf), tJ.S_z(; sf)] + Svec = [tJ.S_x(particle_symmetry, spin_symmetry; sf), + tJ.S_y(particle_symmetry, spin_symmetry; sf), + tJ.S_z(particle_symmetry, spin_symmetry; sf)] # Hermiticity for s in Svec @test s' ≈ s @@ -51,6 +57,9 @@ implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep)] # operators should be normalized S = 1 / 2 @test sum(tr(Svec[i]^2) for i in 1:3) / (2S + 1) ≈ S * (S + 1) + # test S_plus and S_min + @test tJ.S_plusmin(particle_symmetry, spin_symmetry; sf) ≈ + (Svec[1] + im * Svec[2]) ⊗ (Svec[1] - im * Svec[2]) # commutation relations for i in 1:3, j in 1:3 @test Svec[i] * Svec[j] - Svec[j] * Svec[i] ≈ @@ -69,7 +78,8 @@ function hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, sf) hop_heis = (-t) * (tJ.e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + tJ.e_minplus(particle_symmetry, spin_symmetry; sf=sf)) + J * - (tJ.S_exchange(particle_symmetry, spin_symmetry; sf=sf) - (1 / 4) * (num ⊗ num)) + (tJ.S_exchange(particle_symmetry, spin_symmetry; sf=sf) - + (1 / 4) * (num ⊗ num)) chemical_potential = (-mu) * num I = id(tJ.tj_space(particle_symmetry, spin_symmetry; sf=sf)) H = sum(1:(L - 1)) do i @@ -93,11 +103,16 @@ end end sort!(vals_triv) - H_u1 = hamiltonian(Trivial, U1Irrep; t, J, mu, L, sf) - vals_u1 = mapreduce(vcat, eigvals(H_u1)) do (c, v) - return repeat(real.(v), dim(c)) + for (particle_symmetry, spin_symmetry) in implemented_symmetries + if (particle_symmetry, spin_symmetry) == (Trivial, Trivial) + continue + end + H_symm = hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, sf) + vals_symm = mapreduce(vcat, eigvals(H_symm)) do (c, v) + return repeat(real.(v), dim(c)) + end + sort!(vals_symm) + @test vals_triv ≈ vals_symm end - sort!(vals_u1) - @test vals_triv ≈ vals_u1 end end From 7ba06bce9c833a933090d34543036bd8e9928212 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sat, 30 Nov 2024 21:31:34 +0800 Subject: [PATCH 06/14] Add singlet pairing operators --- src/operators/tjoperators.jl | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index c9805d4..2c782da 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -13,6 +13,7 @@ using TensorKit export tj_space export e_plusmin, e_plusmin_up, e_plusmin_down export e_minplus, e_minplus_up, e_minplus_down +export e_minmin_ud, e_minmin_du, e_singlet export e_number, e_number_up, e_number_down export S_x, S_y, S_z export S_plusmin, S_minplus, S_exchange @@ -230,6 +231,93 @@ function e_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:S end const e⁻e⁺ = e_minplus +""" + e_minmin_ud(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator `e_{1,↑} e_{2,↓}` that annihilates a spin-up particle at the first site and a spin-down particle at the second site. +The only nonzero matrix element corresponds to `|00⟩ <-- |↑↓⟩`. +""" +e_minmin_ud(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minmin_ud(ComplexF64, + P, S; sf) +function e_minmin_ud(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = two_site_operator(T, Trivial, Trivial; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(h), I(h), dual(I(b)), dual(I(b)))][1, 1, 1, 2] = -sgn * 1 + return t +end +function e_minmin_ud(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(h, 0), I(h, 0), dual(I(b, 1 // 2)), dual(I(b, -1 // 2)))] .= -sgn * 1 + return t +end +function e_minmin_ud(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + t = two_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(h, 0), I(h, 0), dual(I(b, 1)), dual(I(b, 1)))][1, 1, 1, 2] = -sgn * 1 + return t +end +function e_minmin_ud(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + t = two_site_operator(T, U1Irrep, U1Irrep; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(h, 0, 0), I(h, 0, 0), dual(I(b, 1, 1 // 2)), dual(I(b, 1, -1 // 2)))] .= -sgn * 1 + return t +end + +""" + e_minmin_du(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body operator `e_{1,↓} e_{2,↑}` that annihilates a spin-down particle at the first site and a spin-up particle at the second site. +The only nonzero matrix element corresponds to `|00⟩ <-- |↓↑⟩`. +""" +e_minmin_du(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minmin_du(ComplexF64, + P, S; sf) +function e_minmin_du(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) + t = two_site_operator(T, Trivial, Trivial; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(h), I(h), dual(I(b)), dual(I(b)))][1, 1, 2, 1] = -sgn * 1 + return t +end +function e_minmin_du(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(h, 0), I(h, 0), dual(I(b, -1 // 2)), dual(I(b, 1 // 2)))] .= -sgn * 1 + return t +end +function e_minmin_du(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) + t = two_site_operator(T, U1Irrep, Trivial; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(h, 0), I(h, 0), dual(I(b, 1)), dual(I(b, 1)))][1, 1, 2, 1] = -sgn * 1 + return t +end +function e_minmin_du(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) + t = two_site_operator(T, U1Irrep, U1Irrep; sf) + I = sectortype(t) + (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + t[(I(h, 0, 0), I(h, 0, 0), dual(I(b, 1, -1 // 2)), dual(I(b, 1, 1 // 2)))] .= -sgn * 1 + return t +end + +""" + e_singlet(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + +Return the two-body singlet operator `(e_{1,↓} e_{2,↑} - e_{1,↓} e_{2,↑}) / sqrt(2)`. +""" +e_singlet(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_singlet(ComplexF64, P, + S; sf) +function e_singlet(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return (e_minmin_ud(T, particle_symmetry, spin_symmetry; sf) - + e_minmin_du(T, particle_symmetry, spin_symmetry; sf)) / sqrt(2) +end + """ e_number_up(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) From da18092235e7791b7699e9bdc7b7870138eb4733 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sun, 1 Dec 2024 10:26:34 +0800 Subject: [PATCH 07/14] Add notes for `e_minplus` --- src/operators/hubbardoperators.jl | 12 ++++++++---- src/operators/tjoperators.jl | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/operators/hubbardoperators.jl b/src/operators/hubbardoperators.jl index 6b60c9f..b111dec 100644 --- a/src/operators/hubbardoperators.jl +++ b/src/operators/hubbardoperators.jl @@ -64,7 +64,7 @@ end """ e_plusmin_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) -Return the two-body operator that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. +Return the two-body operator `e†_{1,↑}, e_{2,↑}` that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. """ e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}) = e_plusmin_up(ComplexF64, P, S) function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}) @@ -111,7 +111,7 @@ const e⁺e⁻ꜛ = e_plusmin_up """ e_plusmin_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) -Return the two-body operator that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. +Return the two-body operator `e†_{1,↓}, e_{2,↓}` that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. """ e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}) = e_plusmin_down(ComplexF64, P, S) function e_plusmin_down(T, ::Type{Trivial}, ::Type{Trivial}) @@ -158,7 +158,9 @@ const e⁺e⁻ꜜ = e_plusmin_down """ e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) -Return the two-body operator that annihilates a spin-up electron at the first site and creates a spin-up electron at the second. +Return the Hermitian conjugate of `e_plusmin_up`, i.e. +`(e†_{1,↑}, e_{2,↑})† = -e_{1,↑}, e†_{2,↑}` (note the extra minus sign). +It annihilates a spin-up electron at the first site and creates a spin-up electron at the second. """ e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}) = e_minplus_up(ComplexF64, P, S) function e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) @@ -169,7 +171,9 @@ const e⁻⁺ꜛ = e_minplus_up """ e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) -Return the two-body operator that annihilates a spin-down electron at the first site and creates a spin-down electron at the second. +Return the Hermitian conjugate of `e_plusmin_down`, i.e. +`(e†_{1,↓}, e_{2,↓})† = -e_{1,↓}, e†_{2,↓}` (note the extra minus sign). +It annihilates a spin-down electron at the first site and creates a spin-down electron at the second. """ e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}) = e_minplus_down(ComplexF64, P, S) function e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index 2c782da..1e3474e 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -80,7 +80,7 @@ end """ e_plusmin_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body operator that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. +Return the two-body operator `e†_{1,↑}, e_{2,↑}` that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. The only nonzero matrix element corresponds to `|↑0⟩ <-- |0↑⟩`. """ e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin_up(ComplexF64, @@ -131,7 +131,7 @@ const e⁺e⁻ꜛ = e_plusmin_up """ e_plusmin_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body operator that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. +Return the two-body operator `e†_{1,↓}, e_{2,↓}` that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. The only nonzero matrix element corresponds to `|↓0⟩ <-- |0↓⟩`. """ e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin_down(ComplexF64, @@ -176,7 +176,9 @@ const e⁺e⁻ꜜ = e_plusmin_down """ e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body operator that annihilates a spin-up electron at the first site and creates a spin-up electron at the second. +Return the Hermitian conjugate of `e_plusmin_up`, i.e. +`(e†_{1,↑}, e_{2,↑})† = -e_{1,↑}, e†_{2,↑}` (note the extra minus sign). +It annihilates a spin-up electron at the first site and creates a spin-up electron at the second. The only nonzero matrix element corresponds to `|0↑⟩ <-- |↑0⟩`. """ e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minplus_up(ComplexF64, @@ -190,7 +192,9 @@ const e⁻⁺ꜛ = e_minplus_up """ e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body operator that annihilates a spin-down electron at the first site and creates a spin-down electron at the second. +Return the Hermitian conjugate of `e_plusmin_down`, i.e. +`(e†_{1,↓}, e_{2,↓})† = -e_{1,↓}, e†_{2,↓}` (note the extra minus sign). +It annihilates a spin-down electron at the first site and creates a spin-down electron at the second. The only nonzero matrix element corresponds to `|0↓⟩ <-- |↓0⟩`. """ e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minplus_down(ComplexF64, From cb6033b31e7794ea6ff5d7d5fe666f92a3bbe775 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sun, 1 Dec 2024 17:39:58 +0800 Subject: [PATCH 08/14] Add more operators for t-J model --- src/MPSKitModels.jl | 5 +-- src/operators/tjoperators.jl | 67 +++++++++++++++++++++++++++++++----- test/tjoperators.jl | 3 +- 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/MPSKitModels.jl b/src/MPSKitModels.jl index d8d65ae..1b56f5a 100644 --- a/src/MPSKitModels.jl +++ b/src/MPSKitModels.jl @@ -35,7 +35,7 @@ export c⁺, c⁻, c⁺⁺, c⁻⁻, c⁺⁻, c⁻⁺ export e_plus, e_min, e_plusplus, e_minmin, e_plusmin, e_minplus export e_number, e_number_up, e_number_down, e_number_updown export e⁺⁺, e⁻⁻, e⁺⁻, e⁻⁺ -export tJ +export tJ, TJOperators export transverse_field_ising export kitaev_model @@ -70,7 +70,8 @@ using .HubbardOperators # TJOperators share operator names with HubbardOperators # and is only imported to avoid name conflicts include("operators/tjoperators.jl") -import .TJOperators as tJ +import .TJOperators +const tJ = TJOperators include("operators/bosonoperators.jl") include("models/hamiltonians.jl") diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index 1e3474e..c1ce577 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -14,12 +14,13 @@ export tj_space export e_plusmin, e_plusmin_up, e_plusmin_down export e_minplus, e_minplus_up, e_minplus_down export e_minmin_ud, e_minmin_du, e_singlet -export e_number, e_number_up, e_number_down -export S_x, S_y, S_z +export e_number, e_number_up, e_number_down, e_number_hole +export S_x, S_y, S_z, S_plus, S_min export S_plusmin, S_minplus, S_exchange export e⁺e⁻, e⁺e⁻ꜛ, e⁺e⁻ꜜ, e⁻e⁺, e⁻e⁺ꜛ, e⁻e⁺ꜜ -export nꜛ, nꜜ +export nꜛ, nꜜ, nʰ +export Sˣ, Sʸ, Sᶻ, S⁺, S⁻ # not exported because namespace: export n """ @@ -423,13 +424,28 @@ function e_number(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Se end const n = e_number +""" + e_number_hole(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + +Return the one-body operator that counts the number of holes. +""" +e_number_hole(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_number_hole(ComplexF64, + P, S; + sf) +function e_number_hole(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + iden = TensorKit.id(tj_space(particle_symmetry, spin_symmetry; sf)) + return iden - e_number(T, particle_symmetry, spin_symmetry; sf) +end +const nʰ = e_number_hole + """ S_x(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) Return the one-body spin-1/2 x-operator on the electrons. """ -S_x(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_x(ComplexF64, P, S; sf) -S_x(; sf::Bool=false) = S_x(ComplexF64, Trivial, Trivial; sf) +S_x(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; sf::Bool=false) = S_x(ComplexF64, + P, S; sf) function S_x(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) t = single_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) @@ -446,14 +462,15 @@ function S_x(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false t[(I(b, 1), dual(I(b, 1)))][2, 1] = 0.5 return t end +const Sˣ = S_x """ S_y(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) Return the one-body spin-1/2 x-operator on the electrons (only defined for `Trivial` symmetry). """ -S_y(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_y(ComplexF64, P, S; sf) -S_y(; sf::Bool=false) = S_y(ComplexF64, Trivial, Trivial; sf) +S_y(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; sf::Bool=false) = S_y(ComplexF64, + P, S; sf) function S_y(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) t = single_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) @@ -470,14 +487,15 @@ function S_y(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false t[(I(b, 1), dual(I(b, 1)))][2, 1] = 0.5im return t end +const Sʸ = S_y """ S_z(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) Return the one-body spin-1/2 z-operator on the electrons. """ -S_z(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_z(ComplexF64, P, S; sf) -S_z(; sf::Bool=false) = S_z(ComplexF64, Trivial, Trivial; sf) +S_z(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; sf::Bool=false) = S_z(ComplexF64, + P, S; sf) function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) t = single_site_operator(T, Trivial, Trivial; sf) I = sectortype(t) @@ -510,6 +528,37 @@ function S_z(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false t[(I(b, 1, -1 // 2), dual(I(b, 1, -1 // 2)))] .= -0.5 return t end +const Sᶻ = S_z + +""" + S_plus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + +Return the spin-plus operator. +""" +S_plus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_plus(ComplexF64, + P, S; + sf) +function S_plus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return S_x(T, particle_symmetry, spin_symmetry; sf) + + 1im * S_y(T, particle_symmetry, spin_symmetry; sf) +end +const S⁺ = S_plus + +""" + S_min(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + +Return the spin-minus operator. +""" +S_min(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_min(ComplexF64, + P, S; + sf) +function S_min(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; + sf::Bool=false) + return S_x(T, particle_symmetry, spin_symmetry; sf) - + 1im * S_y(T, particle_symmetry, spin_symmetry; sf) +end +const S⁻ = S_min """ S_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) diff --git a/test/tjoperators.jl b/test/tjoperators.jl index 5a0e4b4..066a6d4 100644 --- a/test/tjoperators.jl +++ b/test/tjoperators.jl @@ -59,7 +59,8 @@ implemented_symmetries = [(Trivial, Trivial), @test sum(tr(Svec[i]^2) for i in 1:3) / (2S + 1) ≈ S * (S + 1) # test S_plus and S_min @test tJ.S_plusmin(particle_symmetry, spin_symmetry; sf) ≈ - (Svec[1] + im * Svec[2]) ⊗ (Svec[1] - im * Svec[2]) + tJ.S_plus(particle_symmetry, spin_symmetry; sf) ⊗ + tJ.S_min(particle_symmetry, spin_symmetry; sf) # commutation relations for i in 1:3, j in 1:3 @test Svec[i] * Svec[j] - Svec[j] * Svec[i] ≈ From 1eaeffa0a8b99e862637a1815e08223bb59d0edc Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sun, 1 Dec 2024 21:43:46 +0800 Subject: [PATCH 09/14] Undo irrelevant format changes --- docs/make.jl | 6 ++- src/lattices/squarelattice.jl | 32 ++++++--------- src/models/hamiltonians.jl | 72 ++++++++++++++------------------- src/models/quantum_chemistry.jl | 7 +--- 4 files changed, 48 insertions(+), 69 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 0d1d4c8..1f9a253 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -9,8 +9,10 @@ makedocs(; prettyurls=get(ENV, "CI", nothing) == "true", mathengine=MathJax()), pages=["Home" => "index.md", - "Manual" => ["man/operators.md", "man/mpoham.md", "man/lattices.md", + "Manual" => ["man/operators.md", + "man/mpoham.md", + "man/lattices.md", "man/models.md"], - "Index" => "package_index.md"],) + "Index" => "package_index.md"]) deploydocs(; repo="github.com/QuantumKitHub/MPSKitModels.jl.git") diff --git a/src/lattices/squarelattice.jl b/src/lattices/squarelattice.jl index e917810..52a85ae 100644 --- a/src/lattices/squarelattice.jl +++ b/src/lattices/squarelattice.jl @@ -149,36 +149,28 @@ end function nearest_neighbours(lattice::FiniteStrip) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in - 1:rows, - j in - 1:(cols - 1)) - vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for - i in 1:(rows - 1), j in 1:cols) + horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) + for i in 1:rows, j in 1:(cols - 1)) + vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) + for i in 1:(rows - 1), j in 1:cols) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::FiniteCylinder) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in - 1:rows, - j in - 1:(cols - 1)) - vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for i in - 1:rows, - j in - 1:cols) + horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) + for i in 1:rows, j in 1:(cols - 1)) + vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) + for i in 1:rows, j in 1:cols) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::FiniteHelix) rows = lattice.L cols = lattice.N ÷ lattice.L - horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) for i in - 1:rows, - j in - 1:(cols - 1)) - vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) for - i in 1:rows, j in 1:cols if (i != rows && j != cols)) + horizontal = (LatticePoint((i, j), lattice) => LatticePoint((i, j + 1), lattice) + for i in 1:rows, j in 1:(cols - 1)) + vertical = (LatticePoint((i, j), lattice) => LatticePoint((i + 1, j), lattice) + for i in 1:rows, j in 1:cols if (i != rows && j != cols)) return Iterators.flatten((horizontal, vertical)) end function nearest_neighbours(lattice::Union{InfiniteStrip,InfiniteCylinder,InfiniteHelix}) diff --git a/src/models/hamiltonians.jl b/src/models/hamiltonians.jl index acd3ab9..2cf1506 100644 --- a/src/models/hamiltonians.jl +++ b/src/models/hamiltonians.jl @@ -23,21 +23,23 @@ function transverse_field_ising(lattice::AbstractLattice; kwargs...) return transverse_field_ising(ComplexF64, Trivial, lattice; kwargs...) end function transverse_field_ising(S::Type{<:Sector}, - lattice::AbstractLattice=InfiniteChain(1); kwargs...) + lattice::AbstractLattice=InfiniteChain(1); + kwargs...) return transverse_field_ising(ComplexF64, S, lattice; kwargs...) end function transverse_field_ising(T::Type{<:Number}, lattice::AbstractLattice; kwargs...) return transverse_field_ising(T, Trivial, lattice; kwargs...) end -function transverse_field_ising(T::Type{<:Number}, S::Type{<:Sector}, - lattice::AbstractLattice; kwargs...) +function transverse_field_ising(T::Type{<:Number}, + S::Type{<:Sector}, + lattice::AbstractLattice; + kwargs...) throw(ArgumentError("`symmetry` must be either `Trivial`, `Z2Irrep` or `FermionParity`")) end function transverse_field_ising(T::Type{<:Number}=ComplexF64, S::Union{Type{Trivial},Type{Z2Irrep}}=Trivial, lattice::AbstractLattice=InfiniteChain(1); - J=1.0, - g=1.0,) + J=1.0, g=1.0) ZZ = rmul!(σᶻᶻ(T, S), -J) X = rmul!(σˣ(T, S), g * -J) return @mpoham begin @@ -49,7 +51,8 @@ function transverse_field_ising(T::Type{<:Number}=ComplexF64, end end function transverse_field_ising(T::Type{<:Number}, ::Type{fℤ₂}, - lattice::AbstractLattice=InfiniteChain(1); J=1.0, g=1.0) + lattice::AbstractLattice=InfiniteChain(1); + J=1.0, g=1.0) twosite = axpby!(-J, c_plusmin(T) + c_minplus(T), J, c_plusplus(T) + c_minmin(T)) onesite = axpby!(2g * J, c_number(T), -g * J, id(Matrix{T}, space(twosite, 1))) @@ -83,9 +86,7 @@ function kitaev_model(lattice::AbstractLattice; kwargs...) end function kitaev_model(elt::Type{<:Number}=ComplexF64, lattice::AbstractLattice=InfiniteChain(1); - t=1.0, - mu=1.0, - Delta=1.0,) + t=1.0, mu=1.0, Delta=1.0) TB = rmul!(c_plusmin(elt) + c_minplus(elt), -t / 2) # tight-binding term SC = rmul!(c_plusplus(elt) + c_minmin(elt), Delta / 2) # superconducting term CP = rmul!(c_number(elt), -mu) # chemical potential term @@ -131,8 +132,7 @@ end function heisenberg_XXX(T::Type{<:Number}=ComplexF64, symmetry::Type{<:Sector}=Trivial, lattice::AbstractLattice=InfiniteChain(1); - J::Real=1.0, - spin::Real=1,) + J::Real=1.0, spin::Real=1) term = rmul!(S_exchange(T, symmetry; spin=spin), J) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return term{i,j} @@ -164,9 +164,7 @@ end function heisenberg_XXZ(elt::Type{<:Number}=ComplexF64, symmetry::Type{<:Sector}=Trivial, lattice::AbstractLattice=InfiniteChain(1); - J=1.0, - Delta=1.0, - spin=1,) + J=1.0, Delta=1.0, spin=1) term = rmul!(S_xx(elt, symmetry; spin=spin), J) + rmul!(S_yy(elt, symmetry; spin=spin), J) + rmul!(S_zz(elt, symmetry; spin=spin), Delta * J) @@ -192,10 +190,7 @@ function heisenberg_XYZ(lattice::AbstractLattice; kwargs...) end function heisenberg_XYZ(T::Type{<:Number}=ComplexF64, lattice::AbstractLattice=InfiniteChain(1); - Jx=1.0, - Jy=1.0, - Jz=1.0, - spin=1,) + Jx=1.0, Jy=1.0, Jz=1.0, spin=1) term = rmul!(S_xx(T, Trivial; spin=spin), Jx) + rmul!(S_yy(T, Trivial; spin=spin), Jy) + rmul!(S_zz(T, Trivial; spin=spin), Jz) @@ -231,9 +226,7 @@ end function bilinear_biquadratic_model(elt::Type{<:Number}=ComplexF64, symmetry::Type{<:Sector}=Trivial, lattice::AbstractLattice=InfiniteChain(1); - spin=1, - J=1.0, - θ=0.0,) + spin=1, J=1.0, θ=0.0) return @mpoham sum(nearest_neighbours(lattice)) do (i, j) return J * cos(θ) * S_exchange(elt, symmetry; spin=spin){i,j} + J * sin(θ) * (S_exchange(elt, symmetry; spin=spin)^2){i,j} @@ -259,19 +252,18 @@ function quantum_potts end function quantum_potts(lattice::AbstractLattice; kwargs...) return quantum_potts(ComplexF64, Trivial, lattice; kwargs...) end -function quantum_potts(symmetry::Type{<:Sector}, lattice::AbstractLattice=InfiniteChain(1); - kwargs...) +function quantum_potts(symmetry::Type{<:Sector}, + lattice::AbstractLattice=InfiniteChain(1); kwargs...) return quantum_potts(ComplexF64, symmetry, lattice; kwargs...) end -function quantum_potts(elt::Type{<:Number}, lattice::AbstractLattice; kwargs...) +function quantum_potts(elt::Type{<:Number}, lattice::AbstractLattice; + kwargs...) return quantum_potts(elt, Trivial, lattice; kwargs...) end function quantum_potts(elt::Type{<:Number}=ComplexF64, symmetry::Type{<:Sector}=Trivial, lattice::AbstractLattice=InfiniteChain(1); - q=3, - J=1.0, - g=1.0,) + q=3, J=1.0, g=1.0) return @mpoham sum(sum(nearest_neighbours(lattice)) do (i, j) return -J * (potts_ZZ(elt, symmetry; q)^k){i,j} end - sum(vertices(lattice)) do i @@ -312,10 +304,7 @@ function hubbard_model(T::Type{<:Number}=ComplexF64, particle_symmetry::Type{<:Sector}=Trivial, spin_symmetry::Type{<:Sector}=Trivial, lattice::AbstractLattice=InfiniteChain(1); - t=1.0, - U=1.0, - mu=0.0, - n::Integer=0,) + t=1.0, U=1.0, mu=0.0, n::Integer=0) hopping = e⁺e⁻(T, particle_symmetry, spin_symmetry) + e⁻e⁺(T, particle_symmetry, spin_symmetry) interaction_term = nꜛnꜜ(T, particle_symmetry, spin_symmetry) @@ -323,9 +312,10 @@ function hubbard_model(T::Type{<:Number}=ComplexF64, return @mpoham begin sum(nearest_neighbours(lattice)) do (i, j) return -t * hopping{i,j} - end + sum(vertices(lattice)) do i - return U * interaction_term{i} - mu * N{i} - end + end + + sum(vertices(lattice)) do i + return U * interaction_term{i} - mu * N{i} + end end end @@ -353,11 +343,7 @@ end function bose_hubbard_model(elt::Type{<:Number}=ComplexF64, symmetry::Type{<:Sector}=Trivial, lattice::AbstractLattice=InfiniteChain(1); - cutoff::Integer=5, - t=1.0, - U=1.0, - mu=0.0, - n::Integer=0,) + cutoff::Integer=5, t=1.0, U=1.0, mu=0.0, n::Integer=0) hopping_term = a_plusmin(elt, symmetry; cutoff=cutoff) + a_minplus(elt, symmetry; cutoff=cutoff) N = a_number(elt, symmetry; cutoff=cutoff) @@ -366,9 +352,10 @@ function bose_hubbard_model(elt::Type{<:Number}=ComplexF64, H = @mpoham begin sum(nearest_neighbours(lattice)) do (i, j) return -t * hopping_term{i,j} - end + sum(vertices(lattice)) do i - return U / 2 * interaction_term{i} - mu * N{i} - end + end + + sum(vertices(lattice)) do i + return U / 2 * interaction_term{i} - mu * N{i} + end end if symmetry === Trivial @@ -384,6 +371,7 @@ function bose_hubbard_model(elt::Type{<:Number}=ComplexF64, return H end + #=========================================================================================== t-J models ===========================================================================================# diff --git a/src/models/quantum_chemistry.jl b/src/models/quantum_chemistry.jl index f00d977..4291b02 100644 --- a/src/models/quantum_chemistry.jl +++ b/src/models/quantum_chemistry.jl @@ -42,17 +42,14 @@ function mapped_quantum_chemistry_hamiltonian(E0, K, V, Elt=ComplexF64) (1, 1 // 2, 1) => 1, (2, 0, 0) => 1) - ap = TensorMap(ones, - Elt, + ap = TensorMap(ones, Elt, psp * Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1 // 2, 1) => 1), psp) blocks(ap)[(U₁(0) ⊠ SU₂(0) ⊠ FermionParity(0))] .*= -sqrt(2) blocks(ap)[(U₁(1) ⊠ SU₂(1 // 2) ⊠ FermionParity(1))] .*= 1 - bm = TensorMap(ones, - Elt, - psp, + bm = TensorMap(ones, Elt, psp, Vect[(Irrep[U₁] ⊠ Irrep[SU₂] ⊠ FermionParity)]((-1, 1 // 2, 1) => 1) * psp) blocks(bm)[(U₁(0) ⊠ SU₂(0) ⊠ FermionParity(0))] .*= sqrt(2) From 0f78e51b86f09c59b9becadad5d6461bfaaacb8a Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sun, 1 Dec 2024 21:54:08 +0800 Subject: [PATCH 10/14] Double-tick math expressions --- src/operators/hubbardoperators.jl | 8 ++++---- src/operators/tjoperators.jl | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/operators/hubbardoperators.jl b/src/operators/hubbardoperators.jl index b111dec..8c4e259 100644 --- a/src/operators/hubbardoperators.jl +++ b/src/operators/hubbardoperators.jl @@ -64,7 +64,7 @@ end """ e_plusmin_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) -Return the two-body operator `e†_{1,↑}, e_{2,↑}` that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. +Return the two-body operator ``e†_{1,↑}, e_{2,↑}`` that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. """ e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}) = e_plusmin_up(ComplexF64, P, S) function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}) @@ -111,7 +111,7 @@ const e⁺e⁻ꜛ = e_plusmin_up """ e_plusmin_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) -Return the two-body operator `e†_{1,↓}, e_{2,↓}` that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. +Return the two-body operator ``e†_{1,↓}, e_{2,↓}`` that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. """ e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}) = e_plusmin_down(ComplexF64, P, S) function e_plusmin_down(T, ::Type{Trivial}, ::Type{Trivial}) @@ -159,7 +159,7 @@ const e⁺e⁻ꜜ = e_plusmin_down e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) Return the Hermitian conjugate of `e_plusmin_up`, i.e. -`(e†_{1,↑}, e_{2,↑})† = -e_{1,↑}, e†_{2,↑}` (note the extra minus sign). +``(e†_{1,↑}, e_{2,↑})† = -e_{1,↑}, e†_{2,↑}`` (note the extra minus sign). It annihilates a spin-up electron at the first site and creates a spin-up electron at the second. """ e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}) = e_minplus_up(ComplexF64, P, S) @@ -172,7 +172,7 @@ const e⁻⁺ꜛ = e_minplus_up e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}) Return the Hermitian conjugate of `e_plusmin_down`, i.e. -`(e†_{1,↓}, e_{2,↓})† = -e_{1,↓}, e†_{2,↓}` (note the extra minus sign). +``(e†_{1,↓}, e_{2,↓})† = -e_{1,↓}, e†_{2,↓}`` (note the extra minus sign). It annihilates a spin-down electron at the first site and creates a spin-down electron at the second. """ e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}) = e_minplus_down(ComplexF64, P, S) diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index c1ce577..8733901 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -81,7 +81,7 @@ end """ e_plusmin_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body operator `e†_{1,↑}, e_{2,↑}` that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. +Return the two-body operator ``e†_{1,↑}, e_{2,↑}`` that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. The only nonzero matrix element corresponds to `|↑0⟩ <-- |0↑⟩`. """ e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin_up(ComplexF64, @@ -132,7 +132,7 @@ const e⁺e⁻ꜛ = e_plusmin_up """ e_plusmin_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body operator `e†_{1,↓}, e_{2,↓}` that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. +Return the two-body operator ``e†_{1,↓}, e_{2,↓}`` that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. The only nonzero matrix element corresponds to `|↓0⟩ <-- |0↓⟩`. """ e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin_down(ComplexF64, @@ -178,7 +178,7 @@ const e⁺e⁻ꜜ = e_plusmin_down e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) Return the Hermitian conjugate of `e_plusmin_up`, i.e. -`(e†_{1,↑}, e_{2,↑})† = -e_{1,↑}, e†_{2,↑}` (note the extra minus sign). +``(e†_{1,↑}, e_{2,↑})† = -e_{1,↑}, e†_{2,↑}`` (note the extra minus sign). It annihilates a spin-up electron at the first site and creates a spin-up electron at the second. The only nonzero matrix element corresponds to `|0↑⟩ <-- |↑0⟩`. """ @@ -194,7 +194,7 @@ const e⁻⁺ꜛ = e_minplus_up e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) Return the Hermitian conjugate of `e_plusmin_down`, i.e. -`(e†_{1,↓}, e_{2,↓})† = -e_{1,↓}, e†_{2,↓}` (note the extra minus sign). +``(e†_{1,↓}, e_{2,↓})† = -e_{1,↓}, e†_{2,↓}`` (note the extra minus sign). It annihilates a spin-down electron at the first site and creates a spin-down electron at the second. The only nonzero matrix element corresponds to `|0↓⟩ <-- |↓0⟩`. """ @@ -239,7 +239,7 @@ const e⁻e⁺ = e_minplus """ e_minmin_ud(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body operator `e_{1,↑} e_{2,↓}` that annihilates a spin-up particle at the first site and a spin-down particle at the second site. +Return the two-body operator ``e_{1,↑} e_{2,↓}`` that annihilates a spin-up particle at the first site and a spin-down particle at the second site. The only nonzero matrix element corresponds to `|00⟩ <-- |↑↓⟩`. """ e_minmin_ud(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minmin_ud(ComplexF64, @@ -276,7 +276,7 @@ end """ e_minmin_du(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body operator `e_{1,↓} e_{2,↑}` that annihilates a spin-down particle at the first site and a spin-up particle at the second site. +Return the two-body operator ``e_{1,↓} e_{2,↑}`` that annihilates a spin-down particle at the first site and a spin-up particle at the second site. The only nonzero matrix element corresponds to `|00⟩ <-- |↓↑⟩`. """ e_minmin_du(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minmin_du(ComplexF64, @@ -313,7 +313,7 @@ end """ e_singlet(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) -Return the two-body singlet operator `(e_{1,↓} e_{2,↑} - e_{1,↓} e_{2,↑}) / sqrt(2)`. +Return the two-body singlet operator ``(e_{1,↓} e_{2,↑} - e_{1,↓} e_{2,↑}) / sqrt(2)``. """ e_singlet(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_singlet(ComplexF64, P, S; sf) From 352f23e49dbcfd1d13bdd5b208e0362aada828ae Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sun, 1 Dec 2024 22:05:17 +0800 Subject: [PATCH 11/14] Un-abbreviate some names; remove exportation of `tJ` --- src/MPSKitModels.jl | 2 +- src/models/hamiltonians.jl | 13 +- src/operators/tjoperators.jl | 502 +++++++++++++++++++---------------- test/tjoperators.jl | 73 ++--- 4 files changed, 314 insertions(+), 276 deletions(-) diff --git a/src/MPSKitModels.jl b/src/MPSKitModels.jl index 1b56f5a..0d8fc38 100644 --- a/src/MPSKitModels.jl +++ b/src/MPSKitModels.jl @@ -35,7 +35,7 @@ export c⁺, c⁻, c⁺⁺, c⁻⁻, c⁺⁻, c⁻⁺ export e_plus, e_min, e_plusplus, e_minmin, e_plusmin, e_minplus export e_number, e_number_up, e_number_down, e_number_updown export e⁺⁺, e⁻⁻, e⁺⁻, e⁻⁺ -export tJ, TJOperators +export TJOperators export transverse_field_ising export kitaev_model diff --git a/src/models/hamiltonians.jl b/src/models/hamiltonians.jl index 2cf1506..04ec904 100644 --- a/src/models/hamiltonians.jl +++ b/src/models/hamiltonians.jl @@ -371,7 +371,6 @@ function bose_hubbard_model(elt::Type{<:Number}=ComplexF64, return H end - #=========================================================================================== t-J models ===========================================================================================# @@ -379,7 +378,7 @@ end """ tj_model([elt::Type{<:Number}], [particle_symmetry::Type{<:Sector}], [spin_symmetry::Type{<:Sector}], [lattice::AbstractLattice]; - t, J, mu, sf::Bool=false) + t, J, mu, slave_fermion::Bool=false) MPO for the hamiltonian of the t-J model, as defined by ```math @@ -408,11 +407,11 @@ function tj_model(T::Type{<:Number}=ComplexF64, t=2.5, J=1.0, mu=0.0, - sf::Bool=false,) - hopping = tJ.e_plusmin(T, particle_symmetry, spin_symmetry; sf) + - tJ.e_minplus(T, particle_symmetry, spin_symmetry; sf) - num = tJ.e_number(T, particle_symmetry, spin_symmetry; sf) - heisenberg = tJ.S_exchange(T, particle_symmetry, spin_symmetry; sf) - + slave_fermion::Bool=false,) + hopping = tJ.e_plusmin(T, particle_symmetry, spin_symmetry; slave_fermion) + + tJ.e_minplus(T, particle_symmetry, spin_symmetry; slave_fermion) + num = tJ.e_number(T, particle_symmetry, spin_symmetry; slave_fermion) + heisenberg = tJ.S_exchange(T, particle_symmetry, spin_symmetry; slave_fermion) - (1 / 4) * (num ⊗ num) return @mpoham begin sum(nearest_neighbours(lattice)) do (i, j) diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index 8733901..ebc7a8c 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -13,7 +13,7 @@ using TensorKit export tj_space export e_plusmin, e_plusmin_up, e_plusmin_down export e_minplus, e_minplus_up, e_minplus_down -export e_minmin_ud, e_minmin_du, e_singlet +export e_minmin_updown, e_minmin_downup, e_singlet export e_number, e_number_up, e_number_down, e_number_hole export S_x, S_y, S_z, S_plus, S_min export S_plusmin, S_minplus, S_exchange @@ -24,37 +24,39 @@ export Sˣ, Sʸ, Sᶻ, S⁺, S⁻ # not exported because namespace: export n """ - tj_space(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + tj_space(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the local hilbert space for a t-J-type model with the given particle and spin symmetries. The possible symmetries are - Particle number: `Trivial`, `U1Irrep`; - Spin: `Trivial`, `U1Irrep`, `SU2Irrep`. -Setting `sf = true` switches to the slave-fermion basis. +Setting `slave_fermion = true` switches to the slave-fermion basis. """ -function tj_space(::Type{Trivial}=Trivial, ::Type{Trivial}=Trivial; sf::Bool=false) - return sf ? Vect[FermionParity](0 => 2, 1 => 1) : Vect[FermionParity](0 => 1, 1 => 2) +function tj_space(::Type{Trivial}=Trivial, ::Type{Trivial}=Trivial; + slave_fermion::Bool=false) + return slave_fermion ? Vect[FermionParity](0 => 2, 1 => 1) : + Vect[FermionParity](0 => 1, 1 => 2) end -function tj_space(::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - return if sf +function tj_space(::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + return if slave_fermion Vect[FermionParity ⊠ U1Irrep]((1, 0) => 1, (0, 1 // 2) => 1, (0, -1 // 2) => 1) else Vect[FermionParity ⊠ U1Irrep]((0, 0) => 1, (1, 1 // 2) => 1, (1, -1 // 2) => 1) end end -function tj_space(::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) +function tj_space(::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) return error("Not implemented") end -function tj_space(::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - return if sf +function tj_space(::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + return if slave_fermion Vect[FermionParity ⊠ U1Irrep]((1, 0) => 1, (0, 1) => 2) else Vect[FermionParity ⊠ U1Irrep]((0, 0) => 1, (1, 1) => 2) end end -function tj_space(::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - return if sf +function tj_space(::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + return if slave_fermion Vect[FermionParity ⊠ U1Irrep ⊠ U1Irrep]((1, 0, 0) => 1, (0, 1, 1 // 2) => 1, (0, 1, -1 // 2) => 1) else @@ -62,34 +64,36 @@ function tj_space(::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) (1, 1, -1 // 2) => 1) end end -function tj_space(::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) +function tj_space(::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) return error("Not implemented") end function single_site_operator(T, particle_symmetry::Type{<:Sector}, - spin_symmetry::Type{<:Sector}; sf::Bool=false) - V = tj_space(particle_symmetry, spin_symmetry; sf) + spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) + V = tj_space(particle_symmetry, spin_symmetry; slave_fermion) return TensorMap(zeros, T, V ← V) end function two_site_operator(T, particle_symmetry::Type{<:Sector}, - spin_symmetry::Type{<:Sector}; sf::Bool=false) - V = tj_space(particle_symmetry, spin_symmetry; sf) + spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) + V = tj_space(particle_symmetry, spin_symmetry; slave_fermion) return TensorMap(zeros, T, V ⊗ V ← V ⊗ V) end """ - e_plusmin_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_plusmin_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body operator ``e†_{1,↑}, e_{2,↑}`` that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. The only nonzero matrix element corresponds to `|↑0⟩ <-- |0↑⟩`. """ -e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin_up(ComplexF64, - P, S; sf) -function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, Trivial, Trivial; sf) +e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_plusmin_up(ComplexF64, + P, + S; + slave_fermion) +function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) #= The extra minus sign in slave-fermion basis: c†_{1,↑} c_{2,↑} |0↑⟩ = h_1 b†_{1,↑} h†_2 b_{2,↑} h†_1 b†_{2,↑}|vac⟩ @@ -100,364 +104,387 @@ function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) t[(I(b), I(h), dual(I(h)), dual(I(b)))][1, 1, 1, 1] = sgn * 1 return t end -function e_plusmin_up(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, Trivial, U1Irrep; sf) +function e_plusmin_up(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(b, 1 // 2), I(h, 0), dual(I(h, 0)), dual(I(b, 1 // 2)))] .= sgn * 1 return t end -function e_plusmin_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) +function e_plusmin_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) return error("Not implemented") end -function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, Trivial; sf) +function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(b, 1), I(h, 0), dual(I(h, 0)), dual(I(b, 1)))][1, 1, 1, 1] = sgn * 1 return t end -function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, U1Irrep; sf) +function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, U1Irrep; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(b, 1, 1 // 2), I(h, 0, 0), dual(I(h, 0, 0)), dual(I(b, 1, 1 // 2)))] .= sgn * 1 return t end -function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) +function e_plusmin_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) return error("Not implemented") end const e⁺e⁻ꜛ = e_plusmin_up """ - e_plusmin_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_plusmin_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body operator ``e†_{1,↓}, e_{2,↓}`` that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. The only nonzero matrix element corresponds to `|↓0⟩ <-- |0↓⟩`. """ -e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin_down(ComplexF64, - P, S; - sf) -function e_plusmin_down(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, Trivial, Trivial; sf) +e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_plusmin_down(ComplexF64, + P, + S; + slave_fermion) +function e_plusmin_down(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(b), I(h), dual(I(h)), dual(I(b)))][2, 1, 1, 2] = sgn * 1 return t end -function e_plusmin_down(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, Trivial, U1Irrep; sf) +function e_plusmin_down(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(b, -1 // 2), I(h, 0), dual(I(h, 0)), dual(I(b, -1 // 2)))] .= sgn * 1 return t end -function e_plusmin_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) +function e_plusmin_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) return error("Not implemented") end -function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, Trivial; sf) +function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(b, 1), I(h, 0), dual(I(h, 0)), dual(I(b, 1)))][2, 1, 1, 2] = sgn * 1 return t end -function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, U1Irrep; sf) +function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, U1Irrep; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(b, 1, -1 // 2), I(h, 0, 0), dual(I(h, 0, 0)), dual(I(b, 1, -1 // 2)))] .= sgn * 1 return t end -function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) +function e_plusmin_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) return error("Not implemented") end const e⁺e⁻ꜜ = e_plusmin_down """ - e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the Hermitian conjugate of `e_plusmin_up`, i.e. ``(e†_{1,↑}, e_{2,↑})† = -e_{1,↑}, e†_{2,↑}`` (note the extra minus sign). It annihilates a spin-up electron at the first site and creates a spin-up electron at the second. The only nonzero matrix element corresponds to `|0↑⟩ <-- |↑0⟩`. """ -e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minplus_up(ComplexF64, - P, S; sf) +e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minplus_up(ComplexF64, + P, + S; + slave_fermion) function e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return copy(adjoint(e_plusmin_up(T, particle_symmetry, spin_symmetry; sf))) + slave_fermion::Bool=false) + return copy(adjoint(e_plusmin_up(T, particle_symmetry, spin_symmetry; slave_fermion))) end const e⁻⁺ꜛ = e_minplus_up """ - e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the Hermitian conjugate of `e_plusmin_down`, i.e. ``(e†_{1,↓}, e_{2,↓})† = -e_{1,↓}, e†_{2,↓}`` (note the extra minus sign). It annihilates a spin-down electron at the first site and creates a spin-down electron at the second. The only nonzero matrix element corresponds to `|0↓⟩ <-- |↓0⟩`. """ -e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minplus_down(ComplexF64, - P, S; - sf) +e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minplus_down(ComplexF64, + P, + S; + slave_fermion) function e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return copy(adjoint(e_plusmin_down(T, particle_symmetry, spin_symmetry; sf))) + slave_fermion::Bool=false) + return copy(adjoint(e_plusmin_down(T, particle_symmetry, spin_symmetry; slave_fermion))) end const e⁻e⁺ꜜ = e_minplus_down """ - e_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body operator that creates a particle at the first site and annihilates a particle at the second. This is the sum of `e_plusmin_up` and `e_plusmin_down`. """ -e_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_plusmin(ComplexF64, P, - S; sf) +e_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_plusmin(ComplexF64, + P, + S; + slave_fermion) function e_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return e_plusmin_up(T, particle_symmetry, spin_symmetry; sf) + - e_plusmin_down(T, particle_symmetry, spin_symmetry; sf) + slave_fermion::Bool=false) + return e_plusmin_up(T, particle_symmetry, spin_symmetry; slave_fermion) + + e_plusmin_down(T, particle_symmetry, spin_symmetry; slave_fermion) end const e⁺e⁻ = e_plusmin """ - e_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body operator that annihilates a particle at the first site and creates a particle at the second. This is the sum of `e_minplus_up` and `e_minplus_down`. """ -e_minplus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minplus(ComplexF64, P, - S; sf) +e_minplus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minplus(ComplexF64, + P, + S; + slave_fermion) function e_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return copy(adjoint(e_plusmin(T, particle_symmetry, spin_symmetry; sf))) + slave_fermion::Bool=false) + return copy(adjoint(e_plusmin(T, particle_symmetry, spin_symmetry; slave_fermion))) end const e⁻e⁺ = e_minplus """ - e_minmin_ud(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_minmin_updown(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body operator ``e_{1,↑} e_{2,↓}`` that annihilates a spin-up particle at the first site and a spin-down particle at the second site. The only nonzero matrix element corresponds to `|00⟩ <-- |↑↓⟩`. """ -e_minmin_ud(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minmin_ud(ComplexF64, - P, S; sf) -function e_minmin_ud(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, Trivial, Trivial; sf) +e_minmin_updown(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minmin_updown(ComplexF64, + P, + S; + slave_fermion) +function e_minmin_updown(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(h), I(h), dual(I(b)), dual(I(b)))][1, 1, 1, 2] = -sgn * 1 return t end -function e_minmin_ud(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, Trivial, U1Irrep; sf) +function e_minmin_updown(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(h, 0), I(h, 0), dual(I(b, 1 // 2)), dual(I(b, -1 // 2)))] .= -sgn * 1 return t end -function e_minmin_ud(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, Trivial; sf) +function e_minmin_updown(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(h, 0), I(h, 0), dual(I(b, 1)), dual(I(b, 1)))][1, 1, 1, 2] = -sgn * 1 return t end -function e_minmin_ud(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, U1Irrep; sf) +function e_minmin_updown(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, U1Irrep; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(h, 0, 0), I(h, 0, 0), dual(I(b, 1, 1 // 2)), dual(I(b, 1, -1 // 2)))] .= -sgn * 1 return t end """ - e_minmin_du(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_minmin_downup(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body operator ``e_{1,↓} e_{2,↑}`` that annihilates a spin-down particle at the first site and a spin-up particle at the second site. The only nonzero matrix element corresponds to `|00⟩ <-- |↓↑⟩`. """ -e_minmin_du(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_minmin_du(ComplexF64, - P, S; sf) -function e_minmin_du(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, Trivial, Trivial; sf) +e_minmin_downup(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minmin_downup(ComplexF64, + P, + S; + slave_fermion) +function e_minmin_downup(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(h), I(h), dual(I(b)), dual(I(b)))][1, 1, 2, 1] = -sgn * 1 return t end -function e_minmin_du(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, Trivial, U1Irrep; sf) +function e_minmin_downup(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(h, 0), I(h, 0), dual(I(b, -1 // 2)), dual(I(b, 1 // 2)))] .= -sgn * 1 return t end -function e_minmin_du(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, Trivial; sf) +function e_minmin_downup(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(h, 0), I(h, 0), dual(I(b, 1)), dual(I(b, 1)))][1, 1, 2, 1] = -sgn * 1 return t end -function e_minmin_du(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, U1Irrep; sf) +function e_minmin_downup(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, U1Irrep; slave_fermion) I = sectortype(t) - (h, b, sgn) = sf ? (1, 0, -1) : (0, 1, 1) + (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) t[(I(h, 0, 0), I(h, 0, 0), dual(I(b, 1, -1 // 2)), dual(I(b, 1, 1 // 2)))] .= -sgn * 1 return t end """ - e_singlet(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_singlet(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body singlet operator ``(e_{1,↓} e_{2,↑} - e_{1,↓} e_{2,↑}) / sqrt(2)``. """ -e_singlet(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_singlet(ComplexF64, P, - S; sf) +e_singlet(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_singlet(ComplexF64, + P, + S; + slave_fermion) function e_singlet(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return (e_minmin_ud(T, particle_symmetry, spin_symmetry; sf) - - e_minmin_du(T, particle_symmetry, spin_symmetry; sf)) / sqrt(2) + slave_fermion::Bool=false) + return (e_minmin_updown(T, particle_symmetry, spin_symmetry; slave_fermion) - + e_minmin_downup(T, particle_symmetry, spin_symmetry; slave_fermion)) / sqrt(2) end """ - e_number_up(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + e_number_up(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the one-body operator that counts the number of spin-up electrons. """ -e_number_up(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_number_up(ComplexF64, - P, S; sf) -function e_number_up(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf) +e_number_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_number_up(ComplexF64, + P, + S; + slave_fermion) +function e_number_up(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; + slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b), dual(I(b)))][1, 1] = 1 return t end -function e_number_up(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, Trivial, U1Irrep; sf) +function e_number_up(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, U1Irrep; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1 // 2), dual(I(b, 1 // 2)))][1, 1] = 1 return t end -function e_number_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) +function e_number_up(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) throw(ArgumentError("`e_number_up` is not symmetric under `SU2Irrep` spin symmetry")) end -function e_number_up(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, U1Irrep, Trivial; sf) +function e_number_up(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1), dual(I(b, 1)))][1, 1] = 1 return t end -function e_number_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, U1Irrep, U1Irrep; sf) +function e_number_up(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, U1Irrep; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1, 1 // 2), dual(I(b, 1, 1 // 2)))] .= 1 return t end -function e_number_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) +function e_number_up(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) throw(ArgumentError("`e_number_up` is not symmetric under `SU2Irrep` spin symmetry")) end const nꜛ = e_number_up """ - e_number_down(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + e_number_down(particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Return the one-body operator that counts the number of spin-down electrons. """ -e_number_down(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_number_down(ComplexF64, - P, S; - sf) -function e_number_down(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf) +e_number_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_number_down(ComplexF64, + P, + S; + slave_fermion) +function e_number_down(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; + slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b), dual(I(b)))][2, 2] = 1 return t end -function e_number_down(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, Trivial, U1Irrep; sf) +function e_number_down(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, U1Irrep; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, -1 // 2), dual(I(b, -1 // 2)))][1, 1] = 1 return t end -function e_number_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; sf::Bool=false) +function e_number_down(T, ::Type{Trivial}, ::Type{SU2Irrep}; slave_fermion::Bool=false) throw(ArgumentError("`e_number_down` is not symmetric under `SU2Irrep` spin symmetry")) end -function e_number_down(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, U1Irrep, Trivial; sf) +function e_number_down(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1), dual(I(b, 1)))][2, 2] = 1 return t end -function e_number_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, U1Irrep, U1Irrep; sf) +function e_number_down(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, U1Irrep; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1, -1 // 2), dual(I(b, 1, -1 // 2)))] .= 1 return t end -function e_number_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; sf::Bool=false) +function e_number_down(T, ::Type{U1Irrep}, ::Type{SU2Irrep}; slave_fermion::Bool=false) throw(ArgumentError("`e_number_down` is not symmetric under `SU2Irrep` spin symmetry")) end const nꜜ = e_number_down """ - e_number(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + e_number(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Return the one-body operator that counts the number of particles. """ -e_number(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_number(ComplexF64, P, S; - sf) +e_number(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_number(ComplexF64, + P, S; + slave_fermion) function e_number(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return e_number_up(T, particle_symmetry, spin_symmetry; sf) + - e_number_down(T, particle_symmetry, spin_symmetry; sf) + slave_fermion::Bool=false) + return e_number_up(T, particle_symmetry, spin_symmetry; slave_fermion) + + e_number_down(T, particle_symmetry, spin_symmetry; slave_fermion) end const n = e_number """ - e_number_hole(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + e_number_hole(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Return the one-body operator that counts the number of holes. """ -e_number_hole(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = e_number_hole(ComplexF64, - P, S; - sf) +e_number_hole(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_number_hole(ComplexF64, + P, + S; + slave_fermion) function e_number_hole(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - iden = TensorKit.id(tj_space(particle_symmetry, spin_symmetry; sf)) - return iden - e_number(T, particle_symmetry, spin_symmetry; sf) + slave_fermion::Bool=false) + iden = TensorKit.id(tj_space(particle_symmetry, spin_symmetry; slave_fermion)) + return iden - e_number(T, particle_symmetry, spin_symmetry; slave_fermion) end const nʰ = e_number_hole """ - S_x(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + S_x(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Return the one-body spin-1/2 x-operator on the electrons. """ -S_x(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; sf::Bool=false) = S_x(ComplexF64, - P, S; sf) -function S_x(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf) +S_x(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; slave_fermion::Bool=false) = S_x(ComplexF64, + P, + S; + slave_fermion) +function S_x(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b), dual(I(b)))][1, 2] = 0.5 t[(I(b), dual(I(b)))][2, 1] = 0.5 return t end -function S_x(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, U1Irrep, Trivial; sf) +function S_x(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1), dual(I(b, 1)))][1, 2] = 0.5 t[(I(b, 1), dual(I(b, 1)))][2, 1] = 0.5 return t @@ -465,24 +492,26 @@ end const Sˣ = S_x """ - S_y(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + S_y(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Return the one-body spin-1/2 x-operator on the electrons (only defined for `Trivial` symmetry). """ -S_y(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; sf::Bool=false) = S_y(ComplexF64, - P, S; sf) -function S_y(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf) +S_y(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; slave_fermion::Bool=false) = S_y(ComplexF64, + P, + S; + slave_fermion) +function S_y(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b), dual(I(b)))][1, 2] = -0.5im t[(I(b), dual(I(b)))][2, 1] = 0.5im return t end -function S_y(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, U1Irrep, Trivial; sf) +function S_y(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1), dual(I(b, 1)))][1, 2] = -0.5im t[(I(b, 1), dual(I(b, 1)))][2, 1] = 0.5im return t @@ -490,40 +519,42 @@ end const Sʸ = S_y """ - S_z(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + S_z(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Return the one-body spin-1/2 z-operator on the electrons. """ -S_z(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; sf::Bool=false) = S_z(ComplexF64, - P, S; sf) -function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, Trivial, Trivial; sf) +S_z(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; slave_fermion::Bool=false) = S_z(ComplexF64, + P, + S; + slave_fermion) +function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b), dual(I(b)))][1, 1] = 0.5 t[(I(b), dual(I(b)))][2, 2] = -0.5 return t end -function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, Trivial, U1Irrep; sf) +function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = single_site_operator(T, Trivial, U1Irrep; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1 // 2), dual(I(b, 1 // 2)))] .= 0.5 t[(I(b, -1 // 2), dual(I(b, -1 // 2)))] .= -0.5 return t end -function S_z(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = single_site_operator(T, U1Irrep, Trivial; sf) +function S_z(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1), dual(I(b, 1)))][1, 1] = 0.5 t[(I(b, 1), dual(I(b, 1)))][2, 2] = -0.5 return t end -function S_z(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - t = single_site_operator(T, U1Irrep, U1Irrep; sf) +function S_z(T::Type{<:Number}, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = single_site_operator(T, U1Irrep, U1Irrep; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1, 1 // 2), dual(I(b, 1, 1 // 2)))] .= 0.5 t[(I(b, 1, -1 // 2), dual(I(b, 1, -1 // 2)))] .= -0.5 return t @@ -531,99 +562,106 @@ end const Sᶻ = S_z """ - S_plus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + S_plus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Return the spin-plus operator. """ -S_plus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_plus(ComplexF64, - P, S; - sf) +S_plus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_plus(ComplexF64, + P, S; + slave_fermion) function S_plus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return S_x(T, particle_symmetry, spin_symmetry; sf) + - 1im * S_y(T, particle_symmetry, spin_symmetry; sf) + slave_fermion::Bool=false) + return S_x(T, particle_symmetry, spin_symmetry; slave_fermion) + + 1im * S_y(T, particle_symmetry, spin_symmetry; slave_fermion) end const S⁺ = S_plus """ - S_min(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool=false) + S_min(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Return the spin-minus operator. """ -S_min(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_min(ComplexF64, - P, S; - sf) +S_min(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_min(ComplexF64, + P, S; + slave_fermion) function S_min(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return S_x(T, particle_symmetry, spin_symmetry; sf) - - 1im * S_y(T, particle_symmetry, spin_symmetry; sf) + slave_fermion::Bool=false) + return S_x(T, particle_symmetry, spin_symmetry; slave_fermion) - + 1im * S_y(T, particle_symmetry, spin_symmetry; slave_fermion) end const S⁻ = S_min """ - S_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + S_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body operator S⁺S⁻. The only nonzero matrix element corresponds to `|↑↓⟩ <-- |↓↑⟩`. """ -S_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_plusmin(ComplexF64, P, - S; sf) -function S_plusmin(T, ::Type{Trivial}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, Trivial, Trivial; sf) +S_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_plusmin(ComplexF64, + P, + S; + slave_fermion) +function S_plusmin(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b), I(b), dual(I(b)), dual(I(b)))][1, 2, 2, 1] = 1 return t end -function S_plusmin(T, ::Type{Trivial}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, Trivial, U1Irrep; sf) +function S_plusmin(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, Trivial, U1Irrep; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1 // 2), I(b, -1 // 2), dual(I(b, -1 // 2)), dual(I(b, 1 // 2)))] .= 1 return t end -function S_plusmin(T, ::Type{U1Irrep}, ::Type{Trivial}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, Trivial; sf) +function S_plusmin(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1), I(b, 1), dual(I(b, 1)), dual(I(b, 1)))][1, 2, 2, 1] = 1 return t end -function S_plusmin(T, ::Type{U1Irrep}, ::Type{U1Irrep}; sf::Bool=false) - t = two_site_operator(T, U1Irrep, U1Irrep; sf) +function S_plusmin(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) + t = two_site_operator(T, U1Irrep, U1Irrep; slave_fermion) I = sectortype(t) - b = sf ? 0 : 1 + b = slave_fermion ? 0 : 1 t[(I(b, 1, 1 // 2), I(b, 1, -1 // 2), dual(I(b, 1, -1 // 2)), dual(I(b, 1, 1 // 2)))] .= 1 return t end """ - S_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + S_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the two-body operator S⁻S⁺. The only nonzero matrix element corresponds to `|↓↑⟩ <-- |↑↓⟩`. """ -S_minplus(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_minplus(ComplexF64, P, - S; sf) +S_minplus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_minplus(ComplexF64, + P, + S; + slave_fermion) function S_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - return copy(adjoint(S_plusmin(T, particle_symmetry, spin_symmetry; sf))) + slave_fermion::Bool=false) + return copy(adjoint(S_plusmin(T, particle_symmetry, spin_symmetry; slave_fermion))) end """ - S_exchange(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; sf::Bool = false) + S_exchange(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) Return the spin exchange operator S⁻S⁺. The only nonzero matrix element corresponds to `|↓↑⟩ <-- |↑↓⟩`. """ -S_exchange(P::Type{<:Sector}, S::Type{<:Sector}; sf::Bool=false) = S_exchange(ComplexF64, P, - S; sf) +S_exchange(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_exchange(ComplexF64, + P, + S; + slave_fermion) function S_exchange(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; - sf::Bool=false) - Sz = S_z(T, particle_symmetry, spin_symmetry; sf) - return (1 / 2) * (S_plusmin(T, particle_symmetry, spin_symmetry; sf) + slave_fermion::Bool=false) + Sz = S_z(T, particle_symmetry, spin_symmetry; slave_fermion) + return (1 / 2) * (S_plusmin(T, particle_symmetry, spin_symmetry; slave_fermion) + - S_minplus(T, particle_symmetry, spin_symmetry; sf)) + Sz ⊗ Sz + S_minplus(T, particle_symmetry, spin_symmetry; slave_fermion)) + + Sz ⊗ Sz end end diff --git a/test/tjoperators.jl b/test/tjoperators.jl index 066a6d4..46765d6 100644 --- a/test/tjoperators.jl +++ b/test/tjoperators.jl @@ -8,36 +8,36 @@ implemented_symmetries = [(Trivial, Trivial), (U1Irrep, Trivial), (U1Irrep, U1Irrep)] @testset "basic properties" begin - for sf in (false, true), + for slave_fermion in (false, true), particle_symmetry in (Trivial, U1Irrep), spin_symmetry in (Trivial, U1Irrep, SU2Irrep) if (particle_symmetry, spin_symmetry) in implemented_symmetries # test hermiticity - @test tJ.e_plusmin(particle_symmetry, spin_symmetry; sf=sf)' ≈ - tJ.e_minplus(particle_symmetry, spin_symmetry; sf=sf) + @test tJ.e_plusmin(particle_symmetry, spin_symmetry; slave_fermion)' ≈ + tJ.e_minplus(particle_symmetry, spin_symmetry; slave_fermion) if spin_symmetry !== SU2Irrep - @test tJ.e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ - tJ.e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) - @test tJ.e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ - tJ.e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) - @test tJ.e_plusmin_down(particle_symmetry, spin_symmetry; sf=sf)' ≈ - tJ.e_minplus_down(particle_symmetry, spin_symmetry; sf=sf) - @test tJ.e_plusmin_up(particle_symmetry, spin_symmetry; sf=sf)' ≈ - tJ.e_minplus_up(particle_symmetry, spin_symmetry; sf=sf) + @test tJ.e_plusmin_down(particle_symmetry, spin_symmetry; slave_fermion)' ≈ + tJ.e_minplus_down(particle_symmetry, spin_symmetry; slave_fermion) + @test tJ.e_plusmin_up(particle_symmetry, spin_symmetry; slave_fermion)' ≈ + tJ.e_minplus_up(particle_symmetry, spin_symmetry; slave_fermion) + @test tJ.e_plusmin_down(particle_symmetry, spin_symmetry; slave_fermion)' ≈ + tJ.e_minplus_down(particle_symmetry, spin_symmetry; slave_fermion) + @test tJ.e_plusmin_up(particle_symmetry, spin_symmetry; slave_fermion)' ≈ + tJ.e_minplus_up(particle_symmetry, spin_symmetry; slave_fermion) end # test number operator if spin_symmetry !== SU2Irrep - pspace = tJ.tj_space(particle_symmetry, spin_symmetry; sf=sf) - @test tJ.e_number(particle_symmetry, spin_symmetry; sf=sf) ≈ - tJ.e_number_up(particle_symmetry, spin_symmetry; sf=sf) + - tJ.e_number_down(particle_symmetry, spin_symmetry; sf=sf) + pspace = tJ.tj_space(particle_symmetry, spin_symmetry; slave_fermion) + @test tJ.e_number(particle_symmetry, spin_symmetry; slave_fermion) ≈ + tJ.e_number_up(particle_symmetry, spin_symmetry; slave_fermion) + + tJ.e_number_down(particle_symmetry, spin_symmetry; slave_fermion) @test TensorMap(zeros, pspace, pspace) ≈ - tJ.e_number_up(particle_symmetry, spin_symmetry; sf=sf) * - tJ.e_number_down(particle_symmetry, spin_symmetry; sf=sf) ≈ - tJ.e_number_down(particle_symmetry, spin_symmetry; sf=sf) * - tJ.e_number_up(particle_symmetry, spin_symmetry; sf=sf) + tJ.e_number_up(particle_symmetry, spin_symmetry; slave_fermion) * + tJ.e_number_down(particle_symmetry, spin_symmetry; slave_fermion) ≈ + tJ.e_number_down(particle_symmetry, spin_symmetry; slave_fermion) * + tJ.e_number_up(particle_symmetry, spin_symmetry; slave_fermion) end # test spin operator @@ -47,9 +47,9 @@ implemented_symmetries = [(Trivial, Trivial), ε[mod1(i, 3), mod1(i + 1, 3), mod1(i + 2, 3)] = 1 ε[mod1(i, 3), mod1(i - 1, 3), mod1(i - 2, 3)] = -1 end - Svec = [tJ.S_x(particle_symmetry, spin_symmetry; sf), - tJ.S_y(particle_symmetry, spin_symmetry; sf), - tJ.S_z(particle_symmetry, spin_symmetry; sf)] + Svec = [tJ.S_x(particle_symmetry, spin_symmetry; slave_fermion), + tJ.S_y(particle_symmetry, spin_symmetry; slave_fermion), + tJ.S_z(particle_symmetry, spin_symmetry; slave_fermion)] # Hermiticity for s in Svec @test s' ≈ s @@ -58,9 +58,9 @@ implemented_symmetries = [(Trivial, Trivial), S = 1 / 2 @test sum(tr(Svec[i]^2) for i in 1:3) / (2S + 1) ≈ S * (S + 1) # test S_plus and S_min - @test tJ.S_plusmin(particle_symmetry, spin_symmetry; sf) ≈ - tJ.S_plus(particle_symmetry, spin_symmetry; sf) ⊗ - tJ.S_min(particle_symmetry, spin_symmetry; sf) + @test tJ.S_plusmin(particle_symmetry, spin_symmetry; slave_fermion) ≈ + tJ.S_plus(particle_symmetry, spin_symmetry; slave_fermion) ⊗ + tJ.S_min(particle_symmetry, spin_symmetry; slave_fermion) # commutation relations for i in 1:3, j in 1:3 @test Svec[i] * Svec[j] - Svec[j] * Svec[i] ≈ @@ -68,21 +68,21 @@ implemented_symmetries = [(Trivial, Trivial), end end else - @test_broken tJ.e_plusmin(particle_symmetry, spin_symmetry; sf=sf) - @test_broken tJ.e_minplus(particle_symmetry, spin_symmetry; sf=sf) + @test_broken tJ.e_plusmin(particle_symmetry, spin_symmetry; slave_fermion) + @test_broken tJ.e_minplus(particle_symmetry, spin_symmetry; slave_fermion) end end end -function hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, sf) - num = tJ.e_number(particle_symmetry, spin_symmetry; sf=sf) - hop_heis = (-t) * (tJ.e_plusmin(particle_symmetry, spin_symmetry; sf=sf) + - tJ.e_minplus(particle_symmetry, spin_symmetry; sf=sf)) + +function hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, slave_fermion) + num = tJ.e_number(particle_symmetry, spin_symmetry; slave_fermion) + hop_heis = (-t) * (tJ.e_plusmin(particle_symmetry, spin_symmetry; slave_fermion) + + tJ.e_minplus(particle_symmetry, spin_symmetry; slave_fermion)) + J * - (tJ.S_exchange(particle_symmetry, spin_symmetry; sf=sf) - + (tJ.S_exchange(particle_symmetry, spin_symmetry; slave_fermion) - (1 / 4) * (num ⊗ num)) chemical_potential = (-mu) * num - I = id(tJ.tj_space(particle_symmetry, spin_symmetry; sf=sf)) + I = id(tJ.tj_space(particle_symmetry, spin_symmetry; slave_fermion)) H = sum(1:(L - 1)) do i return reduce(⊗, insert!(collect(Any, fill(I, L - 2)), i, hop_heis)) end + sum(1:L) do i @@ -97,8 +97,8 @@ end J = randn() mu = randn() - for sf in (false, true) - H_triv = hamiltonian(Trivial, Trivial; t, J, mu, L, sf) + for slave_fermion in (false, true) + H_triv = hamiltonian(Trivial, Trivial; t, J, mu, L, slave_fermion) vals_triv = mapreduce(vcat, eigvals(H_triv)) do (c, v) return repeat(real.(v), dim(c)) end @@ -108,7 +108,8 @@ end if (particle_symmetry, spin_symmetry) == (Trivial, Trivial) continue end - H_symm = hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, sf) + H_symm = hamiltonian(particle_symmetry, spin_symmetry; t, J, mu, L, + slave_fermion) vals_symm = mapreduce(vcat, eigvals(H_symm)) do (c, v) return repeat(real.(v), dim(c)) end From 29bfcbe641fd297daeda4238a23505b42b78c134 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Mon, 2 Dec 2024 11:49:36 +0800 Subject: [PATCH 12/14] Remove invalid definition of `e_minmin` --- src/operators/tjoperators.jl | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index ebc7a8c..2e9e7f9 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -272,19 +272,8 @@ function e_minmin_updown(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Boo t[(I(h, 0), I(h, 0), dual(I(b, 1 // 2)), dual(I(b, -1 // 2)))] .= -sgn * 1 return t end -function e_minmin_updown(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) - t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) - I = sectortype(t) - (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) - t[(I(h, 0), I(h, 0), dual(I(b, 1)), dual(I(b, 1)))][1, 1, 1, 2] = -sgn * 1 - return t -end -function e_minmin_updown(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) - t = two_site_operator(T, U1Irrep, U1Irrep; slave_fermion) - I = sectortype(t) - (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) - t[(I(h, 0, 0), I(h, 0, 0), dual(I(b, 1, 1 // 2)), dual(I(b, 1, -1 // 2)))] .= -sgn * 1 - return t +function e_minmin_updown(T, ::Type{U1Irrep}, ::Type{<:Sector}; slave_fermion::Bool=false) + throw(ArgumentError("`e_minmin_updown` is not symmetric under `U1Irrep` particle symmetry")) end """ @@ -311,19 +300,8 @@ function e_minmin_downup(T, ::Type{Trivial}, ::Type{U1Irrep}; slave_fermion::Boo t[(I(h, 0), I(h, 0), dual(I(b, -1 // 2)), dual(I(b, 1 // 2)))] .= -sgn * 1 return t end -function e_minmin_downup(T, ::Type{U1Irrep}, ::Type{Trivial}; slave_fermion::Bool=false) - t = two_site_operator(T, U1Irrep, Trivial; slave_fermion) - I = sectortype(t) - (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) - t[(I(h, 0), I(h, 0), dual(I(b, 1)), dual(I(b, 1)))][1, 1, 2, 1] = -sgn * 1 - return t -end -function e_minmin_downup(T, ::Type{U1Irrep}, ::Type{U1Irrep}; slave_fermion::Bool=false) - t = two_site_operator(T, U1Irrep, U1Irrep; slave_fermion) - I = sectortype(t) - (h, b, sgn) = slave_fermion ? (1, 0, -1) : (0, 1, 1) - t[(I(h, 0, 0), I(h, 0, 0), dual(I(b, 1, -1 // 2)), dual(I(b, 1, 1 // 2)))] .= -sgn * 1 - return t +function e_minmin_downup(T, ::Type{U1Irrep}, ::Type{<:Sector}; slave_fermion::Bool=false) + throw(ArgumentError("`e_minmin_downup` is not symmetric under `U1Irrep` particle symmetry")) end """ From 395369d24193f8b2bfac93ccf885091580fbb2ae Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 2 Dec 2024 17:00:12 -0500 Subject: [PATCH 13/14] formatting updates --- src/operators/tjoperators.jl | 150 ++++++++++++++++------------------- 1 file changed, 67 insertions(+), 83 deletions(-) diff --git a/src/operators/tjoperators.jl b/src/operators/tjoperators.jl index 2e9e7f9..a93536f 100644 --- a/src/operators/tjoperators.jl +++ b/src/operators/tjoperators.jl @@ -86,10 +86,9 @@ end Return the two-body operator ``e†_{1,↑}, e_{2,↑}`` that creates a spin-up electron at the first site and annihilates a spin-up electron at the second. The only nonzero matrix element corresponds to `|↑0⟩ <-- |0↑⟩`. """ -e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_plusmin_up(ComplexF64, - P, - S; - slave_fermion) +function e_plusmin_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_plusmin_up(ComplexF64, P, S; slave_fermion) +end function e_plusmin_up(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) @@ -139,10 +138,9 @@ const e⁺e⁻ꜛ = e_plusmin_up Return the two-body operator ``e†_{1,↓}, e_{2,↓}`` that creates a spin-down electron at the first site and annihilates a spin-down electron at the second. The only nonzero matrix element corresponds to `|↓0⟩ <-- |0↓⟩`. """ -e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_plusmin_down(ComplexF64, - P, - S; - slave_fermion) +function e_plusmin_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_plusmin_down(ComplexF64, P, S; slave_fermion) +end function e_plusmin_down(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) @@ -187,10 +185,9 @@ Return the Hermitian conjugate of `e_plusmin_up`, i.e. It annihilates a spin-up electron at the first site and creates a spin-up electron at the second. The only nonzero matrix element corresponds to `|0↑⟩ <-- |↑0⟩`. """ -e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minplus_up(ComplexF64, - P, - S; - slave_fermion) +function e_minplus_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_minplus_up(ComplexF64, P, S; slave_fermion) +end function e_minplus_up(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return copy(adjoint(e_plusmin_up(T, particle_symmetry, spin_symmetry; slave_fermion))) @@ -205,10 +202,9 @@ Return the Hermitian conjugate of `e_plusmin_down`, i.e. It annihilates a spin-down electron at the first site and creates a spin-down electron at the second. The only nonzero matrix element corresponds to `|0↓⟩ <-- |↓0⟩`. """ -e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minplus_down(ComplexF64, - P, - S; - slave_fermion) +function e_minplus_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_minplus_down(ComplexF64, P, S; slave_fermion) +end function e_minplus_down(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return copy(adjoint(e_plusmin_down(T, particle_symmetry, spin_symmetry; slave_fermion))) @@ -221,10 +217,9 @@ const e⁻e⁺ꜜ = e_minplus_down Return the two-body operator that creates a particle at the first site and annihilates a particle at the second. This is the sum of `e_plusmin_up` and `e_plusmin_down`. """ -e_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_plusmin(ComplexF64, - P, - S; - slave_fermion) +function e_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_plusmin(ComplexF64, P, S; slave_fermion) +end function e_plusmin(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return e_plusmin_up(T, particle_symmetry, spin_symmetry; slave_fermion) + @@ -238,10 +233,9 @@ const e⁺e⁻ = e_plusmin Return the two-body operator that annihilates a particle at the first site and creates a particle at the second. This is the sum of `e_minplus_up` and `e_minplus_down`. """ -e_minplus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minplus(ComplexF64, - P, - S; - slave_fermion) +function e_minplus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_minplus(ComplexF64, P, S; slave_fermion) +end function e_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return copy(adjoint(e_plusmin(T, particle_symmetry, spin_symmetry; slave_fermion))) @@ -254,10 +248,9 @@ const e⁻e⁺ = e_minplus Return the two-body operator ``e_{1,↑} e_{2,↓}`` that annihilates a spin-up particle at the first site and a spin-down particle at the second site. The only nonzero matrix element corresponds to `|00⟩ <-- |↑↓⟩`. """ -e_minmin_updown(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minmin_updown(ComplexF64, - P, - S; - slave_fermion) +function e_minmin_updown(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_minmin_updown(ComplexF64, P, S; slave_fermion) +end function e_minmin_updown(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) @@ -282,10 +275,9 @@ end Return the two-body operator ``e_{1,↓} e_{2,↑}`` that annihilates a spin-down particle at the first site and a spin-up particle at the second site. The only nonzero matrix element corresponds to `|00⟩ <-- |↓↑⟩`. """ -e_minmin_downup(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_minmin_downup(ComplexF64, - P, - S; - slave_fermion) +function e_minmin_downup(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_minmin_downup(ComplexF64, P, S; slave_fermion) +end function e_minmin_downup(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) @@ -309,10 +301,9 @@ end Return the two-body singlet operator ``(e_{1,↓} e_{2,↑} - e_{1,↓} e_{2,↑}) / sqrt(2)``. """ -e_singlet(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_singlet(ComplexF64, - P, - S; - slave_fermion) +function e_singlet(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_singlet(ComplexF64, P, S; slave_fermion) +end function e_singlet(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return (e_minmin_updown(T, particle_symmetry, spin_symmetry; slave_fermion) - @@ -324,10 +315,9 @@ end Return the one-body operator that counts the number of spin-up electrons. """ -e_number_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_number_up(ComplexF64, - P, - S; - slave_fermion) +function e_number_up(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_number_up(ComplexF64, P, S; slave_fermion) +end function e_number_up(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = single_site_operator(T, Trivial, Trivial; slave_fermion) @@ -370,10 +360,9 @@ const nꜛ = e_number_up Return the one-body operator that counts the number of spin-down electrons. """ -e_number_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_number_down(ComplexF64, - P, - S; - slave_fermion) +function e_number_down(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_number_down(ComplexF64, P, S; slave_fermion) +end function e_number_down(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = single_site_operator(T, Trivial, Trivial; slave_fermion) @@ -416,9 +405,9 @@ const nꜜ = e_number_down Return the one-body operator that counts the number of particles. """ -e_number(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_number(ComplexF64, - P, S; - slave_fermion) +function e_number(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_number(ComplexF64, P, S; slave_fermion) +end function e_number(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return e_number_up(T, particle_symmetry, spin_symmetry; slave_fermion) + @@ -431,10 +420,9 @@ const n = e_number Return the one-body operator that counts the number of holes. """ -e_number_hole(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = e_number_hole(ComplexF64, - P, - S; - slave_fermion) +function e_number_hole(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return e_number_hole(ComplexF64, P, S; slave_fermion) +end function e_number_hole(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) iden = TensorKit.id(tj_space(particle_symmetry, spin_symmetry; slave_fermion)) @@ -447,10 +435,10 @@ const nʰ = e_number_hole Return the one-body spin-1/2 x-operator on the electrons. """ -S_x(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; slave_fermion::Bool=false) = S_x(ComplexF64, - P, - S; - slave_fermion) +function S_x(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; + slave_fermion::Bool=false) + return S_x(ComplexF64, P, S; slave_fermion) +end function S_x(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = single_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) @@ -474,10 +462,10 @@ const Sˣ = S_x Return the one-body spin-1/2 x-operator on the electrons (only defined for `Trivial` symmetry). """ -S_y(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; slave_fermion::Bool=false) = S_y(ComplexF64, - P, - S; - slave_fermion) +function S_y(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; + slave_fermion::Bool=false) + return S_y(ComplexF64, P, S; slave_fermion) +end function S_y(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = single_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) @@ -501,10 +489,10 @@ const Sʸ = S_y Return the one-body spin-1/2 z-operator on the electrons. """ -S_z(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; slave_fermion::Bool=false) = S_z(ComplexF64, - P, - S; - slave_fermion) +function S_z(P::Type{<:Sector}=Trivial, S::Type{<:Sector}=Trivial; + slave_fermion::Bool=false) + return S_z(ComplexF64, P, S; slave_fermion) +end function S_z(T::Type{<:Number}, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = single_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) @@ -544,9 +532,9 @@ const Sᶻ = S_z Return the spin-plus operator. """ -S_plus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_plus(ComplexF64, - P, S; - slave_fermion) +function S_plus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return S_plus(ComplexF64, P, S; slave_fermion) +end function S_plus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return S_x(T, particle_symmetry, spin_symmetry; slave_fermion) + @@ -559,9 +547,9 @@ const S⁺ = S_plus Return the spin-minus operator. """ -S_min(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_min(ComplexF64, - P, S; - slave_fermion) +function S_min(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return S_min(ComplexF64, P, S; slave_fermion) +end function S_min(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return S_x(T, particle_symmetry, spin_symmetry; slave_fermion) - @@ -575,10 +563,9 @@ const S⁻ = S_min Return the two-body operator S⁺S⁻. The only nonzero matrix element corresponds to `|↑↓⟩ <-- |↓↑⟩`. """ -S_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_plusmin(ComplexF64, - P, - S; - slave_fermion) +function S_plusmin(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return S_plusmin(ComplexF64, P, S; slave_fermion) +end function S_plusmin(T, ::Type{Trivial}, ::Type{Trivial}; slave_fermion::Bool=false) t = two_site_operator(T, Trivial, Trivial; slave_fermion) I = sectortype(t) @@ -614,10 +601,9 @@ end Return the two-body operator S⁻S⁺. The only nonzero matrix element corresponds to `|↓↑⟩ <-- |↑↓⟩`. """ -S_minplus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_minplus(ComplexF64, - P, - S; - slave_fermion) +function S_minplus(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return S_minplus(ComplexF64, P, S; slave_fermion) +end function S_minplus(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) return copy(adjoint(S_plusmin(T, particle_symmetry, spin_symmetry; slave_fermion))) @@ -626,13 +612,11 @@ end """ S_exchange(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool = false) -Return the spin exchange operator S⁻S⁺. -The only nonzero matrix element corresponds to `|↓↑⟩ <-- |↑↓⟩`. +Return the spin exchange operator S⋅S. """ -S_exchange(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) = S_exchange(ComplexF64, - P, - S; - slave_fermion) +function S_exchange(P::Type{<:Sector}, S::Type{<:Sector}; slave_fermion::Bool=false) + return S_exchange(ComplexF64, P, S; slave_fermion) +end function S_exchange(T, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}; slave_fermion::Bool=false) Sz = S_z(T, particle_symmetry, spin_symmetry; slave_fermion) From 75345bb89da0994b334c1bc79c711e50f9337e02 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 2 Dec 2024 17:02:27 -0500 Subject: [PATCH 14/14] remove type alias --- src/MPSKitModels.jl | 1 - src/models/hamiltonians.jl | 14 ++++++-------- test/tjoperators.jl | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/MPSKitModels.jl b/src/MPSKitModels.jl index 0d8fc38..e46d026 100644 --- a/src/MPSKitModels.jl +++ b/src/MPSKitModels.jl @@ -71,7 +71,6 @@ using .HubbardOperators # and is only imported to avoid name conflicts include("operators/tjoperators.jl") import .TJOperators -const tJ = TJOperators include("operators/bosonoperators.jl") include("models/hamiltonians.jl") diff --git a/src/models/hamiltonians.jl b/src/models/hamiltonians.jl index 04ec904..1d441f2 100644 --- a/src/models/hamiltonians.jl +++ b/src/models/hamiltonians.jl @@ -404,14 +404,12 @@ function tj_model(T::Type{<:Number}=ComplexF64, particle_symmetry::Type{<:Sector}=Trivial, spin_symmetry::Type{<:Sector}=Trivial, lattice::AbstractLattice=InfiniteChain(1); - t=2.5, - J=1.0, - mu=0.0, - slave_fermion::Bool=false,) - hopping = tJ.e_plusmin(T, particle_symmetry, spin_symmetry; slave_fermion) + - tJ.e_minplus(T, particle_symmetry, spin_symmetry; slave_fermion) - num = tJ.e_number(T, particle_symmetry, spin_symmetry; slave_fermion) - heisenberg = tJ.S_exchange(T, particle_symmetry, spin_symmetry; slave_fermion) - + t=2.5, J=1.0, mu=0.0, slave_fermion::Bool=false) + hopping = TJOperators.e_plusmin(T, particle_symmetry, spin_symmetry; slave_fermion) + + TJOperators.e_minplus(T, particle_symmetry, spin_symmetry; slave_fermion) + num = TJOperators.e_number(T, particle_symmetry, spin_symmetry; slave_fermion) + heisenberg = TJOperators.S_exchange(T, particle_symmetry, spin_symmetry; + slave_fermion) - (1 / 4) * (num ⊗ num) return @mpoham begin sum(nearest_neighbours(lattice)) do (i, j) diff --git a/test/tjoperators.jl b/test/tjoperators.jl index 46765d6..fa71421 100644 --- a/test/tjoperators.jl +++ b/test/tjoperators.jl @@ -1,7 +1,7 @@ using Test using TensorKit using LinearAlgebra: eigvals -import MPSKitModels: tJ +import MPSKitModels: TJOperators as tJ implemented_symmetries = [(Trivial, Trivial), (Trivial, U1Irrep),