Skip to content
8 changes: 7 additions & 1 deletion src/PEPSKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ using LinearAlgebra, Statistics, Base.Threads, Base.Iterators, Printf
using Compat
using Accessors: @set, @reset
using VectorInterface
using TensorKit, KrylovKit, MPSKit, OptimKit, TensorOperations
using TensorKit, KrylovKit, OptimKit, TensorOperations
using ChainRulesCore, Zygote
using LoggingExtras

using MPSKit
using MPSKit: MPOTensor, GenericMPSTensor, MPSBondTensor, TransferMatrix
import MPSKit: leading_boundary, loginit!, logiter!, logfinish!, logcancel!, physicalspace

using MPSKitModels
using FiniteDifferences
using OhMyThreads: tmap
Expand Down Expand Up @@ -65,6 +69,7 @@ include("algorithms/time_evolution/simpleupdate.jl")
include("algorithms/time_evolution/simpleupdate3site.jl")

include("algorithms/toolbox.jl")
include("algorithms/correlators.jl")

include("utility/symmetrization.jl")

Expand All @@ -80,6 +85,7 @@ export CTMRGEnv, SequentialCTMRG, SimultaneousCTMRG
export FixedSpaceTruncation, HalfInfiniteProjector, FullInfiniteProjector
export LocalOperator, physicalspace
export expectation_value, cost_function, product_peps, correlation_length, network_value
export correlator
export leading_boundary
export PEPSOptimize, GeomSum, ManualIter, LinSolver, EigSolver
export fixedpoint
Expand Down
17 changes: 15 additions & 2 deletions src/algorithms/contractions/vumps_contractions.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using MPSKit: GenericMPSTensor, MPSBondTensor

#
# Environment transfer functions
#
Expand Down Expand Up @@ -40,6 +38,21 @@
A[χ_NW D_N_above D_N_below; χ_NE]
end

# transfer with excited GL
function MPSKit.transfer_left(

Check warning on line 42 in src/algorithms/contractions/vumps_contractions.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/contractions/vumps_contractions.jl#L42

Added line #L42 was not covered by tests
GL::GenericMPSTensor{S,4},
O::PEPSSandwich,
A::GenericMPSTensor{S,3},
Ā::GenericMPSTensor{S,3},
) where {S}
@autoopt @tensor GL′[χ_SE D_E_above d_string D_E_below; χ_NE] :=

Check warning on line 48 in src/algorithms/contractions/vumps_contractions.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/contractions/vumps_contractions.jl#L48

Added line #L48 was not covered by tests
GL[χ_SW D_W_above d_string D_W_below; χ_NW] *
conj(Ā[χ_SW D_S_above D_S_below; χ_SE]) *
ket(O)[d; D_N_above D_E_above D_S_above D_W_above] *
conj(bra(O)[d; D_N_below D_E_below D_S_below D_W_below]) *
A[χ_NW D_N_above D_N_below; χ_NE]
end

function _transfer_right(
GR::GenericMPSTensor{S,3},
O::PEPSSandwich,
Expand Down
199 changes: 199 additions & 0 deletions src/algorithms/correlators.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
function correlator_horizontal(

Check warning on line 1 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L1

Added line #L1 was not covered by tests
bra::InfinitePEPS,
operator,
i::CartesianIndex{2},
js::AbstractVector{CartesianIndex{2}},
ket::InfinitePEPS,
env::CTMRGEnv,
)
size(ket) == size(bra) ||

Check warning on line 9 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L9

Added line #L9 was not covered by tests
throw(DimensionMismatch("The ket and bra must have the same unit cell."))
all(==(i[1]) ∘ first ∘ Tuple, js) ||

Check warning on line 11 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L11

Added line #L11 was not covered by tests
throw(ArgumentError("Not a horizontal correlation function"))
issorted(vcat(i, js); by=last ∘ Tuple) ||

Check warning on line 13 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L13

Added line #L13 was not covered by tests
throw(ArgumentError("Not an increasing sequence of coordinates"))

O = FiniteMPO(operator)
length(O) == 2 || throw(ArgumentError("Operator must act on two sites"))

Check warning on line 17 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L16-L17

Added lines #L16 - L17 were not covered by tests

# preallocate with correct scalartype
G = similar(

Check warning on line 20 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L20

Added line #L20 was not covered by tests
js,
TensorOperations.promote_contract(
scalartype(bra), scalartype(ket), scalartype(env), scalartype.(O)...
),
)

# left start for operator and norm contractions
Vn, Vo = start_correlator(i, bra, O[1], ket, env)
i += CartesianIndex(0, 1)

Check warning on line 29 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L28-L29

Added lines #L28 - L29 were not covered by tests

for (k, j) in enumerate(js)

Check warning on line 31 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L31

Added line #L31 was not covered by tests
# transfer until left of site j
while j > i
Atop = env.edges[NORTH, _prev(i[1], end), mod1(i[2], end)]
Abot = env.edges[SOUTH, _next(i[1], end), mod1(i[2], end)]
sandwich = (

Check warning on line 36 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L33-L36

Added lines #L33 - L36 were not covered by tests
ket[mod1(i[1], end), mod1(i[2], end)], bra[mod1(i[1], end), mod1(i[2], end)]
)
T = TransferMatrix(Atop, sandwich, _dag(Abot))
Vo = Vo * T
Vn = Vn * T
i += CartesianIndex(0, 1)
end

Check warning on line 43 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L39-L43

Added lines #L39 - L43 were not covered by tests

# compute overlap with operator
numerator = end_correlator_numerator(j, Vo, bra, O[2], ket, env)

Check warning on line 46 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L46

Added line #L46 was not covered by tests

# transfer right of site j
Atop = env.edges[NORTH, _prev(i[1], end), mod1(i[2], end)]
Abot = env.edges[SOUTH, _next(i[1], end), mod1(i[2], end)]
sandwich = (

Check warning on line 51 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L49-L51

Added lines #L49 - L51 were not covered by tests
ket[mod1(i[1], end), mod1(i[2], end)], bra[mod1(i[1], end), mod1(i[2], end)]
)
T = TransferMatrix(Atop, sandwich, _dag(Abot))
Vo = Vo * T
Vn = Vn * T
i += CartesianIndex(0, 1)

Check warning on line 57 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L54-L57

Added lines #L54 - L57 were not covered by tests

# compute overlap without operator
denominator = end_correlator_denominator(j, Vn, env)

Check warning on line 60 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L60

Added line #L60 was not covered by tests

G[k] = numerator / denominator
end

Check warning on line 63 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L62-L63

Added lines #L62 - L63 were not covered by tests

return G

Check warning on line 65 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L65

Added line #L65 was not covered by tests
end

function start_correlator(

Check warning on line 68 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L68

Added line #L68 was not covered by tests
i::CartesianIndex{2},
below::InfinitePEPS,
O::MPOTensor,
above::InfinitePEPS,
env::CTMRGEnv,
)
r, c = Tuple(i)
E_north = env.edges[NORTH, _prev(r, end), mod1(c, end)]
E_south = env.edges[SOUTH, _next(r, end), mod1(c, end)]
E_west = env.edges[WEST, mod1(r, end), _prev(c, end)]
C_northwest = env.corners[NORTHWEST, _prev(r, end), _prev(c, end)]
C_southwest = env.corners[SOUTHWEST, _next(r, end), _prev(c, end)]
sandwich = (below[mod1(r, end), mod1(c, end)], above[mod1(r, end), mod1(c, end)])

Check warning on line 81 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L75-L81

Added lines #L75 - L81 were not covered by tests

# TODO: part of these contractions is duplicated between the two output tensors,
# so could be optimized further
@autoopt @tensor Vn[χSE Detop Debot; χNE] :=

Check warning on line 85 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L85

Added line #L85 was not covered by tests
E_south[χSE Dstop Dsbot; χSW2] *
C_southwest[χSW2; χSW] *
E_west[χSW Dwtop Dwbot; χNW] *
C_northwest[χNW; χN] *
conj(bra(sandwich)[d; Dnbot Debot Dsbot Dwbot]) *
ket(sandwich)[d; Dntop Detop Dstop Dwtop] *
E_north[χN Dntop Dnbot; χNE]

@autoopt @tensor Vo[χSE Detop dstring Debot; χNE] :=

Check warning on line 94 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L94

Added line #L94 was not covered by tests
E_south[χSE Dstop Dsbot; χSW2] *
C_southwest[χSW2; χSW] *
E_west[χSW Dwtop Dwbot; χNW] *
C_northwest[χNW; χN] *
conj(bra(sandwich)[d1; Dnbot Debot Dsbot Dwbot]) *
removeunit(O, 1)[d1; d2 dstring] *
ket(sandwich)[d2; Dntop Detop Dstop Dwtop] *
E_north[χN Dntop Dnbot; χNE]

return Vn, Vo

Check warning on line 104 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L104

Added line #L104 was not covered by tests
end

function end_correlator_numerator(

Check warning on line 107 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L107

Added line #L107 was not covered by tests
j::CartesianIndex{2},
V,
above::InfinitePEPS,
O::MPOTensor,
below::InfinitePEPS,
env::CTMRGEnv,
)
r, c = Tuple(j)
E_north = env.edges[NORTH, _prev(r, end), mod1(c, end)]
E_east = env.edges[EAST, mod1(r, end), _next(c, end)]
E_south = env.edges[SOUTH, _next(r, end), mod1(c, end)]
C_northeast = env.corners[NORTHEAST, _prev(r, end), _next(c, end)]
C_southeast = env.corners[SOUTHEAST, _next(r, end), _next(c, end)]
sandwich = (above[mod1(r, end), mod1(c, end)], below[mod1(r, end), mod1(c, end)])

Check warning on line 121 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L115-L121

Added lines #L115 - L121 were not covered by tests

return @autoopt @tensor contractcheck = true V[χSW DWt dstring DWb; χNW] *

Check warning on line 123 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L123

Added line #L123 was not covered by tests
E_south[χSSE DSt DSb; χSW] *
E_east[χNEE DEt DEb; χSEE] *
E_north[χNW DNt DNb; χNNE] *
C_northeast[χNNE; χNEE] *
C_southeast[χSEE; χSSE] *
conj(bra(sandwich)[db; DNb DEb DSb DWb]) *
ket(sandwich)[dt; DNt DEt DSt DWt] *
removeunit(O, 4)[dstring db; dt]
end

function end_correlator_denominator(j::CartesianIndex{2}, V, env::CTMRGEnv)
r, c = Tuple(j)
C_northeast = env.corners[NORTHEAST, _prev(r, end), _next(c, end)]
E_east = env.edges[EAST, mod1(r, end), _next(c, end)]
C_southeast = env.corners[SOUTHEAST, _next(r, end), _next(c, end)]

Check warning on line 138 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L134-L138

Added lines #L134 - L138 were not covered by tests

return @autoopt @tensor V[χS DEt DEb; χN] *

Check warning on line 140 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L140

Added line #L140 was not covered by tests
C_northeast[χN; χNE] *
E_east[χNE DEt DEb; χSE] *
C_southeast[χSE; χS]
end

function correlator_vertical(

Check warning on line 146 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L146

Added line #L146 was not covered by tests
bra::InfinitePEPS,
O,
i::CartesianIndex{2},
js::AbstractVector{CartesianIndex{2}},
ket::InfinitePEPS,
env::CTMRGEnv,
)
rotated_bra = rotl90(bra)
rotated_ket = bra === ket ? rotated_bra : rotl90(ket)

Check warning on line 155 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L154-L155

Added lines #L154 - L155 were not covered by tests

rotated_i = rotl90(i)
rotated_j = map(rotl90, js)

Check warning on line 158 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L157-L158

Added lines #L157 - L158 were not covered by tests

return correlator_horizontal(

Check warning on line 160 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L160

Added line #L160 was not covered by tests
rotated_bra, O, rotated_i, rotated_j, rotated_ket, rotl90(env)
)
end

const CoordCollection{N} = Union{AbstractVector{CartesianIndex{N}},CartesianIndices{N}}

function MPSKit.correlator(

Check warning on line 167 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L167

Added line #L167 was not covered by tests
bra::InfinitePEPS,
O,
i::CartesianIndex{2},
js::CoordCollection{2},
ket::InfinitePEPS,
env::CTMRGEnv,
)
js = vec(js) # map CartesianIndices to actual Vector instead of Matrix

Check warning on line 175 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L175

Added line #L175 was not covered by tests

if all(==(i[1]) ∘ first ∘ Tuple, js)
return correlator_horizontal(bra, O, i, js, ket, env)
elseif all(==(i[2]) ∘ last ∘ Tuple, js)
return correlator_vertical(bra, O, i, js, ket, env)

Check warning on line 180 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L177-L180

Added lines #L177 - L180 were not covered by tests
else
error("Only horizontal or vertical correlators are implemented")

Check warning on line 182 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L182

Added line #L182 was not covered by tests
end
end

function MPSKit.correlator(

Check warning on line 186 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L186

Added line #L186 was not covered by tests
bra::InfinitePEPS,
O,
i::CartesianIndex{2},
j::CartesianIndex{2},
ket::InfinitePEPS,
env::CTMRGEnv,
)
return only(correlator(bra, O, i, j:j, ket, env))

Check warning on line 194 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L194

Added line #L194 was not covered by tests
end

function MPSKit.correlator(state::InfinitePEPS, O, i::CartesianIndex{2}, j, env::CTMRGEnv)
return MPSKit.correlator(state, O, i, j, state, env)

Check warning on line 198 in src/algorithms/correlators.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/correlators.jl#L197-L198

Added lines #L197 - L198 were not covered by tests
end
58 changes: 54 additions & 4 deletions test/examples/tf_ising.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,62 @@ peps, env, E, = fixedpoint(H, peps₀, env₀; tol=gradtol)

# compute magnetization
σx = TensorMap(scalartype(peps₀)[0 1; 1 0], ℂ^2, ℂ^2)
M = LocalOperator(physicalspace(H), (CartesianIndex(1, 1),) => σx)
magn = expectation_value(peps, M, env)
σz = TensorMap(scalartype(peps₀)[1 0; 0 -1], ℂ^2, ℂ^2)
Mx = LocalOperator(physicalspace(H), (CartesianIndex(1, 1),) => σx)
Mz = LocalOperator(physicalspace(H), (CartesianIndex(1, 1),) => σz)
magnx = expectation_value(peps, Mx, env)
magnz = expectation_value(peps, Mz, env)

@test E ≈ e atol = 1e-2
@test imag(magn) ≈ 0 atol = 1e-6
@test abs(magn) ≈ mˣ atol = 5e-2
@test imag(magnx) ≈ 0 atol = 1e-6
@test abs(magnx) ≈ mˣ atol = 5e-2

# compute connected correlation functions
corrh =
correlator(
peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(1, 2):CartesianIndex(1, 21), env
) .- magnz^2
corrv =
correlator(
peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(2, 1):CartesianIndex(21, 1), env
) .- magnz^2

@test corrh[end] ≈ 0.0 atol = 1e-5
@test 1 / log(corrh[18] / corrh[19]) ≈ ξ_h[1] atol = 2e-2 # test correlation length far away from short-range effects
@test corrv[end] ≈ 0.0 atol = 1e-5
@test 1 / log(corrv[18] / corrv[19]) ≈ ξ_v[1] atol = 3e-2 # test correlation length far away from short-range effects
@test corrv ≈ corrh rtol = 1e-2

# compute weird geometries
corrh_2 =
correlator(
peps,
σz ⊗ σz,
CartesianIndex(3, 2),
CartesianIndex(3, 3):CartesianIndex(1, 2):CartesianIndex(3, 7),
env,
) .- magnz^2
@test corrh_2 ≈ corrh[1:2:5]
corrv_2 =
correlator(
peps,
σz ⊗ σz,
CartesianIndex(2, 3),
CartesianIndex(3, 3):CartesianIndex(2, 1):CartesianIndex(7, 3),
env,
) .- magnz^2
@test corrv_2 ≈ corrv[1:2:5]

# Change from specific values and distances to a range
corrh_int =
correlator(peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(1, 21), env) - magnz^2
corrv_int =
correlator(peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(21, 1), env) - magnz^2

@test corrh_int ≈ corrh[20]
@test corrv_int ≈ corrv[20]

@test_broken correlator(peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(2, 2), env)

# find fixedpoint in polarized phase and compute correlations lengths
H_polar = transverse_field_ising(InfiniteSquare(); g=4.5)
Expand Down