Skip to content

Commit a59d1c0

Browse files
authored
Add tests for fermionic periodic boundary conditions (#274)
* Fix and tests fermionic PBC * Refactor ambiguous braiding checks * Circumvent unsupported tensorkit feature * formatting * Fixes attempt II * Fix tests * remove twists * Clean up utility
1 parent 939c885 commit a59d1c0

File tree

4 files changed

+91
-21
lines changed

4 files changed

+91
-21
lines changed

src/transfermatrix/transfer.jl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,25 +68,21 @@ end
6868
# the transfer operation of a density matrix with a utility leg in its codomain is ill defined - how should one braid the utility leg?
6969
# hence the checks - to make sure that this operation is uniquely defined
7070
function transfer_left(v::MPSTensor{S}, A::MPSTensor{S}, Ab::MPSTensor{S}) where {S}
71-
_can_unambiguously_braid(space(v, 2)) ||
72-
throw(ArgumentError("transfer is not uniquely defined with utility space $(space(v,2))"))
71+
check_unambiguous_braiding(space(v, 2))
7372
@plansor v[-1 -2; -3] := v[1 2; 4] * A[4 5; -3] * τ[2 3; 5 -2] * conj(Ab[1 3; -1])
7473
end
7574
function transfer_right(v::MPSTensor{S}, A::MPSTensor{S}, Ab::MPSTensor{S}) where {S}
76-
_can_unambiguously_braid(space(v, 2)) ||
77-
throw(ArgumentError("transfer is not uniquely defined with utility space $(space(v,2))"))
75+
check_unambiguous_braiding(space(v, 2))
7876
@plansor v[-1 -2; -3] := A[-1 2; 1] * τ[-2 4; 2 3] * conj(Ab[-3 4; 5]) * v[1 3; 5]
7977
end
8078

8179
# the transfer operation with a utility leg in both the domain and codomain is also ill defined - only due to the codomain utility space
8280
function transfer_left(v::MPOTensor{S}, A::MPSTensor{S}, Ab::MPSTensor{S}) where {S}
83-
_can_unambiguously_braid(space(v, 2)) ||
84-
throw(ArgumentError("transfer is not uniquely defined with utility space $(space(v,2))"))
81+
check_unambiguous_braiding(space(v, 2))
8582
@plansor t[-1 -2; -3 -4] := v[1 2; -3 4] * A[4 5; -4] * τ[2 3; 5 -2] * conj(Ab[1 3; -1])
8683
end
8784
function transfer_right(v::MPOTensor{S}, A::MPSTensor{S}, Ab::MPSTensor{S}) where {S}
88-
_can_unambiguously_braid(space(v, 2)) ||
89-
throw(ArgumentError("transfer is not uniquely defined with utility space $(space(v,2))"))
85+
check_unambiguous_braiding(space(v, 2))
9086
@plansor t[-1 -2; -3 -4] := A[-1 2; 1] * τ[-2 4; 2 3] * conj(Ab[-4 4; 5]) * v[1 3; -3 5]
9187
end
9288

src/utility/utility.jl

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,6 @@ function _embedders(spaces)
8989
return maps
9090
end
9191

92-
function _can_unambiguously_braid(sp::VectorSpace)
93-
s = sectortype(sp)
94-
95-
BraidingStyle(s) isa SymmetricBraiding && return true
96-
97-
# if it's not symmetric, then we are only really garantueed that this is possible when only one irrep occurs - the trivial one
98-
for sect in sectors(sp)
99-
sect == one(sect) || return false
100-
end
101-
return true
102-
end
103-
10492
#=
10593
map every element in the tensormap to dfun(E)
10694
allows us to create random tensormaps for any storagetype
@@ -143,3 +131,21 @@ end
143131
function fuser(::Type{T}, V1::S, V2::S) where {T,S<:IndexSpace}
144132
return isomorphism(T, fuse(V1 V2), V1 V2)
145133
end
134+
135+
"""
136+
check_unambiguous_braiding(::Type{Bool}, V::VectorSpace)::Bool
137+
check_unambiguous_braiding(V::VectorSpace)
138+
139+
Verify that the braiding of a vector space is unambiguous. This is the case if the braiding
140+
is symmetric or if all sectors are trivial. The signature with `Type{Bool}` is used to check
141+
while the signature without is used to throw an error if the braiding is ambiguous.
142+
"""
143+
function check_unambiguous_braiding(::Type{Bool}, V::VectorSpace)
144+
I = sectortype(V)
145+
BraidingStyle(I) isa SymmetricBraiding && return true
146+
return all(isone, sectors(V))
147+
end
148+
function check_unambiguous_braiding(V::VectorSpace)
149+
return check_unambiguous_braiding(Bool, V) ||
150+
throw(ArgumentError("cannot unambiguously braid $V"))
151+
end

test/algorithms.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,17 @@ end
766766
permute(TH, ((vcat(N, 1:(N - 1))...,), (vcat(2N, (N + 1):(2N - 1))...,)))
767767
end
768768
end
769+
770+
# fermionic tests
771+
for N in 3:5
772+
h = real(c_plusmin() + c_minplus())
773+
H = InfiniteMPOHamiltonian([space(h, 1)], (1, 2) => h)
774+
H_periodic = periodic_boundary_conditions(H, N)
775+
terms = [(i, i + 1) => h for i in 1:(N - 1)]
776+
push!(terms, (1, N) => h)
777+
H_periodic2 = FiniteMPOHamiltonian(physicalspace(H_periodic), terms)
778+
@test H_periodic H_periodic2
779+
end
769780
end
770781

771782
@testset "TaylorCluster time evolution" begin

test/setup.jl

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ using Combinatorics: permutations
1313

1414
# exports
1515
export S_xx, S_yy, S_zz, S_x, S_y, S_z
16+
export c_plusmin, c_minplus, c_number
1617
export force_planar
1718
export symm_mul_mpo
18-
export transverse_field_ising, heisenberg_XXX, bilinear_biquadratic_model, XY_model
19+
export transverse_field_ising, heisenberg_XXX, bilinear_biquadratic_model, XY_model,
20+
kitaev_model
1921
export classical_ising, finite_classical_ising, sixvertex
2022

2123
# using TensorOperations
@@ -224,6 +226,61 @@ function bilinear_biquadratic_model(::Type{SU2Irrep}; θ=atan(1 / 3), L=Inf)
224226
end
225227
end
226228

229+
function c_plusmin()
230+
P = Vect[FermionParity](0 => 1, 1 => 1)
231+
t = zeros(ComplexF64, P^2 P^2)
232+
I = sectortype(P)
233+
t[(I(1), I(0), dual(I(0)), dual(I(1)))] .= 1
234+
return t
235+
end
236+
237+
function c_minplus()
238+
P = Vect[FermionParity](0 => 1, 1 => 1)
239+
t = zeros(ComplexF64, P^2 P^2)
240+
I = sectortype(t)
241+
t[(I(0), I(1), dual(I(1)), dual(I(0)))] .= 1
242+
return t
243+
end
244+
245+
function c_plusplus()
246+
P = Vect[FermionParity](0 => 1, 1 => 1)
247+
t = zeros(ComplexF64, P^2 P^2)
248+
I = sectortype(t)
249+
t[(I(1), I(1), dual(I(0)), dual(I(0)))] .= 1
250+
return t
251+
end
252+
253+
function c_minmin()
254+
P = Vect[FermionParity](0 => 1, 1 => 1)
255+
t = zeros(ComplexF64, P^2 P^2)
256+
I = sectortype(t)
257+
t[(I(0), I(0), dual(I(1)), dual(I(1)))] .= 1
258+
return t
259+
end
260+
261+
function c_number()
262+
P = Vect[FermionParity](0 => 1, 1 => 1)
263+
t = zeros(ComplexF64, P P)
264+
block(t, fℤ₂(1)) .= 1
265+
return t
266+
end
267+
268+
function kitaev_model(; t=1.0, mu=1.0, Delta=1.0, L=Inf)
269+
TB = scale!(c_plusmin() + c_minplus(), -t / 2) # tight-binding term
270+
SC = scale!(c_plusplus() + c_minmin(), Delta / 2) # superconducting term
271+
CP = scale!(c_number(), -mu) # chemical potential term
272+
273+
if L == Inf
274+
lattice = PeriodicArray([space(TB, 1)])
275+
return InfiniteMPOHamiltonian(lattice, (1, 2) => TB + SC, (1,) => CP)
276+
else
277+
lattice = fill(space(TB, 1), L)
278+
terms = Iterators.flatten((((i, i + 1) => TB + SC for i in 1:(L - 1)),
279+
(i,) => CP for i in 1:L))
280+
return FiniteMPOHamiltonian(lattice, terms)
281+
end
282+
end
283+
227284
function ising_bond_tensor(β)
228285
t = [exp(β) exp(-β); exp(-β) exp(β)]
229286
r = eigen(t)

0 commit comments

Comments
 (0)